more granular PER encoding
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@1207 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/examples/sample.makefile.regen b/examples/sample.makefile.regen
index 95c1779..1b8f8c4 100755
--- a/examples/sample.makefile.regen
+++ b/examples/sample.makefile.regen
@@ -60,27 +60,39 @@
echo " @if test -f ./sample-${ASN1PDU}-1.[db]er ; then \\"
echo " for f in ./sample-${ASN1PDU}-*.[db]er; do \\"
echo ' echo "Recoding $$f into XER and back..."; \'
- echo ' ./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \'
- echo ' ./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \'
- echo ' diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \'
- echo ' rm -f ./.tmp.[12].$$; \'
+ echo ' ./${TARGET} -iber -oxer -b 1 $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -iber -oxer -b 17 $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -iber -oxer -b 33 $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -iber -oxer -b 980 $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -iber -oxer $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -ixer -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \'
+ echo ' diff ./.tmp.1.$$$$ ./.tmp.2.$$$$ || exit 2; \'
+ echo ' rm -f ./.tmp.[12].$$$$; \'
echo ' done; fi'
echo " @if test -f ./sample-${ASN1PDU}-1.xer ; then \\"
echo " for f in ./sample-${ASN1PDU}-*.xer; do \\"
echo ' echo "Recoding $$f into DER and back..."; \'
- echo ' ./${TARGET} -ixer -oder $$f > ./.tmp.1.$$ || exit 2; \'
- echo ' ./${TARGET} -iber -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \'
- echo ' diff $$f ./.tmp.2.$$ || exit 2; \'
- echo ' rm -f ./.tmp.[12].$$; \'
+ echo ' ./${TARGET} -ixer -oder -b 1 $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -ixer -oder -b 17 $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -ixer -oder -b 33 $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -ixer -oder -b 980 $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -ixer -oder $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \'
+ echo ' diff $$f ./.tmp.2.$$$$ || exit 2; \'
+ echo ' rm -f ./.tmp.[12].$$$$; \'
echo ' done; fi'
echo " @if test -f ./sample-${ASN1PDU}-1.per ; then \\"
echo " for f in ./sample-${ASN1PDU}-*.per; do \\"
echo ' echo "Recoding $$f into DER into XER and back..."; \'
- echo ' ./${TARGET} -iper -oder $$f > ./.tmp.1.$$ || exit 2; \'
- echo ' ./${TARGET} -ider -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \'
- echo ' ./${TARGET} -ixer -oper ./.tmp.2.$$ > ./.tmp.1.$$ || exit 2; \'
- echo ' diff $$f ./.tmp.1.$$ || exit 2; \'
- echo ' rm -f ./.tmp.[12].$$; \'
+ echo ' ./${TARGET} -iper -oder -b 1 $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -iper -oder -b 17 $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -iper -oder -b 33 $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -iper -oder -b 980 $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -iper -oder $$f > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \'
+ echo ' ./${TARGET} -ixer -oper ./.tmp.2.$$$$ > ./.tmp.1.$$$$ || exit 2; \'
+ echo ' diff $$f ./.tmp.1.$$$$ || exit 2; \'
+ echo ' rm -f ./.tmp.[12].$$$$; \'
echo ' done; fi'
echo ' @echo ================'
echo ' @echo All tests passed'
diff --git a/examples/sample.source.MHEG5/Makefile b/examples/sample.source.MHEG5/Makefile
index 4a4f48f..db9e195 100644
--- a/examples/sample.source.MHEG5/Makefile
+++ b/examples/sample.source.MHEG5/Makefile
@@ -493,27 +493,27 @@
@if test -f ./sample-InterchangedObject-1.[db]er ; then \
for f in ./sample-InterchangedObject-*.[db]er; do \
echo "Recoding $$f into XER and back..."; \
- ./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \
- ./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
- diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \
- rm -f ./.tmp.[12].$$; \
+ ./${TARGET} -iber -oxer $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -ixer -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
+ diff ./.tmp.1.$$$$ ./.tmp.2.$$$$ || exit 2; \
+ rm -f ./.tmp.[12].$$$$; \
done; fi
@if test -f ./sample-InterchangedObject-1.xer ; then \
for f in ./sample-InterchangedObject-*.xer; do \
echo "Recoding $$f into DER and back..."; \
- ./${TARGET} -ixer -oder $$f > ./.tmp.1.$$ || exit 2; \
- ./${TARGET} -iber -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
- diff $$f ./.tmp.2.$$ || exit 2; \
- rm -f ./.tmp.[12].$$; \
+ ./${TARGET} -ixer -oder $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
+ diff $$f ./.tmp.2.$$$$ || exit 2; \
+ rm -f ./.tmp.[12].$$$$; \
done; fi
@if test -f ./sample-InterchangedObject-1.per ; then \
for f in ./sample-InterchangedObject-*.per; do \
echo "Recoding $$f into DER into XER and back..."; \
- ./${TARGET} -iper -oder $$f > ./.tmp.1.$$ || exit 2; \
- ./${TARGET} -ider -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
- ./${TARGET} -ixer -oper ./.tmp.2.$$ > ./.tmp.1.$$ || exit 2; \
- diff $$f ./.tmp.1.$$ || exit 2; \
- rm -f ./.tmp.[12].$$; \
+ ./${TARGET} -iper -oder $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
+ ./${TARGET} -ixer -oper ./.tmp.2.$$$$ > ./.tmp.1.$$$$ || exit 2; \
+ diff $$f ./.tmp.1.$$$$ || exit 2; \
+ rm -f ./.tmp.[12].$$$$; \
done; fi
@echo ================
@echo All tests passed
diff --git a/examples/sample.source.RRC/Makefile b/examples/sample.source.RRC/Makefile
index 862f2ca..f694fc4 100644
--- a/examples/sample.source.RRC/Makefile
+++ b/examples/sample.source.RRC/Makefile
@@ -4780,27 +4780,35 @@
@if test -f ./sample-DL-DCCH-Message-1.[db]er ; then \
for f in ./sample-DL-DCCH-Message-*.[db]er; do \
echo "Recoding $$f into XER and back..."; \
- ./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \
- ./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
- diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \
- rm -f ./.tmp.[12].$$; \
+ ./${TARGET} -iber -oxer -b 1 $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -iber -oxer -b 17 $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -iber -oxer -b 33 $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -iber -oxer -b 980 $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -iber -oxer $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -ixer -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
+ diff ./.tmp.1.$$$$ ./.tmp.2.$$$$ || exit 2; \
+ rm -f ./.tmp.[12].$$$$; \
done; fi
@if test -f ./sample-DL-DCCH-Message-1.xer ; then \
for f in ./sample-DL-DCCH-Message-*.xer; do \
echo "Recoding $$f into DER and back..."; \
- ./${TARGET} -ixer -oder $$f > ./.tmp.1.$$ || exit 2; \
- ./${TARGET} -iber -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
- diff $$f ./.tmp.2.$$ || exit 2; \
- rm -f ./.tmp.[12].$$; \
+ ./${TARGET} -ixer -oder -b 1 $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -ixer -oder -b 17 $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -ixer -oder -b 33 $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -ixer -oder -b 980 $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -ixer -oder $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
+ diff $$f ./.tmp.2.$$$$ || exit 2; \
+ rm -f ./.tmp.[12].$$$$; \
done; fi
@if test -f ./sample-DL-DCCH-Message-1.per ; then \
for f in ./sample-DL-DCCH-Message-*.per; do \
echo "Recoding $$f into DER into XER and back..."; \
- ./${TARGET} -iper -oder $$f > ./.tmp.1.$$ || exit 2; \
- ./${TARGET} -ider -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
- ./${TARGET} -ixer -oper ./.tmp.2.$$ > ./.tmp.1.$$ || exit 2; \
- diff $$f ./.tmp.1.$$ || exit 2; \
- rm -f ./.tmp.[12].$$; \
+ ./${TARGET} -iper -oder $$f > ./.tmp.1.$$$$ || exit 2; \
+ ./${TARGET} -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
+ ./${TARGET} -ixer -oper ./.tmp.2.$$$$ > ./.tmp.1.$$$$ || exit 2; \
+ diff $$f ./.tmp.1.$$$$ || exit 2; \
+ rm -f ./.tmp.[12].$$$$; \
done; fi
@echo ================
@echo All tests passed
diff --git a/skeletons/converter-sample.c b/skeletons/converter-sample.c
index 79067a3..3ee0b3b 100644
--- a/skeletons/converter-sample.c
+++ b/skeletons/converter-sample.c
@@ -35,7 +35,7 @@
* Open file and parse its contens.
*/
static void *data_decode_from_file(asn_TYPE_descriptor_t *asnTypeOfPDU,
- FILE *f, const char *filename, ssize_t suggested_bufsize);
+ FILE *file, const char *name, ssize_t suggested_bufsize, int first_pdu);
static int write_out(const void *buffer, size_t size, void *key);
static FILE *argument_to_file(char *av[], int idx);
static char *argument_to_name(char *av[], int idx);
@@ -43,6 +43,7 @@
int opt_debug; /* -d */
static int opt_check; /* -c */
static int opt_stack; /* -s */
+static int opt_onepdu; /* -1 */
/* Input data format selector */
static enum input_format {
@@ -107,21 +108,9 @@
fprintf(stderr, "-o<format>: '%s': improper format selector\n",
optarg);
exit(EX_UNAVAILABLE);
- case 'p':
-#ifdef ASN_PDU_COLLECTION
- {
- asn_TYPE_descriptor_t **pdu = asn_pdu_collection;
- if(optarg[0] < 'A' || optarg[0] > 'Z') {
- fprintf(stderr, "Available PDU types:\n");
- for(; *pdu; pdu++) printf("%s\n", (*pdu)->name);
- exit(0);
- }
- while(*pdu && strcmp((*pdu)->name, optarg)) pdu++;
- if(*pdu) { pduType = *pdu; break; }
- }
-#endif /* ASN_PDU_COLLECTION */
- fprintf(stderr, "-p %s: Unrecognized PDU\n", optarg);
- exit(EX_UNAVAILABLE);
+ case '1':
+ opt_onepdu = 1;
+ break;
case 'b':
suggested_bufsize = atoi(optarg);
if(suggested_bufsize < 1
@@ -146,6 +135,21 @@
exit(EX_UNAVAILABLE);
}
break;
+ case 'p':
+#ifdef ASN_PDU_COLLECTION
+ {
+ asn_TYPE_descriptor_t **pdu = asn_pdu_collection;
+ if(optarg[0] < 'A' || optarg[0] > 'Z') {
+ fprintf(stderr, "Available PDU types:\n");
+ for(; *pdu; pdu++) printf("%s\n", (*pdu)->name);
+ exit(0);
+ }
+ while(*pdu && strcmp((*pdu)->name, optarg)) pdu++;
+ if(*pdu) { pduType = *pdu; break; }
+ }
+#endif /* ASN_PDU_COLLECTION */
+ fprintf(stderr, "-p %s: Unrecognized PDU\n", optarg);
+ exit(EX_UNAVAILABLE);
case 's':
opt_stack = atoi(optarg);
if(opt_stack < 0) {
@@ -208,20 +212,26 @@
* Process all files in turn.
*/
for(ac_i = 0; ac_i < ac; ac_i++) {
- asn_enc_rval_t erv;
- void *structure; /* Decoded structure */
- FILE *file = argument_to_file(av, ac_i);
- char *name = argument_to_name(av, ac_i);
+ asn_enc_rval_t erv;
+ void *structure; /* Decoded structure */
+ FILE *file = argument_to_file(av, ac_i);
+ char *name = argument_to_name(av, ac_i);
+ int first_pdu;
+ for(first_pdu = 1; first_pdu || !opt_onepdu; first_pdu = 0) {
/*
* Decode the encoded structure from file.
*/
structure = data_decode_from_file(pduType,
- file, name, suggested_bufsize);
- if(file && file != stdin) fclose(file);
+ file, name, suggested_bufsize, first_pdu);
if(!structure) {
- /* Error message is already printed */
- exit(EX_DATAERR);
+ if(errno) {
+ /* Error message is already printed */
+ exit(EX_DATAERR);
+ } else {
+ /* EOF */
+ break;
+ }
}
/* Check ASN.1 constraints */
@@ -257,6 +267,7 @@
name);
exit(EX_UNAVAILABLE);
}
+ DEBUG("Encoded in %ld bytes of DER", (long)erv.encoded);
break;
case OUT_PER:
erv = uper_encode(pduType, structure, write_out, stdout);
@@ -265,10 +276,15 @@
name);
exit(EX_UNAVAILABLE);
}
+ DEBUG("Encoded in %ld bits of UPER", (long)erv.encoded);
break;
}
ASN_STRUCT_FREE(*pduType, structure);
+ }
+
+ if(file && file != stdin)
+ fclose(file);
}
}
@@ -279,6 +295,7 @@
char *data; /* Pointer to the data bytes */
size_t offset; /* Offset from the start */
size_t length; /* Length of meaningful contents */
+ size_t unbit; /* Unused bits in the last byte */
size_t allocated; /* Allocated memory for data */
int nreallocs; /* Number of data reallocations */
off_t bytes_shifted; /* Number of bytes ever shifted */
@@ -332,17 +349,20 @@
}
static void *
-data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *filename, ssize_t suggested_bufsize) {
+data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *name, ssize_t suggested_bufsize, int on_first_pdu) {
static char *fbuf;
static ssize_t fbuf_size;
static asn_codec_ctx_t s_codec_ctx;
asn_codec_ctx_t *opt_codec_ctx = 0;
void *structure = 0;
asn_dec_rval_t rval;
+ size_t old_offset;
+ size_t new_offset;
size_t rd;
if(!file) {
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
+ fprintf(stderr, "%s: %s\n", name, strerror(errno));
+ errno = EINVAL;
return 0;
}
@@ -351,7 +371,7 @@
opt_codec_ctx = &s_codec_ctx;
}
- DEBUG("Processing %s", filename);
+ DEBUG("Processing %s", name);
/* prepare the file buffer */
if(fbuf_size != suggested_bufsize) {
@@ -363,17 +383,23 @@
fbuf_size = suggested_bufsize;
}
- DynamicBuffer.offset = 0;
- DynamicBuffer.length = 0;
- DynamicBuffer.allocated = 0;
- DynamicBuffer.bytes_shifted = 0;
- DynamicBuffer.nreallocs = 0;
+ if(on_first_pdu) {
+ DynamicBuffer.offset = 0;
+ DynamicBuffer.length = 0;
+ DynamicBuffer.unbit = 0;
+ DynamicBuffer.allocated = 0;
+ DynamicBuffer.bytes_shifted = 0;
+ DynamicBuffer.nreallocs = 0;
+ }
+
+ old_offset = DynamicBuffer.bytes_shifted + DynamicBuffer.offset;
/* Pretend immediate EOF */
rval.code = RC_WMORE;
rval.consumed = 0;
while((rd = fread(fbuf, 1, fbuf_size, file)) || !feof(file)) {
+ int ecbits = 0; /* Extra consumed bits in case of PER */
char *i_bptr;
size_t i_size;
@@ -390,6 +416,8 @@
i_size = rd;
}
+ DEBUG("Decoding %ld bytes", (long)i_size);
+
switch(iform) {
case INP_BER:
rval = ber_decode(opt_codec_ctx, pduType,
@@ -401,7 +429,11 @@
break;
case INP_PER:
rval = uper_decode(opt_codec_ctx, pduType,
- (void **)&structure, i_bptr, i_size);
+ (void **)&structure, i_bptr, i_size, 0);
+ ecbits = rval.consumed % 8; /* Extra bits */
+ DEBUG("PER unused %d bits (consumed %ld, %d)",
+ ecbits, (long)rval.consumed);
+ rval.consumed /= 8; /* Convert to value in bytes! */
break;
}
DEBUG("decode(%ld) consumed %ld (%ld), code %d",
@@ -411,34 +443,37 @@
if(DynamicBuffer.allocated == 0) {
/*
- * Flush the remainder into the intermediate buffer.
+ * Flush remainder into the intermediate buffer.
*/
if(rval.code != RC_FAIL && rval.consumed < rd) {
+ DEBUG("Saving %d bytes", rd - rval.consumed);
add_bytes_to_buffer(fbuf + rval.consumed,
rd - rval.consumed);
rval.consumed = 0;
}
}
+ /*
+ * Adjust position inside the source buffer.
+ */
+ if(DynamicBuffer.allocated) {
+ DynamicBuffer.offset += rval.consumed;
+ DynamicBuffer.length -= rval.consumed;
+ } else {
+ DynamicBuffer.bytes_shifted += rval.consumed;
+ }
+
switch(rval.code) {
case RC_OK:
DEBUG("RC_OK, finishing up with %ld",
(long)rval.consumed);
return structure;
case RC_WMORE:
- /*
- * Adjust position inside the source buffer.
- */
- if(DynamicBuffer.allocated) {
- DynamicBuffer.offset += rval.consumed;
- DynamicBuffer.length -= rval.consumed;
- }
DEBUG("RC_WMORE, continuing %ld with %ld..%ld..%ld",
(long)rval.consumed,
(long)DynamicBuffer.offset,
(long)DynamicBuffer.length,
(long)DynamicBuffer.allocated);
- rval.consumed = 0;
continue;
case RC_FAIL:
break;
@@ -449,13 +484,24 @@
/* Clean up partially decoded structure */
ASN_STRUCT_FREE(*pduType, structure);
- fprintf(stderr, "%s: "
- "Decode failed past byte %ld: %s\n",
- filename, (long)(DynamicBuffer.bytes_shifted
- + DynamicBuffer.offset + rval.consumed),
- (rval.code == RC_WMORE)
- ? "Unexpected end of input"
- : "Input processing error");
+ new_offset = DynamicBuffer.bytes_shifted + DynamicBuffer.offset;
+
+ /*
+ * Print a message and return failure only if not EOF,
+ * unless this is our first PDU (empty file).
+ */
+ if(on_first_pdu || new_offset != old_offset) {
+ fprintf(stderr, "%s: "
+ "Decode failed past byte %ld: %s\n",
+ name, (long)new_offset,
+ (rval.code == RC_WMORE)
+ ? "Unexpected end of input"
+ : "Input processing error");
+ errno = (rval.code == RC_WMORE) ? ENOMSG : EBADMSG;
+ } else {
+ /* Got EOF after a few successful PDU */
+ errno = 0;
+ }
return 0;
}
diff --git a/skeletons/per_decoder.c b/skeletons/per_decoder.c
index 506ad67..bc5f569 100644
--- a/skeletons/per_decoder.c
+++ b/skeletons/per_decoder.c
@@ -3,10 +3,13 @@
#include <per_decoder.h>
asn_dec_rval_t
-uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size) {
+uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits) {
asn_codec_ctx_t s_codec_ctx;
asn_per_data_t pd;
+ if(skip_bits < 0 || skip_bits > 7 || (skip_bits > 0 && !size))
+ _ASN_DECODE_FAILED;
+
/*
* Stack checker requires that the codec context
* must be allocated on the stack.
@@ -25,7 +28,7 @@
/* Fill in the position indicator */
pd.buffer = (const uint8_t *)buffer;
- pd.nboff = 0;
+ pd.nboff = skip_bits;
pd.nbits = 8 * size; /* 8 is CHAR_BIT from <limits.h> */
/*
diff --git a/skeletons/per_decoder.h b/skeletons/per_decoder.h
index 27fe064..23cb7d7 100644
--- a/skeletons/per_decoder.h
+++ b/skeletons/per_decoder.h
@@ -21,7 +21,8 @@
struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */
void **struct_ptr, /* Pointer to a target structure's pointer */
const void *buffer, /* Data to be decoded */
- size_t size /* Size of data buffer */
+ size_t size, /* Size of data buffer */
+ int skip_bits /* Number of unused leading bits, 0..7 */
);
diff --git a/skeletons/per_encoder.c b/skeletons/per_encoder.c
index 6ba28e5..614dd23 100644
--- a/skeletons/per_encoder.c
+++ b/skeletons/per_encoder.c
@@ -21,10 +21,20 @@
po.nbits = 8 * sizeof(po.tmpspace);
po.outper = cb;
po.op_key = app_key;
+ po.flushed_bytes = 0;
er = td->uper_encoder(td, 0, sptr, &po);
- if(er.encoded != -1 && _uper_encode_flush_outp(&po))
- _ASN_ENCODE_FAILED;
+ if(er.encoded != -1) {
+ size_t bits_to_flush;
+
+ bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;
+
+ /* Set number of bits encoded to a firm value */
+ er.encoded = (po.flushed_bytes << 3) + bits_to_flush;
+
+ if(_uper_encode_flush_outp(&po))
+ _ASN_ENCODE_FAILED;
+ }
return er;
}
@@ -52,7 +62,6 @@
asn_enc_rval_t
uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) {
enc_to_buf_arg key;
- asn_enc_rval_t er;
/*
* Invoke type-specific encoder.
@@ -65,10 +74,7 @@
ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);
- er = uper_encode(td, sptr, encode_to_buffer_cb, &key);
- if(er.encoded != -1)
- er.encoded = buffer_size - key.left;
- return er;
+ return uper_encode(td, sptr, encode_to_buffer_cb, &key);
}
static int
diff --git a/skeletons/per_support.c b/skeletons/per_support.c
index 9217038..b0149f8 100644
--- a/skeletons/per_support.c
+++ b/skeletons/per_support.c
@@ -210,6 +210,7 @@
po->tmpspace[0] = po->buffer[0];
po->buffer = po->tmpspace;
po->nbits = 8 * sizeof(po->tmpspace);
+ po->flushed_bytes += complete_bytes;
}
/*
diff --git a/skeletons/per_support.h b/skeletons/per_support.h
index 7e5e594..420bb83 100644
--- a/skeletons/per_support.h
+++ b/skeletons/per_support.h
@@ -76,7 +76,8 @@
size_t nbits; /* Number of bits left in (tmpspace) */
uint8_t tmpspace[32]; /* Preliminary storage to hold data */
int (*outper)(const void *data, size_t size, void *op_key);
- void *op_key;
+ void *op_key; /* Key for (outper) data callback */
+ size_t flushed_bytes; /* Bytes already flushed through (outper) */
} asn_per_outp_t;
/* Output a small number of bits (<= 31) */