expanding range: <= 31 bits now


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@1016 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/skeletons/per_support.c b/skeletons/per_support.c
index 506ca78..9b048f0 100644
--- a/skeletons/per_support.c
+++ b/skeletons/per_support.c
@@ -6,7 +6,7 @@
 #include <per_support.h>
 
 /*
- * Extract a small number of bits (<= 24) from the specified PER data pointer.
+ * Extract a small number of bits (<= 31) from the specified PER data pointer.
  */
 int32_t
 per_get_few_bits(asn_per_data_t *pd, int nbits) {
@@ -16,8 +16,6 @@
 
 	if(nbits < 0 || pd->nboff + nbits > pd->nbits)
 		return -1;
-	if(nbits == 0)
-		return 0;
 
 	/*
 	 * Normalize position indicator.
@@ -34,7 +32,7 @@
 	 * Extract specified number of bits.
 	 */
 	if(off <= 8)
-		accum = (buf[0]) >> (8 - off);
+		accum = nbits ? (buf[0]) >> (8 - off) : 0;
 	else if(off <= 16)
 		accum = ((buf[0] << 8) + buf[1]) >> (16 - off);
 	else if(off <= 24)
@@ -42,12 +40,18 @@
 	else if(off <= 31)
 		accum = ((buf[0] << 24) + (buf[1] << 16)
 			+ (buf[2] << 8) + (buf[3])) >> (32 - off);
-	else {
+	else if(nbits <= 31) {
+		asn_per_data_t tpd = *pd;
+		/* Here are we with our 31-bits limit plus 1..7 bits offset. */
+		tpd.nboff -= nbits;
+		accum  = per_get_few_bits(&tpd, nbits - 24) << 24;
+		accum |= per_get_few_bits(&tpd, 24);
+	} else {
 		pd->nboff -= nbits;	/* Oops, revert back */
 		return -1;
 	}
 
-	return (accum & ((1 << nbits) - 1));
+	return (accum & (((uint32_t)1 << nbits) - 1));
 }
 
 /*
diff --git a/skeletons/per_support.h b/skeletons/per_support.h
index 25c9256..a8f15fb 100644
--- a/skeletons/per_support.h
+++ b/skeletons/per_support.h
@@ -21,7 +21,7 @@
 } asn_per_data_t;
 
 /*
- * Extract a small number of bits (<= 24) from the specified PER data pointer.
+ * Extract a small number of bits (<= 31) from the specified PER data pointer.
  * This function returns -1 if the specified number of bits could not be
  * extracted due to EOD or other conditions.
  */
diff --git a/skeletons/tests/check-PER.c b/skeletons/tests/check-PER.c
index 94f5fe4..5fcb1ae 100644
--- a/skeletons/tests/check-PER.c
+++ b/skeletons/tests/check-PER.c
@@ -14,22 +14,27 @@
 
 	z = per_get_few_bits(&pos, 32);
 	assert(z == -1);
+	assert(pos.nbits == sizeof(buf) * 8);
 
 	z = per_get_few_bits(&pos, 0);
 	assert(z == 0);
 	assert(pos.nboff == 0);
+	assert(pos.nbits == sizeof(buf) * 8);
 
 	z = per_get_few_bits(&pos, 1);
 	assert(z == 1);
 	assert(pos.nboff == 1);
+	assert(pos.nbits == sizeof(buf) * 8);
 
 	z = per_get_few_bits(&pos, 2);
 	assert(z == 1);
 	assert(pos.nboff == 3);
+	assert(pos.nbits == sizeof(buf) * 8);
 
 	z = per_get_few_bits(&pos, 2);
 	assert(z == 2);
 	assert(pos.nboff == 5);
+	assert(pos.nbits == sizeof(buf) * 8);
 
 	z = per_get_few_bits(&pos, 3);
 	assert(z == 7);
@@ -61,6 +66,20 @@
 	z = per_get_few_bits(&pos, 24);
 	assert(z == 14443711);
 
+	/* Get full 31-bit range */
+	pos.buffer = buf;
+	pos.nboff = 7;
+	pos.nbits = sizeof(buf) * 8;
+	z = per_get_few_bits(&pos, 31);
+	assert(z == 1179384747);
+
+	/* Get a bit shifted range */
+	pos.buffer = buf;
+	pos.nboff = 6;
+	pos.nbits = sizeof(buf) * 8;
+	z = per_get_few_bits(&pos, 31);
+	assert(z == 1663434197);
+
 	pos.buffer = buf;
 	pos.nboff = 0;
 	pos.nbits = sizeof(buf) * 8;