diff --git a/examples/sample.makefile.regen b/examples/sample.makefile.regen index 95c17794..1b8f8c4a 100755 --- a/examples/sample.makefile.regen +++ b/examples/sample.makefile.regen @@ -60,27 +60,39 @@ cat Makefile.am.sample \ 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 4a4f48fa..db9e1950 100644 --- a/examples/sample.source.MHEG5/Makefile +++ b/examples/sample.source.MHEG5/Makefile @@ -493,27 +493,27 @@ check: ${TARGET} @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 862f2cac..f694fc43 100644 --- a/examples/sample.source.RRC/Makefile +++ b/examples/sample.source.RRC/Makefile @@ -4780,27 +4780,35 @@ check: ${TARGET} @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 79067a30..3ee0b3b0 100644 --- a/skeletons/converter-sample.c +++ b/skeletons/converter-sample.c @@ -35,7 +35,7 @@ extern asn_TYPE_descriptor_t *asn_pdu_collection[]; * 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 @@ static char *argument_to_name(char *av[], int idx); 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 @@ main(int ac, char *av[]) { fprintf(stderr, "-o: '%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 @@ main(int ac, char *av[]) { 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 @@ main(int ac, char *av[]) { * 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 @@ main(int ac, char *av[]) { 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 @@ main(int ac, char *av[]) { 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 @@ static struct dynamic_buffer { 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 add_bytes_to_buffer(const void *data2add, size_t bySize) { } 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 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *fi 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 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *fi 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 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *fi 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 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *fi 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 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *fi 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 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *fi /* 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 506ad674..bc5f569c 100644 --- a/skeletons/per_decoder.c +++ b/skeletons/per_decoder.c @@ -3,10 +3,13 @@ #include 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 @@ uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sp /* 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 */ /* diff --git a/skeletons/per_decoder.h b/skeletons/per_decoder.h index 27fe064f..23cb7d7a 100644 --- a/skeletons/per_decoder.h +++ b/skeletons/per_decoder.h @@ -21,7 +21,8 @@ asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx, 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 6ba28e53..614dd233 100644 --- a/skeletons/per_encoder.c +++ b/skeletons/per_encoder.c @@ -21,10 +21,20 @@ uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, 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 @@ static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) { 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 @@ uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_ 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 9217038e..b0149f89 100644 --- a/skeletons/per_support.c +++ b/skeletons/per_support.c @@ -210,6 +210,7 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) { 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 7e5e5940..420bb83c 100644 --- a/skeletons/per_support.h +++ b/skeletons/per_support.h @@ -76,7 +76,8 @@ typedef struct asn_per_outp_s { 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) */