mirror of https://gerrit.osmocom.org/asn1c
more granular PER encoding
This commit is contained in:
parent
13c92a6409
commit
bc6917730d
|
@ -60,27 +60,39 @@ cat Makefile.am.sample \
|
||||||
echo " @if test -f ./sample-${ASN1PDU}-1.[db]er ; then \\"
|
echo " @if test -f ./sample-${ASN1PDU}-1.[db]er ; then \\"
|
||||||
echo " for f in ./sample-${ASN1PDU}-*.[db]er; do \\"
|
echo " for f in ./sample-${ASN1PDU}-*.[db]er; do \\"
|
||||||
echo ' echo "Recoding $$f into XER and back..."; \'
|
echo ' echo "Recoding $$f into XER and back..."; \'
|
||||||
echo ' ./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \'
|
echo ' ./${TARGET} -iber -oxer -b 1 $$f > ./.tmp.1.$$$$ || exit 2; \'
|
||||||
echo ' ./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \'
|
echo ' ./${TARGET} -iber -oxer -b 17 $$f > ./.tmp.1.$$$$ || exit 2; \'
|
||||||
echo ' diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \'
|
echo ' ./${TARGET} -iber -oxer -b 33 $$f > ./.tmp.1.$$$$ || exit 2; \'
|
||||||
echo ' rm -f ./.tmp.[12].$$; \'
|
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 ' done; fi'
|
||||||
echo " @if test -f ./sample-${ASN1PDU}-1.xer ; then \\"
|
echo " @if test -f ./sample-${ASN1PDU}-1.xer ; then \\"
|
||||||
echo " for f in ./sample-${ASN1PDU}-*.xer; do \\"
|
echo " for f in ./sample-${ASN1PDU}-*.xer; do \\"
|
||||||
echo ' echo "Recoding $$f into DER and back..."; \'
|
echo ' echo "Recoding $$f into DER and back..."; \'
|
||||||
echo ' ./${TARGET} -ixer -oder $$f > ./.tmp.1.$$ || exit 2; \'
|
echo ' ./${TARGET} -ixer -oder -b 1 $$f > ./.tmp.1.$$$$ || exit 2; \'
|
||||||
echo ' ./${TARGET} -iber -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \'
|
echo ' ./${TARGET} -ixer -oder -b 17 $$f > ./.tmp.1.$$$$ || exit 2; \'
|
||||||
echo ' diff $$f ./.tmp.2.$$ || exit 2; \'
|
echo ' ./${TARGET} -ixer -oder -b 33 $$f > ./.tmp.1.$$$$ || exit 2; \'
|
||||||
echo ' rm -f ./.tmp.[12].$$; \'
|
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 ' done; fi'
|
||||||
echo " @if test -f ./sample-${ASN1PDU}-1.per ; then \\"
|
echo " @if test -f ./sample-${ASN1PDU}-1.per ; then \\"
|
||||||
echo " for f in ./sample-${ASN1PDU}-*.per; do \\"
|
echo " for f in ./sample-${ASN1PDU}-*.per; do \\"
|
||||||
echo ' echo "Recoding $$f into DER into XER and back..."; \'
|
echo ' echo "Recoding $$f into DER into XER and back..."; \'
|
||||||
echo ' ./${TARGET} -iper -oder $$f > ./.tmp.1.$$ || exit 2; \'
|
echo ' ./${TARGET} -iper -oder -b 1 $$f > ./.tmp.1.$$$$ || exit 2; \'
|
||||||
echo ' ./${TARGET} -ider -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \'
|
echo ' ./${TARGET} -iper -oder -b 17 $$f > ./.tmp.1.$$$$ || exit 2; \'
|
||||||
echo ' ./${TARGET} -ixer -oper ./.tmp.2.$$ > ./.tmp.1.$$ || exit 2; \'
|
echo ' ./${TARGET} -iper -oder -b 33 $$f > ./.tmp.1.$$$$ || exit 2; \'
|
||||||
echo ' diff $$f ./.tmp.1.$$ || exit 2; \'
|
echo ' ./${TARGET} -iper -oder -b 980 $$f > ./.tmp.1.$$$$ || exit 2; \'
|
||||||
echo ' rm -f ./.tmp.[12].$$; \'
|
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 ' done; fi'
|
||||||
echo ' @echo ================'
|
echo ' @echo ================'
|
||||||
echo ' @echo All tests passed'
|
echo ' @echo All tests passed'
|
||||||
|
|
|
@ -493,27 +493,27 @@ check: ${TARGET}
|
||||||
@if test -f ./sample-InterchangedObject-1.[db]er ; then \
|
@if test -f ./sample-InterchangedObject-1.[db]er ; then \
|
||||||
for f in ./sample-InterchangedObject-*.[db]er; do \
|
for f in ./sample-InterchangedObject-*.[db]er; do \
|
||||||
echo "Recoding $$f into XER and back..."; \
|
echo "Recoding $$f into XER and back..."; \
|
||||||
./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \
|
./${TARGET} -iber -oxer $$f > ./.tmp.1.$$$$ || exit 2; \
|
||||||
./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
|
./${TARGET} -ixer -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
|
||||||
diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \
|
diff ./.tmp.1.$$$$ ./.tmp.2.$$$$ || exit 2; \
|
||||||
rm -f ./.tmp.[12].$$; \
|
rm -f ./.tmp.[12].$$$$; \
|
||||||
done; fi
|
done; fi
|
||||||
@if test -f ./sample-InterchangedObject-1.xer ; then \
|
@if test -f ./sample-InterchangedObject-1.xer ; then \
|
||||||
for f in ./sample-InterchangedObject-*.xer; do \
|
for f in ./sample-InterchangedObject-*.xer; do \
|
||||||
echo "Recoding $$f into DER and back..."; \
|
echo "Recoding $$f into DER and back..."; \
|
||||||
./${TARGET} -ixer -oder $$f > ./.tmp.1.$$ || exit 2; \
|
./${TARGET} -ixer -oder $$f > ./.tmp.1.$$$$ || exit 2; \
|
||||||
./${TARGET} -iber -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
|
./${TARGET} -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
|
||||||
diff $$f ./.tmp.2.$$ || exit 2; \
|
diff $$f ./.tmp.2.$$$$ || exit 2; \
|
||||||
rm -f ./.tmp.[12].$$; \
|
rm -f ./.tmp.[12].$$$$; \
|
||||||
done; fi
|
done; fi
|
||||||
@if test -f ./sample-InterchangedObject-1.per ; then \
|
@if test -f ./sample-InterchangedObject-1.per ; then \
|
||||||
for f in ./sample-InterchangedObject-*.per; do \
|
for f in ./sample-InterchangedObject-*.per; do \
|
||||||
echo "Recoding $$f into DER into XER and back..."; \
|
echo "Recoding $$f into DER into XER and back..."; \
|
||||||
./${TARGET} -iper -oder $$f > ./.tmp.1.$$ || exit 2; \
|
./${TARGET} -iper -oder $$f > ./.tmp.1.$$$$ || exit 2; \
|
||||||
./${TARGET} -ider -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
|
./${TARGET} -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
|
||||||
./${TARGET} -ixer -oper ./.tmp.2.$$ > ./.tmp.1.$$ || exit 2; \
|
./${TARGET} -ixer -oper ./.tmp.2.$$$$ > ./.tmp.1.$$$$ || exit 2; \
|
||||||
diff $$f ./.tmp.1.$$ || exit 2; \
|
diff $$f ./.tmp.1.$$$$ || exit 2; \
|
||||||
rm -f ./.tmp.[12].$$; \
|
rm -f ./.tmp.[12].$$$$; \
|
||||||
done; fi
|
done; fi
|
||||||
@echo ================
|
@echo ================
|
||||||
@echo All tests passed
|
@echo All tests passed
|
||||||
|
|
|
@ -4780,27 +4780,35 @@ check: ${TARGET}
|
||||||
@if test -f ./sample-DL-DCCH-Message-1.[db]er ; then \
|
@if test -f ./sample-DL-DCCH-Message-1.[db]er ; then \
|
||||||
for f in ./sample-DL-DCCH-Message-*.[db]er; do \
|
for f in ./sample-DL-DCCH-Message-*.[db]er; do \
|
||||||
echo "Recoding $$f into XER and back..."; \
|
echo "Recoding $$f into XER and back..."; \
|
||||||
./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \
|
./${TARGET} -iber -oxer -b 1 $$f > ./.tmp.1.$$$$ || exit 2; \
|
||||||
./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
|
./${TARGET} -iber -oxer -b 17 $$f > ./.tmp.1.$$$$ || exit 2; \
|
||||||
diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \
|
./${TARGET} -iber -oxer -b 33 $$f > ./.tmp.1.$$$$ || exit 2; \
|
||||||
rm -f ./.tmp.[12].$$; \
|
./${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
|
done; fi
|
||||||
@if test -f ./sample-DL-DCCH-Message-1.xer ; then \
|
@if test -f ./sample-DL-DCCH-Message-1.xer ; then \
|
||||||
for f in ./sample-DL-DCCH-Message-*.xer; do \
|
for f in ./sample-DL-DCCH-Message-*.xer; do \
|
||||||
echo "Recoding $$f into DER and back..."; \
|
echo "Recoding $$f into DER and back..."; \
|
||||||
./${TARGET} -ixer -oder $$f > ./.tmp.1.$$ || exit 2; \
|
./${TARGET} -ixer -oder -b 1 $$f > ./.tmp.1.$$$$ || exit 2; \
|
||||||
./${TARGET} -iber -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
|
./${TARGET} -ixer -oder -b 17 $$f > ./.tmp.1.$$$$ || exit 2; \
|
||||||
diff $$f ./.tmp.2.$$ || exit 2; \
|
./${TARGET} -ixer -oder -b 33 $$f > ./.tmp.1.$$$$ || exit 2; \
|
||||||
rm -f ./.tmp.[12].$$; \
|
./${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
|
done; fi
|
||||||
@if test -f ./sample-DL-DCCH-Message-1.per ; then \
|
@if test -f ./sample-DL-DCCH-Message-1.per ; then \
|
||||||
for f in ./sample-DL-DCCH-Message-*.per; do \
|
for f in ./sample-DL-DCCH-Message-*.per; do \
|
||||||
echo "Recoding $$f into DER into XER and back..."; \
|
echo "Recoding $$f into DER into XER and back..."; \
|
||||||
./${TARGET} -iper -oder $$f > ./.tmp.1.$$ || exit 2; \
|
./${TARGET} -iper -oder $$f > ./.tmp.1.$$$$ || exit 2; \
|
||||||
./${TARGET} -ider -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
|
./${TARGET} -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
|
||||||
./${TARGET} -ixer -oper ./.tmp.2.$$ > ./.tmp.1.$$ || exit 2; \
|
./${TARGET} -ixer -oper ./.tmp.2.$$$$ > ./.tmp.1.$$$$ || exit 2; \
|
||||||
diff $$f ./.tmp.1.$$ || exit 2; \
|
diff $$f ./.tmp.1.$$$$ || exit 2; \
|
||||||
rm -f ./.tmp.[12].$$; \
|
rm -f ./.tmp.[12].$$$$; \
|
||||||
done; fi
|
done; fi
|
||||||
@echo ================
|
@echo ================
|
||||||
@echo All tests passed
|
@echo All tests passed
|
||||||
|
|
|
@ -35,7 +35,7 @@ extern asn_TYPE_descriptor_t *asn_pdu_collection[];
|
||||||
* Open file and parse its contens.
|
* Open file and parse its contens.
|
||||||
*/
|
*/
|
||||||
static void *data_decode_from_file(asn_TYPE_descriptor_t *asnTypeOfPDU,
|
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 int write_out(const void *buffer, size_t size, void *key);
|
||||||
static FILE *argument_to_file(char *av[], int idx);
|
static FILE *argument_to_file(char *av[], int idx);
|
||||||
static char *argument_to_name(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 */
|
int opt_debug; /* -d */
|
||||||
static int opt_check; /* -c */
|
static int opt_check; /* -c */
|
||||||
static int opt_stack; /* -s */
|
static int opt_stack; /* -s */
|
||||||
|
static int opt_onepdu; /* -1 */
|
||||||
|
|
||||||
/* Input data format selector */
|
/* Input data format selector */
|
||||||
static enum input_format {
|
static enum input_format {
|
||||||
|
@ -107,21 +108,9 @@ main(int ac, char *av[]) {
|
||||||
fprintf(stderr, "-o<format>: '%s': improper format selector\n",
|
fprintf(stderr, "-o<format>: '%s': improper format selector\n",
|
||||||
optarg);
|
optarg);
|
||||||
exit(EX_UNAVAILABLE);
|
exit(EX_UNAVAILABLE);
|
||||||
case 'p':
|
case '1':
|
||||||
#ifdef ASN_PDU_COLLECTION
|
opt_onepdu = 1;
|
||||||
{
|
break;
|
||||||
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 'b':
|
case 'b':
|
||||||
suggested_bufsize = atoi(optarg);
|
suggested_bufsize = atoi(optarg);
|
||||||
if(suggested_bufsize < 1
|
if(suggested_bufsize < 1
|
||||||
|
@ -146,6 +135,21 @@ main(int ac, char *av[]) {
|
||||||
exit(EX_UNAVAILABLE);
|
exit(EX_UNAVAILABLE);
|
||||||
}
|
}
|
||||||
break;
|
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':
|
case 's':
|
||||||
opt_stack = atoi(optarg);
|
opt_stack = atoi(optarg);
|
||||||
if(opt_stack < 0) {
|
if(opt_stack < 0) {
|
||||||
|
@ -208,20 +212,26 @@ main(int ac, char *av[]) {
|
||||||
* Process all files in turn.
|
* Process all files in turn.
|
||||||
*/
|
*/
|
||||||
for(ac_i = 0; ac_i < ac; ac_i++) {
|
for(ac_i = 0; ac_i < ac; ac_i++) {
|
||||||
asn_enc_rval_t erv;
|
asn_enc_rval_t erv;
|
||||||
void *structure; /* Decoded structure */
|
void *structure; /* Decoded structure */
|
||||||
FILE *file = argument_to_file(av, ac_i);
|
FILE *file = argument_to_file(av, ac_i);
|
||||||
char *name = argument_to_name(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.
|
* Decode the encoded structure from file.
|
||||||
*/
|
*/
|
||||||
structure = data_decode_from_file(pduType,
|
structure = data_decode_from_file(pduType,
|
||||||
file, name, suggested_bufsize);
|
file, name, suggested_bufsize, first_pdu);
|
||||||
if(file && file != stdin) fclose(file);
|
|
||||||
if(!structure) {
|
if(!structure) {
|
||||||
/* Error message is already printed */
|
if(errno) {
|
||||||
exit(EX_DATAERR);
|
/* Error message is already printed */
|
||||||
|
exit(EX_DATAERR);
|
||||||
|
} else {
|
||||||
|
/* EOF */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check ASN.1 constraints */
|
/* Check ASN.1 constraints */
|
||||||
|
@ -257,6 +267,7 @@ main(int ac, char *av[]) {
|
||||||
name);
|
name);
|
||||||
exit(EX_UNAVAILABLE);
|
exit(EX_UNAVAILABLE);
|
||||||
}
|
}
|
||||||
|
DEBUG("Encoded in %ld bytes of DER", (long)erv.encoded);
|
||||||
break;
|
break;
|
||||||
case OUT_PER:
|
case OUT_PER:
|
||||||
erv = uper_encode(pduType, structure, write_out, stdout);
|
erv = uper_encode(pduType, structure, write_out, stdout);
|
||||||
|
@ -265,10 +276,15 @@ main(int ac, char *av[]) {
|
||||||
name);
|
name);
|
||||||
exit(EX_UNAVAILABLE);
|
exit(EX_UNAVAILABLE);
|
||||||
}
|
}
|
||||||
|
DEBUG("Encoded in %ld bits of UPER", (long)erv.encoded);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASN_STRUCT_FREE(*pduType, structure);
|
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 */
|
char *data; /* Pointer to the data bytes */
|
||||||
size_t offset; /* Offset from the start */
|
size_t offset; /* Offset from the start */
|
||||||
size_t length; /* Length of meaningful contents */
|
size_t length; /* Length of meaningful contents */
|
||||||
|
size_t unbit; /* Unused bits in the last byte */
|
||||||
size_t allocated; /* Allocated memory for data */
|
size_t allocated; /* Allocated memory for data */
|
||||||
int nreallocs; /* Number of data reallocations */
|
int nreallocs; /* Number of data reallocations */
|
||||||
off_t bytes_shifted; /* Number of bytes ever shifted */
|
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 *
|
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 char *fbuf;
|
||||||
static ssize_t fbuf_size;
|
static ssize_t fbuf_size;
|
||||||
static asn_codec_ctx_t s_codec_ctx;
|
static asn_codec_ctx_t s_codec_ctx;
|
||||||
asn_codec_ctx_t *opt_codec_ctx = 0;
|
asn_codec_ctx_t *opt_codec_ctx = 0;
|
||||||
void *structure = 0;
|
void *structure = 0;
|
||||||
asn_dec_rval_t rval;
|
asn_dec_rval_t rval;
|
||||||
|
size_t old_offset;
|
||||||
|
size_t new_offset;
|
||||||
size_t rd;
|
size_t rd;
|
||||||
|
|
||||||
if(!file) {
|
if(!file) {
|
||||||
fprintf(stderr, "%s: %s\n", filename, strerror(errno));
|
fprintf(stderr, "%s: %s\n", name, strerror(errno));
|
||||||
|
errno = EINVAL;
|
||||||
return 0;
|
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;
|
opt_codec_ctx = &s_codec_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("Processing %s", filename);
|
DEBUG("Processing %s", name);
|
||||||
|
|
||||||
/* prepare the file buffer */
|
/* prepare the file buffer */
|
||||||
if(fbuf_size != suggested_bufsize) {
|
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;
|
fbuf_size = suggested_bufsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicBuffer.offset = 0;
|
if(on_first_pdu) {
|
||||||
DynamicBuffer.length = 0;
|
DynamicBuffer.offset = 0;
|
||||||
DynamicBuffer.allocated = 0;
|
DynamicBuffer.length = 0;
|
||||||
DynamicBuffer.bytes_shifted = 0;
|
DynamicBuffer.unbit = 0;
|
||||||
DynamicBuffer.nreallocs = 0;
|
DynamicBuffer.allocated = 0;
|
||||||
|
DynamicBuffer.bytes_shifted = 0;
|
||||||
|
DynamicBuffer.nreallocs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
old_offset = DynamicBuffer.bytes_shifted + DynamicBuffer.offset;
|
||||||
|
|
||||||
/* Pretend immediate EOF */
|
/* Pretend immediate EOF */
|
||||||
rval.code = RC_WMORE;
|
rval.code = RC_WMORE;
|
||||||
rval.consumed = 0;
|
rval.consumed = 0;
|
||||||
|
|
||||||
while((rd = fread(fbuf, 1, fbuf_size, file)) || !feof(file)) {
|
while((rd = fread(fbuf, 1, fbuf_size, file)) || !feof(file)) {
|
||||||
|
int ecbits = 0; /* Extra consumed bits in case of PER */
|
||||||
char *i_bptr;
|
char *i_bptr;
|
||||||
size_t i_size;
|
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;
|
i_size = rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG("Decoding %ld bytes", (long)i_size);
|
||||||
|
|
||||||
switch(iform) {
|
switch(iform) {
|
||||||
case INP_BER:
|
case INP_BER:
|
||||||
rval = ber_decode(opt_codec_ctx, pduType,
|
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;
|
break;
|
||||||
case INP_PER:
|
case INP_PER:
|
||||||
rval = uper_decode(opt_codec_ctx, pduType,
|
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;
|
break;
|
||||||
}
|
}
|
||||||
DEBUG("decode(%ld) consumed %ld (%ld), code %d",
|
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) {
|
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) {
|
if(rval.code != RC_FAIL && rval.consumed < rd) {
|
||||||
|
DEBUG("Saving %d bytes", rd - rval.consumed);
|
||||||
add_bytes_to_buffer(fbuf + rval.consumed,
|
add_bytes_to_buffer(fbuf + rval.consumed,
|
||||||
rd - rval.consumed);
|
rd - rval.consumed);
|
||||||
rval.consumed = 0;
|
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) {
|
switch(rval.code) {
|
||||||
case RC_OK:
|
case RC_OK:
|
||||||
DEBUG("RC_OK, finishing up with %ld",
|
DEBUG("RC_OK, finishing up with %ld",
|
||||||
(long)rval.consumed);
|
(long)rval.consumed);
|
||||||
return structure;
|
return structure;
|
||||||
case RC_WMORE:
|
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",
|
DEBUG("RC_WMORE, continuing %ld with %ld..%ld..%ld",
|
||||||
(long)rval.consumed,
|
(long)rval.consumed,
|
||||||
(long)DynamicBuffer.offset,
|
(long)DynamicBuffer.offset,
|
||||||
(long)DynamicBuffer.length,
|
(long)DynamicBuffer.length,
|
||||||
(long)DynamicBuffer.allocated);
|
(long)DynamicBuffer.allocated);
|
||||||
rval.consumed = 0;
|
|
||||||
continue;
|
continue;
|
||||||
case RC_FAIL:
|
case RC_FAIL:
|
||||||
break;
|
break;
|
||||||
|
@ -449,13 +484,24 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *fi
|
||||||
/* Clean up partially decoded structure */
|
/* Clean up partially decoded structure */
|
||||||
ASN_STRUCT_FREE(*pduType, structure);
|
ASN_STRUCT_FREE(*pduType, structure);
|
||||||
|
|
||||||
fprintf(stderr, "%s: "
|
new_offset = DynamicBuffer.bytes_shifted + DynamicBuffer.offset;
|
||||||
"Decode failed past byte %ld: %s\n",
|
|
||||||
filename, (long)(DynamicBuffer.bytes_shifted
|
/*
|
||||||
+ DynamicBuffer.offset + rval.consumed),
|
* Print a message and return failure only if not EOF,
|
||||||
(rval.code == RC_WMORE)
|
* unless this is our first PDU (empty file).
|
||||||
? "Unexpected end of input"
|
*/
|
||||||
: "Input processing error");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,13 @@
|
||||||
#include <per_decoder.h>
|
#include <per_decoder.h>
|
||||||
|
|
||||||
asn_dec_rval_t
|
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_codec_ctx_t s_codec_ctx;
|
||||||
asn_per_data_t pd;
|
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
|
* Stack checker requires that the codec context
|
||||||
* must be allocated on the stack.
|
* 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 */
|
/* Fill in the position indicator */
|
||||||
pd.buffer = (const uint8_t *)buffer;
|
pd.buffer = (const uint8_t *)buffer;
|
||||||
pd.nboff = 0;
|
pd.nboff = skip_bits;
|
||||||
pd.nbits = 8 * size; /* 8 is CHAR_BIT from <limits.h> */
|
pd.nbits = 8 * size; /* 8 is CHAR_BIT from <limits.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 */
|
struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */
|
||||||
void **struct_ptr, /* Pointer to a target structure's pointer */
|
void **struct_ptr, /* Pointer to a target structure's pointer */
|
||||||
const void *buffer, /* Data to be decoded */
|
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 */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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.nbits = 8 * sizeof(po.tmpspace);
|
||||||
po.outper = cb;
|
po.outper = cb;
|
||||||
po.op_key = app_key;
|
po.op_key = app_key;
|
||||||
|
po.flushed_bytes = 0;
|
||||||
|
|
||||||
er = td->uper_encoder(td, 0, sptr, &po);
|
er = td->uper_encoder(td, 0, sptr, &po);
|
||||||
if(er.encoded != -1 && _uper_encode_flush_outp(&po))
|
if(er.encoded != -1) {
|
||||||
_ASN_ENCODE_FAILED;
|
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;
|
return er;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +62,6 @@ static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
|
||||||
asn_enc_rval_t
|
asn_enc_rval_t
|
||||||
uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) {
|
uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) {
|
||||||
enc_to_buf_arg key;
|
enc_to_buf_arg key;
|
||||||
asn_enc_rval_t er;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invoke type-specific encoder.
|
* 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);
|
ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);
|
||||||
|
|
||||||
er = uper_encode(td, sptr, encode_to_buffer_cb, &key);
|
return uper_encode(td, sptr, encode_to_buffer_cb, &key);
|
||||||
if(er.encoded != -1)
|
|
||||||
er.encoded = buffer_size - key.left;
|
|
||||||
return er;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -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->tmpspace[0] = po->buffer[0];
|
||||||
po->buffer = po->tmpspace;
|
po->buffer = po->tmpspace;
|
||||||
po->nbits = 8 * sizeof(po->tmpspace);
|
po->nbits = 8 * sizeof(po->tmpspace);
|
||||||
|
po->flushed_bytes += complete_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -76,7 +76,8 @@ typedef struct asn_per_outp_s {
|
||||||
size_t nbits; /* Number of bits left in (tmpspace) */
|
size_t nbits; /* Number of bits left in (tmpspace) */
|
||||||
uint8_t tmpspace[32]; /* Preliminary storage to hold data */
|
uint8_t tmpspace[32]; /* Preliminary storage to hold data */
|
||||||
int (*outper)(const void *data, size_t size, void *op_key);
|
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;
|
} asn_per_outp_t;
|
||||||
|
|
||||||
/* Output a small number of bits (<= 31) */
|
/* Output a small number of bits (<= 31) */
|
||||||
|
|
Loading…
Reference in New Issue