generic asn_decoder
diff --git a/skeletons/asn_application.c b/skeletons/asn_application.c
index 60c8e78..d7a2bcb 100644
--- a/skeletons/asn_application.c
+++ b/skeletons/asn_application.c
@@ -292,3 +292,51 @@
return er;
}
+
+asn_dec_rval_t
+asn_decode(const asn_codec_ctx_t *opt_codec_parameters,
+ enum asn_transfer_syntax syntax, struct asn_TYPE_descriptor_s *td,
+ void **sptr, const void *buffer, size_t size) {
+
+ (void)opt_codec_parameters;
+ asn_codec_ctx_t *opt_ctx = 0;
+
+ if(!td || !sptr || (size && !buffer)) {
+ ASN__DECODE_FAILED;
+ }
+
+ switch(syntax) {
+ case ATS_CER:
+ case ATS_NONSTANDARD_PLAINTEXT:
+ default:
+ errno = ENOENT;
+ ASN__DECODE_FAILED;
+
+ case ATS_DER:
+ case ATS_BER:
+ return ber_decode(opt_ctx, td, sptr, buffer, size);
+
+ case ATS_BASIC_OER:
+ case ATS_CANONICAL_OER:
+#ifdef ASN_DISABLE_OER_SUPPORT
+ errno = ENOENT;
+ ASN__DECODE_FAILED;
+#else
+ return oer_decode(opt_ctx, td, sptr, buffer, size);
+#endif
+
+ case ATS_UNALIGNED_BASIC_PER:
+ case ATS_UNALIGNED_CANONICAL_PER:
+#ifdef ASN_DISABLE_PER_SUPPORT
+ errno = ENOENT;
+ ASN__DECODE_FAILED;
+#else
+ return uper_decode_complete(opt_ctx, td, sptr, buffer, size);
+#endif
+
+ case ATS_BASIC_XER:
+ case ATS_CANONICAL_XER:
+ return xer_decode(opt_ctx, td, sptr, buffer, size);
+ }
+}
+
diff --git a/skeletons/asn_application.h b/skeletons/asn_application.h
index 0a24018..5fea20c 100644
--- a/skeletons/asn_application.h
+++ b/skeletons/asn_application.h
@@ -111,6 +111,17 @@
asn_app_consume_bytes_f *callback, void *callback_key);
+/*
+ * A generic decoder for any supported transfer syntax.
+ */
+asn_dec_rval_t asn_decode(
+ const asn_codec_ctx_t *opt_codec_parameters, enum asn_transfer_syntax,
+ struct asn_TYPE_descriptor_s *type_to_decode,
+ void **structure_ptr, /* Pointer to a target structure's pointer */
+ const void *buffer, /* Data to be decoded */
+ size_t size /* Size of that buffer */
+ );
+
/*
* A callback of this type is called whenever constraint validation fails
diff --git a/skeletons/converter-sample.c b/skeletons/converter-sample.c
index 81200aa..c95b0d0 100644
--- a/skeletons/converter-sample.c
+++ b/skeletons/converter-sample.c
@@ -54,7 +54,6 @@
int opt_debug; /* -d (or -dd) */
static int opt_check; /* -c (constraints checking) */
static int opt_stack; /* -s (maximum stack size) */
-static int opt_nopad; /* -per-nopad (PER input is not padded) */
static int opt_onepdu; /* -1 (decode single PDU) */
#ifdef JUNKTEST /* Enable -J <probability> */
@@ -242,10 +241,6 @@
}
break;
case 'p':
- if(strcmp(optarg, "er-nopad") == 0) {
- opt_nopad = 1;
- break;
- }
#ifdef ASN_PDU_COLLECTION
if(strcmp(optarg, "list") == 0) {
asn_TYPE_descriptor_t **pdu = asn_pdu_collection;
@@ -318,9 +313,6 @@
(sel->syntax == osyntax) ? " (DEFAULT)" : "");
}
}
- if(pduType->op->uper_decoder)
- fprintf(stderr,
- " -per-nopad Assume PER PDUs are not padded (-iper)\n");
#ifdef ASN_PDU_COLLECTION
fprintf(stderr,
" -p <PDU> Specify PDU type to decode\n"
@@ -655,6 +647,12 @@
(long)DynamicBuffer.allocated);
}
+static int
+restartability_supported(enum asn_transfer_syntax syntax) {
+ return (syntax != ATS_UNALIGNED_BASIC_PER
+ && syntax != ATS_UNALIGNED_CANONICAL_PER);
+}
+
static void *
data_decode_from_file(enum asn_transfer_syntax isyntax, asn_TYPE_descriptor_t *pduType, FILE *file, const char *name, ssize_t suggested_bufsize, int on_first_pdu) {
static uint8_t *fbuf;
@@ -734,66 +732,16 @@
junk_bytes_with_probability(i_bptr, i_size, opt_jprob);
#endif
- switch(isyntax) {
- case ATS_BER:
- case ATS_DER:
- rval = ber_decode(opt_codec_ctx, pduType,
- (void **)&structure, i_bptr, i_size);
- break;
- case ATS_BASIC_OER:
- case ATS_CANONICAL_OER:
-#ifdef ASN_DISABLE_OER_SUPPORT
- rval.code = RC_FAIL;
+ rval = asn_decode(opt_codec_ctx, isyntax, pduType, (void **)&structure,
+ i_bptr, i_size);
+ if(rval.code == RC_WMORE && !restartability_supported(isyntax)) {
+ /* PER does not support restartability */
+ ASN_STRUCT_FREE(*pduType, structure);
+ structure = 0;
rval.consumed = 0;
-#else
- rval = oer_decode(opt_codec_ctx, pduType,
- (void **)&structure, i_bptr, i_size);
-#endif
- break;
- case ATS_BASIC_XER:
- case ATS_CANONICAL_XER:
- rval = xer_decode(opt_codec_ctx, pduType,
- (void **)&structure, i_bptr, i_size);
- break;
- case ATS_UNALIGNED_BASIC_PER:
- case ATS_UNALIGNED_CANONICAL_PER:
-#ifdef ASN_DISABLE_PER_SUPPORT
- rval.code = RC_FAIL;
- rval.consumed = 0;
-#else
- if(opt_nopad)
- rval = uper_decode(opt_codec_ctx, pduType,
- (void **)&structure, i_bptr, i_size, 0,
- DynamicBuffer.unbits);
- else
- rval = uper_decode_complete(opt_codec_ctx, pduType,
- (void **)&structure, i_bptr, i_size);
-#endif
- switch(rval.code) {
- case RC_OK:
- /* Fall through */
- case RC_FAIL:
- if(opt_nopad) {
- /* uper_decode() returns bits! */
- /* Extra bits */
- ecbits = rval.consumed % 8;
- /* Convert into bytes! */
- rval.consumed /= 8;
- }
- break;
- case RC_WMORE:
- /* PER does not support restartability */
- ASN_STRUCT_FREE(*pduType, structure);
- structure = 0;
- rval.consumed = 0;
- /* Continue accumulating data */
- break;
- }
- break;
- default:
- rval.consumed = 0;
- /* Fall through */
+ /* Continue accumulating data */
}
+
DEBUG("decode(%ld) consumed %ld+%db (%ld), code %d",
(long)DynamicBuffer.length,
(long)rval.consumed, ecbits, (long)i_size,