per_get_undo()
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index ec04992..4267d84 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -1078,7 +1078,6 @@
oldpd->nbits -= consumed;
oldpd->buffer = pd->buffer;
oldpd->nboff = pd->nboff;
- oldpd->nboff = pd->nbits;
if(arg->unclaimed) {
/* Refill the container */
@@ -1091,6 +1090,7 @@
pd->buffer = oldpd->buffer;
pd->nboff = oldpd->nboff - 1;
pd->nbits = oldpd->nbits;
+ pd->moved = oldpd->moved - 1;
ASN_DEBUG("====================");
return 0;
}
@@ -1110,12 +1110,12 @@
pd->buffer = oldpd->buffer;
pd->nboff = oldpd->nboff;
pd->nbits = oldpd->nbits;
+ pd->moved = oldpd->moved;
next_chunk_bits = next_chunk_bytes << 3;
avail = pd->nbits - pd->nboff;
- ASN_DEBUG("now at %d bits, want %d",
+ ASN_DEBUG("now at %d bits, want %d, avail %d",
((((int)pd->buffer ) & 0x7) << 3) + pd->nboff,
- next_chunk_bits);
- ASN_DEBUG("avail = %d", avail);
+ next_chunk_bits, avail);
if(avail >= next_chunk_bits) {
pd->nbits = pd->nboff + next_chunk_bits;
arg->unclaimed = 0;
diff --git a/skeletons/per_decoder.c b/skeletons/per_decoder.c
index 2e460da..4e120a4 100644
--- a/skeletons/per_decoder.c
+++ b/skeletons/per_decoder.c
@@ -47,6 +47,7 @@
/* Return the number of consumed bits */
rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3)
+ pd.nboff - skip_bits;
+ assert(rval.consumed == pd.moved);
} else {
/* PER codec is not a restartable */
rval.consumed = 0;
diff --git a/skeletons/per_support.c b/skeletons/per_support.c
index 228fd11..f38422a 100644
--- a/skeletons/per_support.c
+++ b/skeletons/per_support.c
@@ -6,13 +6,23 @@
#include <asn_internal.h>
#include <per_support.h>
+void
+per_get_undo(asn_per_data_t *pd, int nbits) {
+ if(pd->nboff < nbits) {
+ assert(pd->nboff < nbits);
+ } else {
+ pd->nboff -= nbits;
+ pd->moved -= nbits;
+ }
+}
+
/*
* 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) {
size_t off; /* Next after last bit offset */
- ssize_t nleft;
+ ssize_t nleft; /* Number of bits left in this stream */
uint32_t accum;
const uint8_t *buf;
@@ -48,7 +58,9 @@
pd->nbits -= (pd->nboff & ~0x07);
pd->nboff &= 0x07;
}
- off = (pd->nboff += nbits);
+ pd->moved += nbits;
+ pd->nboff += nbits;
+ off = pd->nboff;
buf = pd->buffer;
/*
@@ -66,11 +78,14 @@
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;
+ per_get_undo(&tpd, nbits);
+ /* The number of available bits in the stream allow
+ * for the following operations to take place without
+ * invoking the ->refill() function */
accum = per_get_few_bits(&tpd, nbits - 24) << 24;
accum |= per_get_few_bits(&tpd, 24);
} else {
- pd->nboff -= nbits; /* Oops, revert back */
+ per_get_undo(pd, nbits);
return -1;
}
diff --git a/skeletons/per_support.h b/skeletons/per_support.h
index c22bc72..bf06f05 100644
--- a/skeletons/per_support.h
+++ b/skeletons/per_support.h
@@ -37,11 +37,12 @@
* This structure describes a position inside an incoming PER bit stream.
*/
typedef struct asn_per_data_s {
- const uint8_t *buffer; /* Pointer to the octet stream */
- size_t nboff; /* Bit offset to the meaningful bit */
- size_t nbits; /* Number of bits in the stream */
- int (*refill)(struct asn_per_data_s *);
- void *refill_key;
+ const uint8_t *buffer; /* Pointer to the octet stream */
+ size_t nboff; /* Bit offset to the meaningful bit */
+ size_t nbits; /* Number of bits in the stream */
+ size_t moved; /* Number of bits moved through this bit stream */
+ int (*refill)(struct asn_per_data_s *);
+ void *refill_key;
} asn_per_data_t;
/*
@@ -51,6 +52,9 @@
*/
int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits);
+/* Undo the immediately preceeding "get_few_bits" operation */
+void per_get_undo(asn_per_data_t *per_data, int get_nbits);
+
/*
* Extract a large number of bits from the specified PER data pointer.
* This function returns -1 if the specified number of bits could not be