_set_arcs_l() replaced by _set_arcs() fror OBJECT IDENTIFIER and RELATIVE-OID


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@33 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c
index a156d06..5bb045a 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -118,6 +118,12 @@
 			 * type, there is still possible to fit it when there
 			 * are few unused high bits in the arc value
 			 * representaion.
+			 * 
+			 * Moreover, there is a possibility that the
+			 * number could actually fit the arc space, given
+			 * that add is negative, but we don't handle
+			 * such "temporary lack of precision" situation here.
+			 * May be considered as a bug.
 			 */
 			uint8_t mask = (0xff << (7-(arclen - rvsize))) & 0x7f;
 			if((*arcbuf & mask)) {
@@ -156,7 +162,7 @@
 		inc = +1;	/* Big endian is known [at compile time] */
 
 	{
-		unsigned int bits;	/* typically no more than 3-4 bits */
+		int bits;	/* typically no more than 3-4 bits */
 
 		/* Clear the high unused bits */
 		for(bits = rvsize - arclen;
@@ -287,7 +293,7 @@
 	int add = 0;
 	int i;
 
-	if(!oid || !oid->buf) {
+	if(!oid || !oid->buf || (arc_slots && arc_type_size <= 1)) {
 		errno = EINVAL;
 		return -1;
 	}
@@ -335,37 +341,158 @@
 	return num_arcs;
 }
 
+
+/*
+ * Save the single value as an object identifier arc.
+ */
+inline int
+OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, void *arcval, unsigned int arcval_size, int prepared_order) {
+	/*
+	 * The following conditions must hold:
+	 * assert(arcval);
+	 * assert(arcval_size > 0);
+	 * assert(arcbuf);
+	 */
+#ifdef	WORDS_BIGENDIAN
+	const unsigned isLittleEndian = 0;
+#else
+	unsigned LE = 1;
+	unsigned isLittleEndian = *(char *)&LE;
+#endif
+	uint8_t buffer[arcval_size];
+	uint8_t *tp, *tend;
+	unsigned int cache;
+	uint8_t *bp = arcbuf;
+	int bits;
+
+	if(isLittleEndian && !prepared_order) {
+		uint8_t *a = arcval + arcval_size - 1;
+		uint8_t *aend = arcval;
+		uint8_t *msb = buffer + arcval_size - 1;
+		for(tp = buffer; a >= aend; tp++, a--)
+			if((*tp = *a) && (tp < msb))
+				msb = tp;
+		tend = &buffer[arcval_size];
+		tp = msb;	/* Most significant non-zero byte */
+	} else {
+		/* Look for most significant non-zero byte */
+		tend = arcval + arcval_size;
+		for(tp = arcval; tp < tend - 1; tp++)
+			if(*tp) break;
+	}
+
+	/*
+	 * Split the value in 7-bits chunks.
+	 */
+	bits = ((tend - tp) * CHAR_BIT) % 7;
+	if(bits) {
+		cache = *tp >> (CHAR_BIT - bits);
+		if(cache) {
+			*bp++ = cache | 0x80;
+			cache = *tp++;
+			bits = CHAR_BIT - bits;
+		} else {
+			bits = -bits;
+		}
+	} else {
+		cache = 0;
+	}
+	for(; tp < tend; tp++) {
+		cache = (cache << CHAR_BIT) + *tp;
+		bits += CHAR_BIT;
+		while(bits >= 7) {
+			bits -= 7;
+			*bp++ = 0x80 | (cache >> bits);
+		}
+	}
+	if(bits) *bp++ = cache;
+	bp[-1] &= 0x7f;	/* Clear the last bit */
+
+	return bp - arcbuf;
+}
+
 int
-OBJECT_IDENTIFIER_set_arcs_l(OBJECT_IDENTIFIER_t *oid, unsigned long *arcs, unsigned int arc_slots) {
+OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *oid, void *arcs, unsigned int arc_type_size, unsigned int arc_slots) {
 	uint8_t *buf;
 	uint8_t *bp;
-	unsigned long long first_value;
+	unsigned LE = 1;	/* Little endian (x86) */
+	unsigned isLittleEndian = *((char *)&LE);
+	unsigned int arc0;
+	unsigned int arc1;
+	unsigned size;
 	unsigned i;
-	int size;
 
-	if(oid == NULL || arcs == NULL || arc_slots < 2) {
+	if(!oid || !arcs || arc_type_size < 1 || arc_slots < 2) {
 		errno = EINVAL;
 		return -1;
 	}
 
-	if(arcs[0] <= 1) {
-		if(arcs[1] >= 39) {
+	switch(arc_type_size) {
+	case sizeof(char):
+		arc0 = ((unsigned char *)arcs)[0];
+		arc1 = ((unsigned char *)arcs)[1];
+		break;
+	case sizeof(short):
+		arc0 = ((unsigned short *)arcs)[0];
+		arc1 = ((unsigned short *)arcs)[1];
+		break;
+	case sizeof(int):
+		arc0 = ((unsigned int *)arcs)[0];
+		arc1 = ((unsigned int *)arcs)[1];
+		break;
+	default:
+		arc1 = arc0 = 0;
+		if(isLittleEndian) {	/* Little endian (x86) */
+			unsigned char *ps, *pe;
+			/* If more significant bytes are present,
+			 * make them > 255 quick */
+			for(ps = arcs + 1, pe = ps+arc_type_size; ps < pe; ps++)
+				arc0 |= *ps, arc1 |= *(ps + arc_type_size);
+			arc0 <<= CHAR_BIT, arc1 <<= CHAR_BIT;
+			arc0 = *((unsigned char *)arcs + 0);
+			arc1 = *((unsigned char *)arcs + arc_type_size);
+		} else {
+			unsigned char *ps, *pe;
+			/* If more significant bytes are present,
+			 * make them > 255 quick */
+			for(ps = arcs, pe = ps+arc_type_size - 1; ps < pe; ps++)
+				arc0 |= *ps, arc1 |= *(ps + arc_type_size);
+			arc0 = *((unsigned char *)arcs + arc_type_size - 1);
+			arc1 = *((unsigned char *)arcs +(arc_type_size<< 1)-1);
+		}
+	}
+
+	/*
+	 * The previous chapter left us with the first and the second arcs.
+	 * The values are not precise (that is, they are valid only if
+	 * they're less than 255), but OK for the purposes of making
+	 * the sanity test below.
+	 */
+	if(arc0 <= 1) {
+		if(arc1 >= 39) {
 			/* 8.19.4: At most 39 subsequent values (including 0) */
 			errno = ERANGE;
 			return -1;
 		}
-	} else if(arcs[0] > 2) {
+	} else if(arc0 > 2) {
 		/* 8.19.4: Only three values are allocated from the root node */
 		errno = ERANGE;
 		return -1;
 	}
-
-	first_value = arcs[0] * 40 + arcs[1];
+	/*
+	 * After above tests it is known that the value of arc0 is completely
+	 * trustworthy (0..2). However, the arc1's value is still meaningless.
+	 */
 
 	/*
 	 * Roughly estimate the maximum size necessary to encode these arcs.
+	 * This estimation implicitly takes in account the following facts,
+	 * that cancel each other:
+	 * 	* the first two arcs are encoded in a single value.
+	 * 	* the first value may require more space (+1 byte)
+	 * 	* the value of the first arc which is in range (0..2)
 	 */
-	size = ((sizeof(arcs[0]) + 1) * 8 / 7) * arc_slots;
+	size = ((arc_type_size * CHAR_BIT + 6) / 7) * arc_slots;
 	bp = buf = MALLOC(size + 1);
 	if(!buf) {
 		/* ENOMEM */
@@ -373,67 +500,60 @@
 	}
 
 	/*
-	 * Encode the arcs and refine the encoding size.
+	 * Encode the first two arcs.
+	 * These require special treatment.
 	 */
-	size = 0;
-
 	{
-		uint8_t tbuf[sizeof(first_value) * 2];
-		uint8_t *tp = tbuf;
-		int arc_len = 0;
-		int add = 0;
+		uint8_t first_value[1 + arc_type_size];	/* of two arcs */
+		uint8_t *fv = first_value;
+		uint8_t *tp;
 
-		for(; first_value; first_value >>= 7) {
-			unsigned int b7 = first_value & 0x7f;
-			*tp++ = 0x80 | b7;
-			add++;
-			if(b7) { arc_len += add; add = 0; }
-		}
-
-		if(arc_len) {
-			tp = &tbuf[arc_len - 1];
-			/* The last octet does not have bit 8 set. */
-			*tbuf &= 0x7f;
-			for(; tp >= tbuf; tp--)
-				*bp++ = *tp;
-			size += arc_len;
+		/*
+		 * Simulate first_value = arc0 * 40 + arc1;
+		 */
+		/* Copy the second (1'st) arcs[1] into the first_value */
+		*fv++ = 0;
+		(char *)arcs += arc_type_size;
+		if(isLittleEndian) {
+			uint8_t *aend = arcs - 1;
+			uint8_t *a1 = arcs + arc_type_size - 1;
+			for(; a1 > aend; fv++, a1--) *fv = *a1;
 		} else {
-			*bp++ = 0;
-			size++;
+			uint8_t *a1 = arcs;
+			uint8_t *aend = a1 + arc_type_size;
+			for(; a1 < aend; fv++, a1++) *fv = *a1;
 		}
+		/* Increase the first_value by arc0 */
+		arc0 *= 40;	/* (0..80) */
+		for(tp = first_value + arc_type_size; tp >= first_value; tp--) {
+			unsigned int v = *tp;
+			v += arc0;
+			*tp = v;
+			if(v >= (1 << CHAR_BIT)) arc0 = v >> CHAR_BIT;
+			else break;
+		}
+
+		assert(tp >= first_value);
+
+		bp += OBJECT_IDENTIFIER_set_single_arc(bp, first_value,
+			fv - first_value, 1);
+ 	}
+
+	/*
+	 * Save the rest of arcs.
+	 */
+	for((char *)arcs += arc_type_size, i = 2;
+			i < arc_slots; i++, (char *)arcs += arc_type_size) {
+		bp += OBJECT_IDENTIFIER_set_single_arc(bp,
+			arcs, arc_type_size, 0);
 	}
 
-	for(i = 2; i < arc_slots; i++) {
-		unsigned long value = arcs[i];
-		uint8_t tbuf[sizeof(value) * 2];  /* Conservatively sized */
-		uint8_t *tp = tbuf;
-		int arc_len = 0;
-		int add = 0;
-
-		for(; value; value >>= 7) {
-			unsigned int b7 = value & 0x7F;
-			*tp++ = 0x80 | b7;
-			add++;
-			if(b7) { arc_len += add; add = 0; }
-		}
-
-		if(arc_len) {
-			tp = &tbuf[arc_len - 1];
-			/* The last octet does not have bit 8 set. */
-			*tbuf &= 0x7f;
-			for(; tp >= tbuf; tp--)
-				*bp++ = *tp;
-			size += arc_len;
-		} else {
-			*bp++ = 0;
-			size++;
-		}
-	}
+	assert((bp - buf) <= size);
 
 	/*
 	 * Replace buffer.
 	 */
-	oid->size = size;
+	oid->size = bp - buf;
 	bp = oid->buf;
 	oid->buf = buf;
 	if(bp) FREEMEM(bp);
diff --git a/skeletons/OBJECT_IDENTIFIER.h b/skeletons/OBJECT_IDENTIFIER.h
index 77b07de..8d43c99 100644
--- a/skeletons/OBJECT_IDENTIFIER.h
+++ b/skeletons/OBJECT_IDENTIFIER.h
@@ -68,7 +68,9 @@
  * >=0:		Number of arcs contained in the OBJECT IDENTIFIER
  */
 int OBJECT_IDENTIFIER_get_arcs(OBJECT_IDENTIFIER_t *_oid,
-	void *_arcs, unsigned int _arc_type_size, unsigned int _arc_slots);
+	void *_arcs,			/* i.e., unsigned int arcs[N] */
+	unsigned int _arc_type_size,	/* i.e., sizeof(arcs[0]) */
+	unsigned int _arc_slots		/* i.e., N */);
 
 /*
  * This functions initializes the OBJECT IDENTIFIER object with
@@ -80,15 +82,18 @@
  * -1/ENOMEM:	Memory allocation failed
  * 0:		The object was initialized with new arcs.
  */
-int OBJECT_IDENTIFIER_set_arcs_l(OBJECT_IDENTIFIER_t *_oid,
-	unsigned long *_arcs, unsigned int _arc_slots);
+int OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *_oid,
+	void *_arcs,			/* i.e., unsigned int arcs[N] */
+	unsigned int _arc_type_size,	/* i.e., sizeof(arcs[0]) */
+	unsigned int _arc_slots		/* i.e., N */);
 
 /*
  * Internal functions.
+ * Used by RELATIVE-OID implementation in particular.
  */
 int OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen,
 	signed int add, void *value, unsigned int value_size);
-int OBJECT_IDENTIFIER_get_single_arc_l(uint8_t *arcbuf, unsigned int arclen,
-	signed int add, unsigned long *value);
+int OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf,
+	void *arcval, unsigned int arcval_size, int _prepared_order);
 
 #endif	/* _OBJECT_IDENTIFIER_H_ */
diff --git a/skeletons/RELATIVE-OID.c b/skeletons/RELATIVE-OID.c
index 37f557d..b5c346a 100644
--- a/skeletons/RELATIVE-OID.c
+++ b/skeletons/RELATIVE-OID.c
@@ -3,6 +3,7 @@
  * Redistribution and modifications are permitted subject to BSD license.
  */
 #include <RELATIVE-OID.h>
+#include <limits.h>	/* for CHAR_BIT */
 #include <assert.h>
 #include <errno.h>
 
@@ -96,13 +97,13 @@
 }
 
 int
-RELATIVE_OID_set_arcs_l(RELATIVE_OID_t *roid, unsigned long *arcs, int arcs_slots) {
+RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_size, unsigned int arcs_slots) {
 	uint8_t *buf;
 	uint8_t *bp;
 	int size;
 	int i;
 
-	if(roid == NULL || arcs == NULL || arcs_slots < 0) {
+	if(roid == NULL || arcs == NULL || arc_type_size < 1) {
 		errno = EINVAL;
 		return -1;
 	}
@@ -110,7 +111,7 @@
 	/*
 	 * Roughly estimate the maximum size necessary to encode these arcs.
 	 */
-	size = ((sizeof(arcs[0]) + 1) * 8 / 7) * arcs_slots;
+	size = ((arc_type_size * CHAR_BIT + 6) / 7) * arcs_slots;
 	bp = buf = MALLOC(size + 1);
 	if(!buf) {
 		/* ENOMEM */
@@ -118,45 +119,23 @@
 	}
 
 	/*
-	 * Encode the arcs and refine the encoding size.
+	 * Encode the arcs.
 	 */
-	size = 0;
-	for(i = 0; i < arcs_slots; i++) {
-		unsigned long value = arcs[i];
-		uint8_t tbuf[sizeof(value) * 2];  /* Conservatively sized */
-		uint8_t *tp = tbuf;
-		int arc_len = 0;
-		int add;
-
-		for(add = 1; value; value >>= 7, add++) {
-			unsigned int b7 = value & 0x7F;
-			*tp++ = 0x80 | b7;
-			if(b7) {
-				arc_len += add;
-				add = 0;
-			}
-		}
-
-		if(arc_len) {
-			tp = &tbuf[arc_len - 1];
-			/* The last octet does not have bit 8 set. */
-			*tbuf &= 0x7f;
-			for(; tp >= tbuf; tp--)
-				*bp++ = *tp;
-			size += arc_len;
-		} else {
-			*bp++ = 0;
-			size++;
-		}
+	for(i = 0; i < arcs_slots; i++, (char *)arcs += arc_type_size) {
+		bp += OBJECT_IDENTIFIER_set_single_arc(bp,
+			arcs, arc_type_size, 0);
 	}
 
+	assert((bp - buf) <= size);
+
 	/*
 	 * Replace buffer.
 	 */
-	roid->size = size;
+	roid->size = bp - buf;
 	bp = roid->buf;
 	roid->buf = buf;
 	if(bp) FREEMEM(bp);
 
 	return 0;
 }
+
diff --git a/skeletons/RELATIVE-OID.h b/skeletons/RELATIVE-OID.h
index 926aca3..1dafb62 100644
--- a/skeletons/RELATIVE-OID.h
+++ b/skeletons/RELATIVE-OID.h
@@ -19,12 +19,12 @@
  * Some handy conversion routines *
  **********************************/
 
-/* See OBJECT_IDENTIFIER_set_arcs_l() function in OBJECT_IDENTIFIER.h */
-int RELATIVE_OID_set_arcs_l(RELATIVE_OID_t *_roid,
-	unsigned long *arcs, int arcs_slots);
-
 /* See OBJECT_IDENTIFIER_get_arcs() function in OBJECT_IDENTIFIER.h */
 int RELATIVE_OID_get_arcs(RELATIVE_OID_t *_roid,
 	void *arcs, unsigned int arc_type_size, unsigned int arc_slots);
 
+/* See OBJECT_IDENTIFIER_set_arcs() function in OBJECT_IDENTIFIER.h */
+int RELATIVE_OID_set_arcs(RELATIVE_OID_t *_roid,
+	void *arcs, unsigned int arc_type_size, unsigned int arcs_slots);
+
 #endif	/* _RELATIVE_OID_H_ */
diff --git a/skeletons/tests/check-OIDs.c b/skeletons/tests/check-OIDs.c
index cea630e..97ed33f 100644
--- a/skeletons/tests/check-OIDs.c
+++ b/skeletons/tests/check-OIDs.c
@@ -1,5 +1,5 @@
-#include "../RELATIVE-OID.c"
 #include "../OBJECT_IDENTIFIER.c"
+#include "../RELATIVE-OID.c"
 #include "../INTEGER.c"
 #include "../ber_decoder.c"
 #include "../ber_tlv_length.c"
@@ -42,6 +42,7 @@
 	OBJECT_IDENTIFIER_print(&asn1_DEF_OBJECT_IDENTIFIER, oid, 0, _print, 0);
 	printf("\n");
 
+	memset(arcs, 'A', sizeof(arcs));
 	alen = OBJECT_IDENTIFIER_get_arcs(oid,
 		arcs, sizeof(arcs[0]), sizeof(arcs)/sizeof(arcs[0]));
 	assert(alen > 0);
@@ -85,6 +86,7 @@
 	RELATIVE_OID_print(&asn1_DEF_RELATIVE_OID, oid, 0, _print, 0);
 	printf("\n");
 
+	memset(arcs, 'A', sizeof(arcs));
 	alen = RELATIVE_OID_get_arcs(oid,
 		arcs, sizeof(arcs[0]), sizeof(arcs)/sizeof(arcs[0]));
 	assert(alen > 0);
@@ -113,21 +115,23 @@
 	int ret;
 	int i;
 
-	printf("Encoding {");
+	printf("Encoding (R) {");
 	for(i = 0; i < acount; i++) {
 		printf(" %u", arcs[i]);
 	}
 	printf(" }\n");
 
-	ret = RELATIVE_OID_set_arcs_l(&oid, (unsigned long *)arcs, acount);
+	ret = RELATIVE_OID_set_arcs(&oid, arcs, sizeof(arcs[0]), acount);
 	assert(ret == 0);
 
+	memset(tmp_arcs, 'A', sizeof(tmp_arcs));
 	alen = RELATIVE_OID_get_arcs(&oid, tmp_arcs,
 		sizeof(tmp_arcs[0]), tmp_alen);
 	assert(alen >= 0);
-	assert(alen < tmp_alen);
+	assert(alen <= tmp_alen);
+	assert(alen == acount);
 
-	printf("Encoded {");
+	printf("Encoded  (R) {");
 	for(i = 0; i < alen; i++) {
 		printf(" %lu", tmp_arcs[i]);
 		assert((unsigned long)arcs[i] == tmp_arcs[i]);
@@ -148,26 +152,28 @@
 	int ret;
 	int i;
 
-	printf("Encoding {");
+	printf("Encoding (O) {");
 	for(i = 0; i < acount; i++) {
 		printf(" %u", arcs[i]);
 	}
 	printf(" }\n");
 
-	ret = OBJECT_IDENTIFIER_set_arcs_l(&oid, (unsigned long *)arcs, acount);
+	ret = OBJECT_IDENTIFIER_set_arcs(&oid, arcs, sizeof(arcs[0]), acount);
 	assert(ret == 0);
 
+	memset(tmp_arcs, 'A', sizeof(tmp_arcs));
 	alen = OBJECT_IDENTIFIER_get_arcs(&oid,
 		tmp_arcs, sizeof(tmp_arcs[0]), tmp_alen);
 	assert(alen >= 0);
-	assert(alen < tmp_alen);
+	assert(alen <= tmp_alen);
+	assert(alen == acount);
 
-	printf("Encoded {");
+	printf("Encoded  (O) { ");
 	for(i = 0; i < alen; i++) {
-		printf(" %lu", tmp_arcs[i]);
+		printf("%lu ", tmp_arcs[i]); fflush(stdout);
 		assert((unsigned long)arcs[i] == tmp_arcs[i]);
 	}
-	printf(" }\n");
+	printf("}\n");
 }
 
 static int
@@ -224,6 +230,8 @@
 
 int
 main() {
+	int i;
+
 	/* {joint-iso-itu-t 230 3} */
 	uint8_t buf1[] = {
 		0x06,	/* OBJECT IDENTIFIER */
@@ -240,34 +248,75 @@
 	};
 	int buf2_check[] = { 8571, 3, 2 };
 
-	int buf3_check[] = { 0 };
-	int buf4_check[] = { 1 };
-	int buf5_check[] = { 80, 40 };
-	int buf6_check[] = { 127 };
-	int buf7_check[] = { 128 };
-	int buf8_check[] = { 65535, 65536 };
-	int buf9_check[] = { 100000, 0x20000, 1234, 256, 127, 128 };
-	int buf10_check[] = { 0, 0xffffffff, 0xff00ff00, 0 };
-	int buf11_check[] = { 0, 1, 2 };
-	int buf12_check[] = { 1, 38, 3 };
-	int buf13_check[] = { 0, 0, 0xf000 };
+	/* {joint-iso-itu-t 42 } */
+	uint8_t buf3[] = {
+		0x06,	/* OBJECT IDENTIFIER */
+		0x01,	/* Length */
+		0x7A
+	};
+	int buf3_check[] = { 2, 42 };
+
+	/* {joint-iso-itu-t 25957 } */
+	uint8_t buf4[] = {
+		0x06,	/* OBJECT IDENTIFIER */
+		0x03,	/* Length */
+		0x81, 0x80 + 0x4B, 0x35
+	};
+	int buf4_check[] = { 2, 25957 };
+
+	int buf5_check[] = { 0 };
+	int buf6_check[] = { 1 };
+	int buf7_check[] = { 80, 40 };
+	int buf8_check[] = { 127 };
+	int buf9_check[] = { 128 };
+	int buf10_check[] = { 65535, 65536 };
+	int buf11_check[] = { 100000, 0x20000, 1234, 256, 127, 128 };
+	int buf12_check[] = { 0, 0xffffffff, 0xff00ff00, 0 };
+	int buf13_check[] = { 0, 1, 2 };
+	int buf14_check[] = { 1, 38, 3 };
+	int buf15_check[] = { 0, 0, 0xf000 };
+	int buf16_check[] = { 0, 0, 0, 1, 0 };
+	int buf17_check[] = { 2, 0xffffffAf, 0xff00ff00, 0 };
 
 
 	CHECK_OID(1);	/* buf1, buf1_check */
 	CHECK_ROID(2);	/* buf2, buf2_check */
+	CHECK_OID(3);	/* buf3, buf3_check */
+	CHECK_OID(4);	/* buf4, buf4_check */
 
-	CHECK_REGEN(3);	/* Regenerate RELATIVE-OID */
-	CHECK_REGEN(4);
-	CHECK_REGEN(5);
+	CHECK_REGEN(5);	/* Regenerate RELATIVE-OID */
 	CHECK_REGEN(6);
 	CHECK_REGEN(7);
 	CHECK_REGEN(8);
 	CHECK_REGEN(9);
 	CHECK_REGEN(10);
+	CHECK_REGEN(11);
+	CHECK_REGEN(12);
+	CHECK_REGEN(13);
+	CHECK_REGEN(14);
+	CHECK_REGEN(15);
+	CHECK_REGEN(16);
+	CHECK_REGEN(17);
 	CHECK_REGEN_OID(1);	/* Regenerate OBJECT IDENTIFIER */
-	CHECK_REGEN_OID(11);
-	CHECK_REGEN_OID(12);
+	CHECK_REGEN_OID(3);	/* Regenerate OBJECT IDENTIFIER */
+	CHECK_REGEN_OID(4);	/* Regenerate OBJECT IDENTIFIER */
 	CHECK_REGEN_OID(13);
+	CHECK_REGEN_OID(14);
+	CHECK_REGEN_OID(15);
+	CHECK_REGEN_OID(16);
+	CHECK_REGEN_OID(17);
+
+	for(i = 0; i < 100000; i++) {
+		int bufA_check[3] = { 2, i, rand() };
+		int bufB_check[2] = { rand(), i * 121 };
+		CHECK_REGEN(A);
+		CHECK_REGEN_OID(A);
+		CHECK_REGEN(B);
+		if(i > 100) i++;
+		if(i > 500) i++;
+		if(i > 1000) i += 3;
+		if(i > 5000) i += 151;
+	}
 
 	if(getenv("CHECK_SPEED")) {
 		/* Useful for developers only */