faster path for common size
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@23 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c
index c417616..a156d06 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -91,6 +91,7 @@
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 @@
}
}
+ /* 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 @@
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 @@
return 0;
}
+