From c4c6196c40740e67b83aa58708a8e374963eba70 Mon Sep 17 00:00:00 2001
From: Lev Walkin <vlm@lionet.info>
Date: Mon, 14 Jun 2004 08:17:27 +0000
Subject: [PATCH] faster path for common size

---
 skeletons/OBJECT_IDENTIFIER.c | 30 ++++++++++++++++++++++++------
 skeletons/tests/check-OIDs.c  |  5 ++++-
 2 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c
index c4176160..a156d060 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -91,6 +91,7 @@ OBJECT_IDENTIFIER_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
 	return 0;
 }
 
+
 int
 OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbuf, unsigned int rvsize) {
 	unsigned LE = 1;	/* Little endian (x86) */
@@ -130,23 +131,39 @@ OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed in
 		}
 	}
 
+	/* Faster path for common size */
+	if(rvsize == (CHAR_BIT * sizeof(unsigned long))) {
+		unsigned long accum;
+		/* Gather all bits into the accumulator */
+		for(accum = cache; arcbuf < arcend; arcbuf++)
+			accum = (accum << 7) | (*arcbuf & ~0x80);
+		if(accum < (unsigned)-add) {
+			errno = ERANGE;	/* Overflow */
+			return -1;
+		}
+		*(unsigned long *)rvbuf = accum + add;
+		return 0;
+	}
+
 #ifndef	WORDS_BIGENDIAN
 	if(*(unsigned char *)&LE) {	/* Little endian (x86) */
 		/* "Convert" to big endian */
-		rvbuf += rvsize / CHAR_BIT;
+		rvbuf += rvsize / CHAR_BIT - 1;
+		((unsigned char *)rvstart)--;
 		inc = -1;	/* Descending */
-	} else {
-		inc = +1;	/* Ascending */
-	}
+	} else
 #endif	/* !WORDS_BIGENDIAN */
+		inc = +1;	/* Big endian is known [at compile time] */
 
-	{	/* Native big endian (Sparc, PPC) */
+	{
 		unsigned int bits;	/* typically no more than 3-4 bits */
+
 		/* Clear the high unused bits */
 		for(bits = rvsize - arclen;
 			bits > CHAR_BIT;
 				rvbuf += inc, bits -= CHAR_BIT)
 				*(unsigned char *)rvbuf = 0;
+
 		/* Fill the body of a value */
 		for(; arcbuf < arcend; arcbuf++) {
 			cache = (cache << 7) | (*arcbuf & 0x7f);
@@ -323,8 +340,8 @@ OBJECT_IDENTIFIER_set_arcs_l(OBJECT_IDENTIFIER_t *oid, unsigned long *arcs, unsi
 	uint8_t *buf;
 	uint8_t *bp;
 	unsigned long long first_value;
+	unsigned i;
 	int size;
-	int i;
 
 	if(oid == NULL || arcs == NULL || arc_slots < 2) {
 		errno = EINVAL;
@@ -423,3 +440,4 @@ OBJECT_IDENTIFIER_set_arcs_l(OBJECT_IDENTIFIER_t *oid, unsigned long *arcs, unsi
 
 	return 0;
 }
+
diff --git a/skeletons/tests/check-OIDs.c b/skeletons/tests/check-OIDs.c
index 472e5536..cea630e0 100644
--- a/skeletons/tests/check-OIDs.c
+++ b/skeletons/tests/check-OIDs.c
@@ -269,7 +269,10 @@ main() {
 	CHECK_REGEN_OID(12);
 	CHECK_REGEN_OID(13);
 
-	check_speed();
+	if(getenv("CHECK_SPEED")) {
+		/* Useful for developers only */
+		check_speed();
+	}
 
 	return 0;
 }
-- 
GitLab