port/merge Eurecom APER support from OPENAIRMME
Eurecom has developed APER support for asn1c as part of the OPENAIRMME
softare (a LTE MME). This is too important to let it bit-rout out
of asn1c. Let's forward-port and merge it.
diff --git a/skeletons/ANY.c b/skeletons/ANY.c
index 77024bd..128b550 100644
--- a/skeletons/ANY.c
+++ b/skeletons/ANY.c
@@ -21,7 +21,10 @@
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
ANY_encode_xer,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
0, 0, 0, 0,
0, /* No PER visible constraints */
@@ -87,6 +90,37 @@
return 0;
}
+int
+ANY_fromType_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
+ uint8_t *buffer = NULL;
+ ssize_t erval;
+
+ if(!st || !td) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if(!sptr) {
+ if(st->buf) FREEMEM(st->buf);
+ st->size = 0;
+ return 0;
+ }
+
+ erval = aper_encode_to_new_buffer(td, td->per_constraints, sptr, (void**)&buffer);
+
+ if(erval == -1) {
+ if(buffer) FREEMEM(buffer);
+ return -1;
+ }
+ assert((size_t)erval > 0);
+
+ if(st->buf) FREEMEM(st->buf);
+ st->buf = buffer;
+ st->size = erval;
+
+ return 0;
+}
+
ANY_t *
ANY_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) {
ANY_t tmp;
@@ -111,6 +145,30 @@
}
}
+ANY_t *
+ANY_new_fromType_aper(asn_TYPE_descriptor_t *td, void *sptr) {
+ ANY_t tmp;
+ ANY_t *st;
+
+ if(!td || !sptr) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ memset(&tmp, 0, sizeof(tmp));
+
+ if(ANY_fromType_aper(&tmp, td, sptr)) return 0;
+
+ st = (ANY_t *)CALLOC(1, sizeof(ANY_t));
+ if(st) {
+ *st = tmp;
+ return st;
+ } else {
+ FREEMEM(tmp.buf);
+ return 0;
+ }
+}
+
int
ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
asn_dec_rval_t rval;
@@ -138,6 +196,33 @@
}
}
+int
+ANY_to_type_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
+ asn_dec_rval_t rval;
+ void *newst = 0;
+
+ if(!st || !td || !struct_ptr) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if(st->buf == 0) {
+ /* Nothing to convert, make it empty. */
+ *struct_ptr = (void *)0;
+ return 0;
+ }
+
+ rval = aper_decode(0, td, (void **)&newst, st->buf, st->size, 0, 0);
+ if(rval.code == RC_OK) {
+ *struct_ptr = newst;
+ return 0;
+ } else {
+ /* Remove possibly partially decoded data. */
+ ASN_STRUCT_FREE(*td, newst);
+ return -1;
+ }
+}
+
static int ANY__consume_bytes(const void *buffer, size_t size, void *key) {
struct _callback_arg *arg = (struct _callback_arg *)key;
diff --git a/skeletons/ANY.h b/skeletons/ANY.h
index b7d92fa..a68441d 100644
--- a/skeletons/ANY.h
+++ b/skeletons/ANY.h
@@ -32,10 +32,13 @@
/* Convert another ASN.1 type into the ANY. This implies DER encoding. */
int ANY_fromType(ANY_t *, asn_TYPE_descriptor_t *td, void *struct_ptr);
+int ANY_fromType_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr);
ANY_t *ANY_new_fromType(asn_TYPE_descriptor_t *td, void *struct_ptr);
+ANY_t *ANY_new_fromType_aper(asn_TYPE_descriptor_t *td, void *sptr);
/* Convert the contents of the ANY type into the specified type. */
int ANY_to_type(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr);
+int ANY_to_type_aper(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr);
#define ANY_fromBuf(s, buf, size) OCTET_STRING_fromBuf((s), (buf), (size))
#define ANY_new_fromBuf(buf, size) OCTET_STRING_new_fromBuf( \
diff --git a/skeletons/BIT_STRING.c b/skeletons/BIT_STRING.c
index 997ff41..d32a12f 100644
--- a/skeletons/BIT_STRING.c
+++ b/skeletons/BIT_STRING.c
@@ -29,6 +29,8 @@
BIT_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Unaligned PER decoder */
OCTET_STRING_encode_uper, /* Unaligned PER encoder */
+ OCTET_STRING_decode_aper, /* Aligned PER decoder */
+ OCTET_STRING_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BIT_STRING_tags,
sizeof(asn_DEF_BIT_STRING_tags)
diff --git a/skeletons/BMPString.c b/skeletons/BMPString.c
index 8beaabd..aa248dc 100644
--- a/skeletons/BMPString.c
+++ b/skeletons/BMPString.c
@@ -35,6 +35,8 @@
BMPString_encode_xer, /* Convert to UTF-8 */
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper, /* Aligned PER decoder */
+ OCTET_STRING_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BMPString_tags,
sizeof(asn_DEF_BMPString_tags)
diff --git a/skeletons/BOOLEAN.c b/skeletons/BOOLEAN.c
index 6e55b3e..64d946a 100644
--- a/skeletons/BOOLEAN.c
+++ b/skeletons/BOOLEAN.c
@@ -24,6 +24,8 @@
BOOLEAN_encode_xer,
BOOLEAN_decode_uper, /* Unaligned PER decoder */
BOOLEAN_encode_uper, /* Unaligned PER encoder */
+ BOOLEAN_decode_aper, /* Aligned PER decoder */
+ BOOLEAN_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BOOLEAN_tags,
sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
@@ -264,6 +266,35 @@
return rv;
}
+asn_dec_rval_t
+BOOLEAN_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_dec_rval_t rv;
+ BOOLEAN_t *st = (BOOLEAN_t *)*sptr;
+
+ (void)opt_codec_ctx;
+ (void)constraints;
+
+ if(!st) {
+ st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st)));
+ if(!st) _ASN_DECODE_FAILED;
+ }
+
+ /*
+ * Extract a single bit
+ */
+ switch(per_get_few_bits(pd, 1)) {
+ case 1: *st = 1; break;
+ case 0: *st = 0; break;
+ case -1: default: _ASN_DECODE_STARVED;
+ }
+
+ ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
+
+ rv.code = RC_OK;
+ rv.consumed = 1;
+ return rv;
+}
asn_enc_rval_t
BOOLEAN_encode_uper(asn_TYPE_descriptor_t *td,
@@ -280,3 +311,18 @@
ASN__ENCODED_OK(er);
}
+
+asn_enc_rval_t
+BOOLEAN_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
+ asn_enc_rval_t er;
+
+ (void)constraints;
+
+ if(!st) _ASN_ENCODE_FAILED;
+
+ per_put_few_bits(po, *st ? 1 : 0, 1);
+
+ _ASN_ENCODED_OK(er);
+}
diff --git a/skeletons/BOOLEAN.h b/skeletons/BOOLEAN.h
index 217d0f1..8ea2892 100644
--- a/skeletons/BOOLEAN.h
+++ b/skeletons/BOOLEAN.h
@@ -28,6 +28,8 @@
xer_type_encoder_f BOOLEAN_encode_xer;
per_type_decoder_f BOOLEAN_decode_uper;
per_type_encoder_f BOOLEAN_encode_uper;
+per_type_decoder_f BOOLEAN_decode_aper;
+per_type_encoder_f BOOLEAN_encode_aper;
#ifdef __cplusplus
}
diff --git a/skeletons/ENUMERATED.c b/skeletons/ENUMERATED.c
index ccb003e..d19a5d3 100644
--- a/skeletons/ENUMERATED.c
+++ b/skeletons/ENUMERATED.c
@@ -26,6 +26,8 @@
INTEGER_encode_xer,
ENUMERATED_decode_uper, /* Unaligned PER decoder */
ENUMERATED_encode_uper, /* Unaligned PER encoder */
+ ENUMERATED_decode_aper, /* Aligned PER decoder */
+ ENUMERATED_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_ENUMERATED_tags,
sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]),
@@ -57,6 +59,27 @@
return rval;
}
+asn_dec_rval_t
+ENUMERATED_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_dec_rval_t rval;
+ ENUMERATED_t *st = (ENUMERATED_t *)*sptr;
+ long value;
+ void *vptr = &value;
+
+ if(!st) {
+ st = (ENUMERATED_t *)(*sptr = CALLOC(1, sizeof(*st)));
+ if(!st) _ASN_DECODE_FAILED;
+ }
+
+ rval = NativeEnumerated_decode_aper(opt_codec_ctx, td, constraints,
+ (void **)&vptr, pd);
+ if(rval.code == RC_OK)
+ if(asn_long2INTEGER(st, value))
+ rval.code = RC_FAIL;
+ return rval;
+}
+
asn_enc_rval_t
ENUMERATED_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
@@ -69,3 +92,14 @@
return NativeEnumerated_encode_uper(td, constraints, &value, po);
}
+asn_enc_rval_t
+ENUMERATED_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ ENUMERATED_t *st = (ENUMERATED_t *)sptr;
+ long value;
+
+ if(asn_INTEGER2long(st, &value))
+ _ASN_ENCODE_FAILED;
+
+ return NativeEnumerated_encode_aper(td, constraints, &value, po);
+}
diff --git a/skeletons/ENUMERATED.h b/skeletons/ENUMERATED.h
index 542dcae..5c4a2ed 100644
--- a/skeletons/ENUMERATED.h
+++ b/skeletons/ENUMERATED.h
@@ -17,6 +17,8 @@
per_type_decoder_f ENUMERATED_decode_uper;
per_type_encoder_f ENUMERATED_encode_uper;
+per_type_decoder_f ENUMERATED_decode_aper;
+per_type_encoder_f ENUMERATED_encode_aper;
#ifdef __cplusplus
}
diff --git a/skeletons/GeneralString.c b/skeletons/GeneralString.c
index c398d2b..934b8a2 100644
--- a/skeletons/GeneralString.c
+++ b/skeletons/GeneralString.c
@@ -24,6 +24,8 @@
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_GeneralString_tags,
sizeof(asn_DEF_GeneralString_tags)
diff --git a/skeletons/GeneralizedTime.c b/skeletons/GeneralizedTime.c
index 7e14477..9fd36d2 100644
--- a/skeletons/GeneralizedTime.c
+++ b/skeletons/GeneralizedTime.c
@@ -181,6 +181,8 @@
GeneralizedTime_encode_xer,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_GeneralizedTime_tags,
sizeof(asn_DEF_GeneralizedTime_tags)
diff --git a/skeletons/GraphicString.c b/skeletons/GraphicString.c
index e572ccd..5f62486 100644
--- a/skeletons/GraphicString.c
+++ b/skeletons/GraphicString.c
@@ -24,6 +24,8 @@
OCTET_STRING_encode_xer, /* Can't expect it to be ASCII/UTF8 */
OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_GraphicString_tags,
sizeof(asn_DEF_GraphicString_tags)
diff --git a/skeletons/IA5String.c b/skeletons/IA5String.c
index b856d30..766963c 100644
--- a/skeletons/IA5String.c
+++ b/skeletons/IA5String.c
@@ -29,6 +29,8 @@
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_IA5String_tags,
sizeof(asn_DEF_IA5String_tags)
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index eed8217..1107e20 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -30,6 +30,8 @@
#else
INTEGER_decode_uper, /* Unaligned PER decoder */
INTEGER_encode_uper, /* Unaligned PER encoder */
+ INTEGER_decode_aper,
+ INTEGER_encode_aper,
#endif /* ASN_DISABLE_PER_SUPPORT */
0, /* Use generic outmost tag fetcher */
asn_DEF_INTEGER_tags,
@@ -410,7 +412,7 @@
(asn_INTEGER_specifics_t *)
td->specifics, lstart, lstop);
if(el) {
- ASN_DEBUG("Found \"%s\" => %ld",
+ ASN_DEBUG("Found \"%s\" => %lld",
el->enum_name, el->nat_value);
dec_value = el->nat_value;
state = ST_END_ENUM;
@@ -608,7 +610,7 @@
if(uper_get_constrained_whole_number(pd,
&uvalue, ct->range_bits))
ASN__DECODE_STARVED;
- ASN_DEBUG("Got value %lu + low %ld",
+ ASN_DEBUG("Got value %lu + low %lld",
uvalue, ct->lower_bound);
uvalue += ct->lower_bound;
if(asn_ulong2INTEGER(st, uvalue))
@@ -665,6 +667,149 @@
return rval;
}
+asn_dec_rval_t
+INTEGER_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+ asn_dec_rval_t rval = { RC_OK, 0 };
+ INTEGER_t *st = (INTEGER_t *)*sptr;
+ asn_per_constraint_t *ct;
+ int repeat;
+
+ (void)opt_codec_ctx;
+
+ if(!st) {
+ st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
+ if(!st) _ASN_DECODE_FAILED;
+ }
+
+ if(!constraints) constraints = td->per_constraints;
+ ct = constraints ? &constraints->value : 0;
+
+ if(ct && ct->flags & APC_EXTENSIBLE) {
+ int inext = per_get_few_bits(pd, 1);
+ if(inext < 0) _ASN_DECODE_STARVED;
+ if(inext) ct = 0;
+ }
+
+ FREEMEM(st->buf);
+ st->buf = 0;
+ st->size = 0;
+ if(ct) {
+ if(ct->flags & APC_SEMI_CONSTRAINED) {
+ st->buf = (uint8_t *)CALLOC(1, 2);
+ if(!st->buf) _ASN_DECODE_FAILED;
+ st->size = 1;
+ } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
+ size_t size = (ct->range_bits + 7) >> 3;
+ st->buf = (uint8_t *)MALLOC(1 + size + 1);
+ if(!st->buf) _ASN_DECODE_FAILED;
+ st->size = size;
+ }
+ }
+
+ /* X.691, #12.2.2 */
+ if(ct && ct->flags != APC_UNCONSTRAINED) {
+ /* #10.5.6 */
+ ASN_DEBUG("Integer with range %d bits", ct->range_bits);
+ if(ct->range_bits >= 0) {
+ if (ct->range_bits > 16) {
+ int max_range_bytes = (ct->range_bits >> 3) + 1;
+ int length, i;
+ int64_t value = 0;
+
+ for (i = 0; i < max_range_bytes; i++) {
+ int upper = 1 << (i + 1);
+ if (upper > max_range_bytes)
+ break;
+ }
+ if ((length = per_get_few_bits(pd, i + 1)) < 0)
+ _ASN_DECODE_STARVED;
+ if (aper_get_align(pd) != 0)
+ _ASN_DECODE_STARVED;
+ ASN_DEBUG("Got length %d", length + 1);
+ for (i = 0; i < length + 1; i++) {
+ int buf = per_get_few_bits(pd, 8);
+ if (buf < 0)
+ _ASN_DECODE_STARVED;
+ value += (((int64_t)buf) << (8 * i));
+ }
+
+ if((specs && specs->field_unsigned)
+ ? asn_uint642INTEGER(st, value)
+ : asn_int642INTEGER(st, value))
+ _ASN_DECODE_FAILED;
+ ASN_DEBUG("Got value %lld + low %lld",
+ value, ct->lower_bound);
+ value += ct->lower_bound;
+ } else {
+ long value = 0;
+ if (ct->range_bits < 8) {
+ value = per_get_few_bits(pd, ct->range_bits);
+ if(value < 0) _ASN_DECODE_STARVED;
+ } else if (ct->range_bits == 8) {
+ if (aper_get_align(pd) < 0)
+ _ASN_DECODE_FAILED;
+ value = per_get_few_bits(pd, ct->range_bits);
+ if(value < 0) _ASN_DECODE_STARVED;
+ } else {
+ /* Align */
+ if (aper_get_align(pd) < 0)
+ _ASN_DECODE_FAILED;
+ value = per_get_few_bits(pd, 16);
+ if(value < 0) _ASN_DECODE_STARVED;
+ }
+ if((specs && specs->field_unsigned)
+ ? asn_ulong2INTEGER(st, value)
+ : asn_long2INTEGER(st, value))
+ _ASN_DECODE_FAILED;
+ ASN_DEBUG("Got value %ld + low %lld",
+ value, ct->lower_bound);
+ value += ct->lower_bound;
+ }
+ return rval;
+ } else {
+ _ASN_DECODE_FAILED;
+ }
+ } else {
+ ASN_DEBUG("Decoding unconstrained integer %s", td->name);
+ }
+
+ /* X.691, #12.2.3, #12.2.4 */
+ do {
+ ssize_t len;
+ void *p;
+ int ret;
+
+ /* Get the PER length */
+ len = aper_get_length(pd, -1, -1, &repeat);
+ if(len < 0) _ASN_DECODE_STARVED;
+
+ p = REALLOC(st->buf, st->size + len + 1);
+ if(!p) _ASN_DECODE_FAILED;
+ st->buf = (uint8_t *)p;
+
+ ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
+ if(ret < 0) _ASN_DECODE_STARVED;
+ st->size += len;
+ } while(repeat);
+ st->buf[st->size] = 0; /* JIC */
+
+ /* #12.2.3 */
+ if(ct && ct->lower_bound) {
+ /*
+ * TODO: replace by in-place arithmetics.
+ */
+ long value;
+ if(asn_INTEGER2long(st, &value))
+ _ASN_DECODE_FAILED;
+ if(asn_long2INTEGER(st, value + ct->lower_bound))
+ _ASN_DECODE_FAILED;
+ }
+
+ return rval;
+}
+
asn_enc_rval_t
INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
@@ -699,7 +844,7 @@
|| uval > (unsigned long)ct->upper_bound)
inext = 1;
}
- ASN_DEBUG("Value %lu (%02x/%d) lb %lu ub %lu %s",
+ ASN_DEBUG("Value %lu (%02x/%d) lb %llu ub %llu %s",
uval, st->buf[0], st->size,
ct->lower_bound, ct->upper_bound,
inext ? "ext" : "fix");
@@ -716,7 +861,7 @@
|| value > ct->upper_bound)
inext = 1;
}
- ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s",
+ ASN_DEBUG("Value %ld (%02x/%d) lb %lld ub %lld %s",
value, st->buf[0], st->size,
ct->lower_bound, ct->upper_bound,
inext ? "ext" : "fix");
@@ -743,7 +888,7 @@
}
if(ct && ct->lower_bound) {
- ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
+ ASN_DEBUG("Adjust lower bound to %lld", ct->lower_bound);
/* TODO: adjust lower bound */
ASN__ENCODE_FAILED;
}
@@ -762,6 +907,129 @@
#endif /* ASN_DISABLE_PER_SUPPORT */
+asn_enc_rval_t
+INTEGER_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+ asn_enc_rval_t er;
+ INTEGER_t *st = (INTEGER_t *)sptr;
+ const uint8_t *buf;
+ const uint8_t *end;
+ asn_per_constraint_t *ct;
+ int64_t value = 0;
+
+ if(!st || st->size == 0) _ASN_ENCODE_FAILED;
+
+ if(!constraints) constraints = td->per_constraints;
+ ct = constraints ? &constraints->value : 0;
+
+ er.encoded = 0;
+
+ if(ct) {
+ int inext = 0;
+ if(specs && specs->field_unsigned) {
+ uint64_t uval;
+ if(asn_INTEGER2uint64(st, &uval))
+ _ASN_ENCODE_FAILED;
+ /* Check proper range */
+ if(ct->flags & APC_SEMI_CONSTRAINED) {
+ if(uval < (unsigned long long)ct->lower_bound)
+ inext = 1;
+ } else if(ct->range_bits >= 0) {
+ if(uval < (unsigned long long)ct->lower_bound
+ || uval > (unsigned long long)ct->upper_bound)
+ inext = 1;
+ }
+ ASN_DEBUG("Value %llu (%02x/%d) lb %llu ub %llu %s",
+ uval, st->buf[0], st->size,
+ ct->lower_bound, ct->upper_bound,
+ inext ? "ext" : "fix");
+ value = uval;
+ } else {
+ if(asn_INTEGER2int64(st, &value)) _ASN_ENCODE_FAILED;
+ /* Check proper range */
+ if(ct->flags & APC_SEMI_CONSTRAINED) {
+ if(value < ct->lower_bound)
+ inext = 1;
+ } else if(ct->range_bits >= 0) {
+ if(value < ct->lower_bound
+ || value > ct->upper_bound)
+ inext = 1;
+ }
+ ASN_DEBUG("Value %lld (%02x/%d) lb %lld ub %lld %s",
+ value, st->buf[0], st->size,
+ ct->lower_bound, ct->upper_bound,
+ inext ? "ext" : "fix");
+ }
+ if(ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, inext, 1))
+ _ASN_ENCODE_FAILED;
+ if(inext) ct = 0;
+ } else if(inext) {
+ _ASN_ENCODE_FAILED;
+ }
+ }
+
+ /* X.691, #12.2.2 */
+ if(ct && ct->range_bits >= 0) {
+ /* #10.5.6 */
+ ASN_DEBUG("Encoding integer with range %d bits",
+ ct->range_bits);
+
+ /* #12 <= 8 -> alignment ? */
+ if (ct->range_bits < 8) {
+ if(per_put_few_bits(po, 0x00 | value, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+ } else if (ct->range_bits == 8) {
+ if(aper_put_align(po) < 0)
+ _ASN_ENCODE_FAILED;
+ if(per_put_few_bits(po, 0x00 | value, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+ } else if (ct->range_bits <= 16) {
+ // Consume the bytes to align on octet
+ if(aper_put_align(po) < 0)
+ _ASN_ENCODE_FAILED;
+ if(per_put_few_bits(po, 0x0000 | value,
+ 16))
+ _ASN_ENCODE_FAILED;
+ } else {
+ /* TODO: extend to >64 bits */
+ int64_t v = value;
+ int i;
+
+ /* Putting length - 1 in the minimum number of bits ex: 5 = 3bits */
+ if (per_put_few_bits(po, st->size - 1, (ct->range_bits >> 3)-1))
+ _ASN_ENCODE_FAILED;
+
+ // Consume the bits to align on octet
+ if (aper_put_align(po) < 0)
+ _ASN_ENCODE_FAILED;
+ /* Put the value */
+ for (i = 0; i < st->size; i++) {
+ if(per_put_few_bits(po, (v >> (8 * (st->size - i - 1))) & 0xff, 8)) _ASN_ENCODE_FAILED;
+ }
+ }
+ _ASN_ENCODED_OK(er);
+ }
+
+ if(ct && ct->lower_bound) {
+ ASN_DEBUG("Adjust lower bound to %lld", ct->lower_bound);
+ /* TODO: adjust lower bound */
+ _ASN_ENCODE_FAILED;
+ }
+
+ for(buf = st->buf, end = st->buf + st->size; buf < end;) {
+ ssize_t mayEncode = aper_put_length(po, -1, end - buf);
+ if(mayEncode < 0)
+ _ASN_ENCODE_FAILED;
+ if(per_put_many_bits(po, buf, 8 * mayEncode))
+ _ASN_ENCODE_FAILED;
+ buf += mayEncode;
+ }
+
+ _ASN_ENCODED_OK(er);
+}
+
int
asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
uint8_t *b, *end;
@@ -823,6 +1091,66 @@
}
int
+asn_INTEGER2int64(const INTEGER_t *iptr, int64_t *lptr) {
+ uint8_t *b, *end;
+ size_t size;
+ int64_t l;
+
+ /* Sanity checking */
+ if(!iptr || !iptr->buf || !lptr) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Cache the begin/end of the buffer */
+ b = iptr->buf; /* Start of the INTEGER buffer */
+ size = iptr->size;
+ end = b + size; /* Where to stop */
+
+ if(size > sizeof(int64_t)) {
+ uint8_t *end1 = end - 1;
+ /*
+ * Slightly more advanced processing,
+ * able to >sizeof(int64_t) bytes,
+ * when the actual value is small
+ * (0x0000000000abcdef would yield a fine 0x00abcdef)
+ */
+ /* Skip out the insignificant leading bytes */
+ for(; b < end1; b++) {
+ switch(*b) {
+ case 0x00: if((b[1] & 0x80) == 0) continue; break;
+ case 0xff: if((b[1] & 0x80) != 0) continue; break;
+ }
+ break;
+ }
+
+ size = end - b;
+ if(size > sizeof(int64_t)) {
+ /* Still cannot fit the int64_t */
+ errno = ERANGE;
+ return -1;
+ }
+ }
+
+ /* Shortcut processing of a corner case */
+ if(end == b) {
+ *lptr = 0;
+ return 0;
+ }
+
+ /* Perform the sign initialization */
+ /* Actually l = -(*b >> 7); gains nothing, yet unreadable! */
+ if((*b >> 7)) l = -1; else l = 0;
+
+ /* Conversion engine */
+ for(; b < end; b++)
+ l = (l << 8) | *b;
+
+ *lptr = l;
+ return 0;
+}
+
+int
asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) {
uint8_t *b, *end;
unsigned long l;
@@ -855,6 +1183,38 @@
}
int
+asn_INTEGER2uint64(const INTEGER_t *iptr, uint64_t *lptr) {
+ uint8_t *b, *end;
+ uint64_t l;
+ size_t size;
+
+ if(!iptr || !iptr->buf || !lptr) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ b = iptr->buf;
+ size = iptr->size;
+ end = b + size;
+
+ /* If all extra leading bytes are zeroes, ignore them */
+ for(; size > sizeof(uint64_t); b++, size--) {
+ if(*b) {
+ /* Value won't fit unsigned long */
+ errno = ERANGE;
+ return -1;
+ }
+ }
+
+ /* Conversion engine */
+ for(l = 0; b < end; b++)
+ l = (l << 8) | *b;
+
+ *lptr = l;
+ return 0;
+}
+
+int
asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
uint8_t *buf;
uint8_t *end;
@@ -880,6 +1240,86 @@
}
int
+asn_uint642INTEGER(INTEGER_t *st, uint64_t value) {
+ uint8_t *buf;
+ uint8_t *end;
+ uint8_t *b;
+ int shr;
+
+ if(value <= INT64_MAX)
+ return asn_int642INTEGER(st, value);
+
+ buf = (uint8_t *)MALLOC(1 + sizeof(value));
+ if(!buf) return -1;
+
+ end = buf + (sizeof(value) + 1);
+ buf[0] = 0;
+ for(b = buf + 1, shr = (sizeof(value)-1)*8; b < end; shr -= 8, b++)
+ *b = (uint8_t)(value >> shr);
+
+ if(st->buf) FREEMEM(st->buf);
+ st->buf = buf;
+ st->size = 1 + sizeof(value);
+
+ return 0;
+}
+
+int
+asn_int642INTEGER(INTEGER_t *st, int64_t value) {
+ uint8_t *buf, *bp;
+ uint8_t *p;
+ uint8_t *pstart;
+ uint8_t *pend1;
+ int littleEndian = 1; /* Run-time detection */
+ int add;
+
+ if(!st) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ buf = (uint8_t *)MALLOC(sizeof(value));
+ if(!buf) return -1;
+
+ if(*(char *)&littleEndian) {
+ pstart = (uint8_t *)&value + sizeof(value) - 1;
+ pend1 = (uint8_t *)&value;
+ add = -1;
+ } else {
+ pstart = (uint8_t *)&value;
+ pend1 = pstart + sizeof(value) - 1;
+ add = 1;
+ }
+
+ /*
+ * If the contents octet consists of more than one octet,
+ * then bits of the first octet and bit 8 of the second octet:
+ * a) shall not all be ones; and
+ * b) shall not all be zero.
+ */
+ for(p = pstart; p != pend1; p += add) {
+ switch(*p) {
+ case 0x00: if((*(p+add) & 0x80) == 0)
+ continue;
+ break;
+ case 0xff: if((*(p+add) & 0x80))
+ continue;
+ break;
+ }
+ break;
+ }
+ /* Copy the integer body */
+ for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)
+ *bp++ = *p;
+
+ if(st->buf) FREEMEM(st->buf);
+ st->buf = buf;
+ st->size = bp - buf;
+
+ return 0;
+}
+
+int
asn_long2INTEGER(INTEGER_t *st, long value) {
uint8_t *buf, *bp;
uint8_t *p;
diff --git a/skeletons/INTEGER.h b/skeletons/INTEGER.h
index 9a88097..5e0d94a 100644
--- a/skeletons/INTEGER.h
+++ b/skeletons/INTEGER.h
@@ -18,7 +18,7 @@
/* Map with <tag> to integer value association */
typedef struct asn_INTEGER_enum_map_s {
- long nat_value; /* associated native integer value */
+ int64_t nat_value; /* associated native integer value */
size_t enum_len; /* strlen("tag") */
const char *enum_name; /* "tag" */
} asn_INTEGER_enum_map_t;
@@ -41,6 +41,8 @@
xer_type_encoder_f INTEGER_encode_xer;
per_type_decoder_f INTEGER_decode_uper;
per_type_encoder_f INTEGER_encode_uper;
+per_type_decoder_f INTEGER_decode_aper;
+per_type_encoder_f INTEGER_encode_aper;
/***********************************
* Some handy conversion routines. *
@@ -52,8 +54,12 @@
* -1/ERANGE: Value encoded is out of range for long representation
* -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()).
*/
+int asn_INTEGER2int64(const INTEGER_t *i, int64_t *l);
+int asn_INTEGER2uint64(const INTEGER_t *i, uint64_t *l);
int asn_INTEGER2long(const INTEGER_t *i, long *l);
int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l);
+int asn_int642INTEGER(INTEGER_t *i, int64_t l);
+int asn_uint642INTEGER(INTEGER_t *i, uint64_t l);
int asn_long2INTEGER(INTEGER_t *i, long l);
int asn_ulong2INTEGER(INTEGER_t *i, unsigned long l);
diff --git a/skeletons/ISO646String.c b/skeletons/ISO646String.c
index 8d681c8..a6cc761 100644
--- a/skeletons/ISO646String.c
+++ b/skeletons/ISO646String.c
@@ -29,6 +29,8 @@
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_ISO646String_tags,
sizeof(asn_DEF_ISO646String_tags)
diff --git a/skeletons/NULL.c b/skeletons/NULL.c
index 62bc91e..a0da602 100644
--- a/skeletons/NULL.c
+++ b/skeletons/NULL.c
@@ -25,6 +25,8 @@
NULL_encode_xer,
NULL_decode_uper, /* Unaligned PER decoder */
NULL_encode_uper, /* Unaligned PER encoder */
+ NULL_decode_aper, /* Aligned PER decoder */
+ NULL_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_NULL_tags,
sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]),
@@ -136,6 +138,34 @@
return rv;
}
+asn_dec_rval_t
+NULL_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_dec_rval_t rv;
+
+ (void)opt_codec_ctx;
+ (void)td;
+ (void)constraints;
+ (void)pd;
+
+ if(!*sptr) {
+ *sptr = MALLOC(sizeof(NULL_t));
+ if(*sptr) {
+ *(NULL_t *)*sptr = 0;
+ } else {
+ _ASN_DECODE_FAILED;
+ }
+ }
+
+ /*
+ * NULL type does not have content octets.
+ */
+
+ rv.code = RC_OK;
+ rv.consumed = 0;
+ return rv;
+}
+
asn_enc_rval_t
NULL_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
void *sptr, asn_per_outp_t *po) {
@@ -149,3 +179,17 @@
er.encoded = 0;
ASN__ENCODED_OK(er);
}
+
+asn_enc_rval_t
+NULL_encode_aper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void *sptr, asn_per_outp_t *po) {
+ asn_enc_rval_t er;
+
+ (void)td;
+ (void)constraints;
+ (void)sptr;
+ (void)po;
+
+ er.encoded = 0;
+ _ASN_ENCODED_OK(er);
+}
diff --git a/skeletons/NULL.h b/skeletons/NULL.h
index 131e775..90784d8 100644
--- a/skeletons/NULL.h
+++ b/skeletons/NULL.h
@@ -25,6 +25,8 @@
xer_type_encoder_f NULL_encode_xer;
per_type_decoder_f NULL_decode_uper;
per_type_encoder_f NULL_encode_uper;
+per_type_decoder_f NULL_decode_aper;
+per_type_encoder_f NULL_encode_aper;
#ifdef __cplusplus
}
diff --git a/skeletons/NativeEnumerated.c b/skeletons/NativeEnumerated.c
index 78366af..5b427ab 100644
--- a/skeletons/NativeEnumerated.c
+++ b/skeletons/NativeEnumerated.c
@@ -30,6 +30,8 @@
NativeEnumerated_encode_xer,
NativeEnumerated_decode_uper,
NativeEnumerated_encode_uper,
+ NativeEnumerated_decode_aper,
+ NativeEnumerated_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeEnumerated_tags,
sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
@@ -125,6 +127,61 @@
return rval;
}
+asn_dec_rval_t
+NativeEnumerated_decode_aper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void **sptr, asn_per_data_t *pd) {
+ asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
+ asn_dec_rval_t rval = { RC_OK, 0 };
+ long *native = (long *)*sptr;
+ asn_per_constraint_t *ct;
+ long value;
+
+ (void)opt_codec_ctx;
+
+ if(constraints) ct = &constraints->value;
+ else if(td->per_constraints) ct = &td->per_constraints->value;
+ else _ASN_DECODE_FAILED; /* Mandatory! */
+ if(!specs) _ASN_DECODE_FAILED;
+
+ if(!native) {
+ native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
+ if(!native) _ASN_DECODE_FAILED;
+ }
+
+ ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
+
+ if(ct->flags & APC_EXTENSIBLE) {
+ int inext = per_get_few_bits(pd, 1);
+ if(inext < 0) _ASN_DECODE_STARVED;
+ if(inext) ct = 0;
+ }
+
+ if(ct && ct->range_bits >= 0) {
+ value = per_get_few_bits(pd, ct->range_bits);
+ if(value < 0) _ASN_DECODE_STARVED;
+ if(value >= (specs->extension
+ ? specs->extension - 1 : specs->map_count))
+ _ASN_DECODE_FAILED;
+ } else {
+ if(!specs->extension)
+ _ASN_DECODE_FAILED;
+ /*
+ * X.691, #10.6: normally small non-negative whole number;
+ */
+ value = uper_get_nsnnwn(pd);
+ if(value < 0) _ASN_DECODE_STARVED;
+ value += specs->extension - 1;
+ if(value >= specs->map_count)
+ _ASN_DECODE_FAILED;
+ }
+
+ *native = specs->value2enum[value].nat_value;
+ ASN_DEBUG("Decoded %s = %ld", td->name, *native);
+
+ return rval;
+}
+
static int
NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
const asn_INTEGER_enum_map_t *a = ap;
@@ -205,3 +262,72 @@
ASN__ENCODED_OK(er);
}
+asn_enc_rval_t
+NativeEnumerated_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
+ asn_enc_rval_t er;
+ long native, value;
+ asn_per_constraint_t *ct;
+ int inext = 0;
+ asn_INTEGER_enum_map_t key;
+ asn_INTEGER_enum_map_t *kf;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+ if(!specs) _ASN_ENCODE_FAILED;
+
+ if(constraints) ct = &constraints->value;
+ else if(td->per_constraints) ct = &td->per_constraints->value;
+ else _ASN_ENCODE_FAILED; /* Mandatory! */
+
+ ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
+
+ er.encoded = 0;
+
+ native = *(long *)sptr;
+ if(native < 0) _ASN_ENCODE_FAILED;
+
+ key.nat_value = native;
+ kf = bsearch(&key, specs->value2enum, specs->map_count,
+ sizeof(key), NativeEnumerated__compar_value2enum);
+ if(!kf) {
+ ASN_DEBUG("No element corresponds to %ld", native);
+ _ASN_ENCODE_FAILED;
+ }
+ value = kf - specs->value2enum;
+
+ if(ct->range_bits >= 0) {
+ int cmpWith = specs->extension
+ ? specs->extension - 1 : specs->map_count;
+ if(value >= cmpWith)
+ inext = 1;
+ }
+ if(ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, inext, 1))
+ _ASN_ENCODE_FAILED;
+ if(inext) ct = 0;
+ } else if(inext) {
+ _ASN_ENCODE_FAILED;
+ }
+
+ if(ct && ct->range_bits >= 0) {
+ if(per_put_few_bits(po, value, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+ _ASN_ENCODED_OK(er);
+ }
+
+ if(!specs->extension)
+ _ASN_ENCODE_FAILED;
+
+ /*
+ * X.691, #10.6: normally small non-negative whole number;
+ */
+ ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
+ value, specs->extension, inext,
+ value - (inext ? (specs->extension - 1) : 0));
+ if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
+ _ASN_ENCODE_FAILED;
+
+ _ASN_ENCODED_OK(er);
+}
+
diff --git a/skeletons/NativeEnumerated.h b/skeletons/NativeEnumerated.h
index c59bb1b..95f0531 100644
--- a/skeletons/NativeEnumerated.h
+++ b/skeletons/NativeEnumerated.h
@@ -24,6 +24,8 @@
xer_type_encoder_f NativeEnumerated_encode_xer;
per_type_decoder_f NativeEnumerated_decode_uper;
per_type_encoder_f NativeEnumerated_encode_uper;
+per_type_decoder_f NativeEnumerated_decode_aper;
+per_type_encoder_f NativeEnumerated_encode_aper;
#ifdef __cplusplus
}
diff --git a/skeletons/NativeInteger.c b/skeletons/NativeInteger.c
index e8ce6d2..157d40a 100644
--- a/skeletons/NativeInteger.c
+++ b/skeletons/NativeInteger.c
@@ -31,6 +31,8 @@
NativeInteger_encode_xer,
NativeInteger_decode_uper, /* Unaligned PER decoder */
NativeInteger_encode_uper, /* Unaligned PER encoder */
+ NativeInteger_decode_aper, /* Aligned PER decoder */
+ NativeInteger_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeInteger_tags,
sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
@@ -267,6 +269,42 @@
return rval;
}
+asn_dec_rval_t
+NativeInteger_decode_aper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+ asn_dec_rval_t rval;
+ long *native = (long *)*sptr;
+ INTEGER_t tmpint;
+ void *tmpintptr = &tmpint;
+
+ (void)opt_codec_ctx;
+ ASN_DEBUG("Decoding NativeInteger %s (APER)", td->name);
+
+ if(!native) {
+ native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
+ if(!native) _ASN_DECODE_FAILED;
+ }
+
+ memset(&tmpint, 0, sizeof tmpint);
+ rval = INTEGER_decode_aper(opt_codec_ctx, td, constraints,
+ &tmpintptr, pd);
+ if(rval.code == RC_OK) {
+ if((specs&&specs->field_unsigned)
+ ? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
+ : asn_INTEGER2long(&tmpint, native))
+ rval.code = RC_FAIL;
+ else
+ ASN_DEBUG("NativeInteger %s got value %ld",
+ td->name, *native);
+ }
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
+
+ return rval;
+}
+
asn_enc_rval_t
NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
@@ -291,6 +329,32 @@
return er;
}
+asn_enc_rval_t
+NativeInteger_encode_aper(
+ asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+ asn_enc_rval_t er;
+ long native;
+ INTEGER_t tmpint;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+
+ native = *(long *)sptr;
+
+ ASN_DEBUG("Encoding NativeInteger %s %ld (APER)", td->name, native);
+
+ memset(&tmpint, 0, sizeof(tmpint));
+ if((specs&&specs->field_unsigned)
+ ? asn_ulong2INTEGER(&tmpint, native)
+ : asn_long2INTEGER(&tmpint, native))
+ _ASN_ENCODE_FAILED;
+ er = INTEGER_encode_aper(td, constraints, &tmpint, po);
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
+ return er;
+}
+
/*
* INTEGER specific human-readable output.
*/
diff --git a/skeletons/NativeInteger.h b/skeletons/NativeInteger.h
index 4e63a83..14aa1a4 100644
--- a/skeletons/NativeInteger.h
+++ b/skeletons/NativeInteger.h
@@ -29,6 +29,8 @@
xer_type_encoder_f NativeInteger_encode_xer;
per_type_decoder_f NativeInteger_decode_uper;
per_type_encoder_f NativeInteger_encode_uper;
+per_type_decoder_f NativeInteger_decode_aper;
+per_type_encoder_f NativeInteger_encode_aper;
#ifdef __cplusplus
}
diff --git a/skeletons/NativeReal.c b/skeletons/NativeReal.c
index ad6f28c..7db8bae 100644
--- a/skeletons/NativeReal.c
+++ b/skeletons/NativeReal.c
@@ -32,6 +32,8 @@
NativeReal_encode_xer,
NativeReal_decode_uper,
NativeReal_encode_uper,
+ NativeReal_decode_aper,
+ NativeReal_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeReal_tags,
sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
@@ -228,6 +230,43 @@
return rval;
}
+asn_dec_rval_t
+NativeReal_decode_aper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void **dbl_ptr, asn_per_data_t *pd) {
+ double *Dbl = (double *)*dbl_ptr;
+ asn_dec_rval_t rval;
+ REAL_t tmp;
+ void *ptmp = &tmp;
+ int ret;
+
+ (void)constraints;
+
+ /*
+ * If the structure is not there, allocate it.
+ */
+ if(Dbl == NULL) {
+ *dbl_ptr = CALLOC(1, sizeof(*Dbl));
+ Dbl = (double *)*dbl_ptr;
+ if(Dbl == NULL)
+ _ASN_DECODE_FAILED;
+ }
+
+ memset(&tmp, 0, sizeof(tmp));
+ rval = OCTET_STRING_decode_aper(opt_codec_ctx, td, NULL,
+ &ptmp, pd);
+ if(rval.code != RC_OK) {
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
+ return rval;
+ }
+
+ ret = asn_REAL2double(&tmp, Dbl);
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
+ if(ret) _ASN_DECODE_FAILED;
+
+ return rval;
+}
+
/*
* Encode the NativeReal using the OCTET STRING PER encoder.
*/
@@ -257,6 +296,32 @@
return erval;
}
+asn_enc_rval_t
+NativeReal_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ double Dbl = *(const double *)sptr;
+ asn_enc_rval_t erval;
+ REAL_t tmp;
+
+ (void)constraints;
+
+ /* Prepare a temporary clean structure */
+ memset(&tmp, 0, sizeof(tmp));
+
+ if(asn_double2REAL(&tmp, Dbl))
+ _ASN_ENCODE_FAILED;
+
+ /* Encode a DER REAL */
+ erval = OCTET_STRING_encode_aper(td, NULL, &tmp, po);
+ if(erval.encoded == -1)
+ erval.structure_ptr = sptr;
+
+ /* Free possibly allocated members of the temporary structure */
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
+
+ return erval;
+}
+
/*
* Decode the chunk of XML text encoding REAL.
*/
diff --git a/skeletons/NativeReal.h b/skeletons/NativeReal.h
index 68a81d9..94ed9de 100644
--- a/skeletons/NativeReal.h
+++ b/skeletons/NativeReal.h
@@ -27,6 +27,8 @@
xer_type_encoder_f NativeReal_encode_xer;
per_type_decoder_f NativeReal_decode_uper;
per_type_encoder_f NativeReal_encode_uper;
+per_type_decoder_f NativeReal_decode_aper;
+per_type_encoder_f NativeReal_encode_aper;
#ifdef __cplusplus
}
diff --git a/skeletons/NumericString.c b/skeletons/NumericString.c
index 887b3f5..1ed6316 100644
--- a/skeletons/NumericString.c
+++ b/skeletons/NumericString.c
@@ -49,6 +49,8 @@
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_NumericString_tags,
sizeof(asn_DEF_NumericString_tags)
diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c
index d0f8b31..8a78265 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -27,6 +27,8 @@
OBJECT_IDENTIFIER_encode_xer,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_OBJECT_IDENTIFIER_tags,
sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c
index 5420ded..c667e8f 100644
--- a/skeletons/OCTET_STRING.c
+++ b/skeletons/OCTET_STRING.c
@@ -36,6 +36,8 @@
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Unaligned PER decoder */
OCTET_STRING_encode_uper, /* Unaligned PER encoder */
+ OCTET_STRING_decode_aper, /* Aligned PER decoder */
+ OCTET_STRING_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_OCTET_STRING_tags,
sizeof(asn_DEF_OCTET_STRING_tags)
@@ -1194,14 +1196,14 @@
static int
OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
size_t units, unsigned int bpc, unsigned int unit_bits,
- long lb, long ub, asn_per_constraints_t *pc) {
+ int64_t lb, int64_t ub, asn_per_constraints_t *pc) {
uint8_t *end = buf + units * bpc;
- ASN_DEBUG("Expanding %d characters into (%ld..%ld):%d",
+ ASN_DEBUG("Expanding %d characters into (%lld..%lld):%d",
(int)units, lb, ub, unit_bits);
/* X.691: 27.5.4 */
- if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
+ if((uint64_t)ub <= ((uint64_t)2 << (unit_bits - 1))) {
/* Decode without translation */
lb = 0;
} else if(pc && pc->code2value) {
@@ -1216,7 +1218,7 @@
value = pc->code2value(code);
if(value < 0) {
ASN_DEBUG("Code %d (0x%02x) is"
- " not in map (%ld..%ld)",
+ " not in map (%lld..%lld)",
code, code, lb, ub);
return 1; /* FATAL */
}
@@ -1240,7 +1242,7 @@
int ch = code + lb;
if(code < 0) return -1; /* WMORE */
if(ch > ub) {
- ASN_DEBUG("Code %d is out of range (%ld..%ld)",
+ ASN_DEBUG("Code %d is out of range (%lld..%lld)",
ch, lb, ub);
return 1; /* FATAL */
}
@@ -1258,14 +1260,14 @@
static int
OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
size_t units, unsigned int bpc, unsigned int unit_bits,
- long lb, long ub, asn_per_constraints_t *pc) {
+ int64_t lb, int64_t ub, asn_per_constraints_t *pc) {
const uint8_t *end = buf + units * bpc;
- ASN_DEBUG("Squeezing %d characters into (%ld..%ld):%d (%d bpc)",
+ ASN_DEBUG("Squeezing %d characters into (%lld..%lld):%d (%d bpc)",
(int)units, lb, ub, unit_bits, bpc);
/* X.691: 27.5.4 */
- if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
+ if((uint64_t)ub <= ((uint64_t)2 << (unit_bits - 1))) {
/* Encode as is */
lb = 0;
} else if(pc && pc->value2code) {
@@ -1282,7 +1284,7 @@
code = pc->value2code(value);
if(code < 0) {
ASN_DEBUG("Character %d (0x%02x) is"
- " not in map (%ld..%ld)",
+ " not in map (%lld..%lld)",
*buf, *buf, lb, ub);
return -1;
}
@@ -1309,7 +1311,7 @@
ch = value - lb;
if(ch < 0 || ch > ub) {
ASN_DEBUG("Character %d (0x%02x)"
- " is out of range (%ld..%ld)",
+ " is out of range (%lld..%lld)",
*buf, *buf, lb, ub + lb);
return -1;
}
@@ -1392,7 +1394,7 @@
if(!st) RETURN(RC_FAIL);
}
- ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
+ ASN_DEBUG("PER Decoding %s size %lld .. %lld bits %d",
csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
@@ -1423,14 +1425,14 @@
if(csiz->effective_bits == 0) {
int ret;
if(bpc) {
- ASN_DEBUG("Encoding OCTET STRING size %ld",
+ ASN_DEBUG("Encoding OCTET STRING size %lld",
csiz->upper_bound);
ret = OCTET_STRING_per_get_characters(pd, st->buf,
csiz->upper_bound, bpc, unit_bits,
cval->lower_bound, cval->upper_bound, pc);
if(ret > 0) RETURN(RC_FAIL);
} else {
- ASN_DEBUG("Encoding BIT STRING size %ld",
+ ASN_DEBUG("Encoding BIT STRING size %lld",
csiz->upper_bound);
ret = per_get_many_bits(pd, st->buf, 0,
unit_bits * csiz->upper_bound);
@@ -1492,6 +1494,194 @@
return rval;
}
+asn_dec_rval_t
+OCTET_STRING_decode_aper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void **sptr, asn_per_data_t *pd) {
+
+ asn_OCTET_STRING_specifics_t *specs = td->specifics
+ ? (asn_OCTET_STRING_specifics_t *)td->specifics
+ : &asn_DEF_OCTET_STRING_specs;
+ asn_per_constraints_t *pc = constraints ? constraints
+ : td->per_constraints;
+ asn_per_constraint_t *cval;
+ asn_per_constraint_t *csiz;
+ asn_dec_rval_t rval = { RC_OK, 0 };
+ BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
+ ssize_t consumed_myself = 0;
+ int repeat;
+ enum {
+ OS__BPC_BIT = 0,
+ OS__BPC_CHAR = 1,
+ OS__BPC_U16 = 2,
+ OS__BPC_U32 = 4
+ } bpc; /* Bytes per character */
+ unsigned int unit_bits;
+ unsigned int canonical_unit_bits;
+
+ (void)opt_codec_ctx;
+
+ if(pc) {
+ cval = &pc->value;
+ csiz = &pc->size;
+ } else {
+ cval = &asn_DEF_OCTET_STRING_constraints.value;
+ csiz = &asn_DEF_OCTET_STRING_constraints.size;
+ }
+
+ switch(specs->subvariant) {
+ default:
+// case ASN_OSUBV_ANY:
+// ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
+// RETURN(RC_FAIL);
+ case ASN_OSUBV_BIT:
+ canonical_unit_bits = unit_bits = 1;
+ bpc = OS__BPC_BIT;
+ break;
+ case ASN_OSUBV_ANY:
+ case ASN_OSUBV_STR:
+ canonical_unit_bits = unit_bits = 8;
+// if(cval->flags & APC_CONSTRAINED)
+// unit_bits = cval->range_bits;
+ bpc = OS__BPC_CHAR;
+ break;
+ case ASN_OSUBV_U16:
+ canonical_unit_bits = unit_bits = 16;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_U16;
+ break;
+ case ASN_OSUBV_U32:
+ canonical_unit_bits = unit_bits = 32;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_U32;
+ break;
+ }
+
+ /*
+ * Allocate the string.
+ */
+ if(!st) {
+ st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
+ if(!st) RETURN(RC_FAIL);
+ }
+
+ ASN_DEBUG("PER Decoding %s size %lld .. %lld bits %d",
+ csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
+ csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
+
+ if(csiz->flags & APC_EXTENSIBLE) {
+ int inext = per_get_few_bits(pd, 1);
+ if(inext < 0) RETURN(RC_WMORE);
+ if(inext) {
+ csiz = &asn_DEF_OCTET_STRING_constraints.size;
+ cval = &asn_DEF_OCTET_STRING_constraints.value;
+ unit_bits = canonical_unit_bits;
+ }
+ }
+
+ if(csiz->effective_bits >= 0) {
+ FREEMEM(st->buf);
+ if(bpc) {
+ st->size = csiz->upper_bound * bpc;
+ } else {
+ st->size = (csiz->upper_bound + 7) >> 3;
+ }
+ st->buf = (uint8_t *)MALLOC(st->size + 1);
+ if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
+ }
+
+ /* X.691, #16.5: zero-length encoding */
+ /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
+ /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
+ if(csiz->effective_bits == 0) {
+ int ret;
+ if (st->size > 2) { /* X.691 #16 NOTE 1 */
+ if (aper_get_align(pd) < 0)
+ RETURN(RC_FAIL);
+ }
+ if(bpc) {
+ ASN_DEBUG("Decoding OCTET STRING size %lld",
+ csiz->upper_bound);
+ ret = OCTET_STRING_per_get_characters(pd, st->buf,
+ csiz->upper_bound, bpc, unit_bits,
+ cval->lower_bound, cval->upper_bound, pc);
+ if(ret > 0) RETURN(RC_FAIL);
+ } else {
+ ASN_DEBUG("Decoding BIT STRING size %lld",
+ csiz->upper_bound);
+ ret = per_get_many_bits(pd, st->buf, 0,
+ unit_bits * csiz->upper_bound);
+ }
+ if(ret < 0) RETURN(RC_WMORE);
+ consumed_myself += unit_bits * csiz->upper_bound;
+ st->buf[st->size] = 0;
+ if(bpc == 0) {
+ int ubs = (csiz->upper_bound & 0x7);
+ st->bits_unused = ubs ? 8 - ubs : 0;
+ }
+ RETURN(RC_OK);
+ }
+
+ st->size = 0;
+ do {
+ ssize_t raw_len;
+ ssize_t len_bytes;
+ ssize_t len_bits;
+ void *p;
+ int ret;
+
+ /* Get the PER length */
+ if (csiz->upper_bound - csiz->lower_bound == 0)
+ // Indefinite length case
+ raw_len = aper_get_length(pd, -1, csiz->effective_bits, &repeat);
+ else
+ raw_len = aper_get_length(pd, csiz->upper_bound - csiz->lower_bound + 1, csiz->effective_bits, &repeat);
+ repeat = 0;
+ if(raw_len < 0) RETURN(RC_WMORE);
+ raw_len += csiz->lower_bound;
+
+ ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
+ (long)csiz->effective_bits, (long)raw_len,
+ repeat ? "repeat" : "once", td->name);
+
+ if (raw_len > 2) { /* X.691 #16 NOTE 1 */
+ if (aper_get_align(pd) < 0)
+ RETURN(RC_FAIL);
+ }
+
+ if(bpc) {
+ len_bytes = raw_len * bpc;
+ len_bits = len_bytes * unit_bits;
+ } else {
+ len_bits = raw_len;
+ len_bytes = (len_bits + 7) >> 3;
+ if(len_bits & 0x7)
+ st->bits_unused = 8 - (len_bits & 0x7);
+ /* len_bits be multiple of 16K if repeat is set */
+ }
+ p = REALLOC(st->buf, st->size + len_bytes + 1);
+ if(!p) RETURN(RC_FAIL);
+ st->buf = (uint8_t *)p;
+
+ if(bpc) {
+ ret = OCTET_STRING_per_get_characters(pd,
+ &st->buf[st->size], raw_len, bpc, unit_bits,
+ cval->lower_bound, cval->upper_bound, pc);
+ if(ret > 0) RETURN(RC_FAIL);
+ } else {
+ ret = per_get_many_bits(pd, &st->buf[st->size],
+ 0, len_bits);
+ }
+ if(ret < 0) RETURN(RC_WMORE);
+ st->size += len_bytes;
+ } while(repeat);
+ st->buf[st->size] = 0; /* nul-terminate */
+
+ return rval;
+}
+
asn_enc_rval_t
OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
@@ -1566,7 +1756,7 @@
}
ASN_DEBUG("Encoding %s into %d units of %d bits"
- " (%ld..%ld, effective %d)%s",
+ " (%lld..%lld, effective %d)%s",
td->name, sizeinunits, unit_bits,
csiz->lower_bound, csiz->upper_bound,
csiz->effective_bits, ct_extensible ? " EXT" : "");
@@ -1598,7 +1788,7 @@
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
if(csiz->effective_bits >= 0) {
- ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits",
+ ASN_DEBUG("Encoding %d bytes (%lld), length in %d bits",
st->size, sizeinunits - csiz->lower_bound,
csiz->effective_bits);
ret = per_put_few_bits(po, sizeinunits - csiz->lower_bound,
@@ -1652,6 +1842,173 @@
ASN__ENCODED_OK(er);
}
+asn_enc_rval_t
+OCTET_STRING_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+
+ asn_OCTET_STRING_specifics_t *specs = td->specifics
+ ? (asn_OCTET_STRING_specifics_t *)td->specifics
+ : &asn_DEF_OCTET_STRING_specs;
+ asn_per_constraints_t *pc = constraints ? constraints
+ : td->per_constraints;
+ asn_per_constraint_t *cval;
+ asn_per_constraint_t *csiz;
+ const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
+ asn_enc_rval_t er = { 0, 0, 0 };
+ int inext = 0; /* Lies not within extension root */
+ unsigned int unit_bits;
+ unsigned int canonical_unit_bits;
+ unsigned int sizeinunits;
+ const uint8_t *buf;
+ int ret;
+ enum {
+ OS__BPC_BIT = 0,
+ OS__BPC_CHAR = 1,
+ OS__BPC_U16 = 2,
+ OS__BPC_U32 = 4
+ } bpc; /* Bytes per character */
+ int ct_extensible;
+
+ if(!st || (!st->buf && st->size))
+ _ASN_ENCODE_FAILED;
+
+ if(pc) {
+ cval = &pc->value;
+ csiz = &pc->size;
+ } else {
+ cval = &asn_DEF_OCTET_STRING_constraints.value;
+ csiz = &asn_DEF_OCTET_STRING_constraints.size;
+ }
+ ct_extensible = csiz->flags & APC_EXTENSIBLE;
+
+ switch(specs->subvariant) {
+ default:
+// case ASN_OSUBV_ANY:
+// _ASN_ENCODE_FAILED;
+ case ASN_OSUBV_BIT:
+ canonical_unit_bits = unit_bits = 1;
+ bpc = OS__BPC_BIT;
+ sizeinunits = st->size * 8 - (st->bits_unused & 0x07);
+ ASN_DEBUG("BIT STRING of %d bytes",
+ sizeinunits);
+ break;
+ case ASN_OSUBV_ANY:
+ case ASN_OSUBV_STR:
+ canonical_unit_bits = unit_bits = 8;
+// if(cval->flags & APC_CONSTRAINED)
+// unit_bits = 8;
+ bpc = OS__BPC_CHAR;
+ sizeinunits = st->size;
+ break;
+ case ASN_OSUBV_U16:
+ canonical_unit_bits = unit_bits = 16;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_U16;
+ sizeinunits = st->size / 2;
+ break;
+ case ASN_OSUBV_U32:
+ canonical_unit_bits = unit_bits = 32;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_U32;
+ sizeinunits = st->size / 4;
+ break;
+ }
+
+ ASN_DEBUG("Encoding %s into %d units of %d bits"
+ " (%lld..%lld, effective %d)%s",
+ td->name, sizeinunits, unit_bits,
+ csiz->lower_bound, csiz->upper_bound,
+ csiz->effective_bits, ct_extensible ? " EXT" : "");
+
+ /* Figure out wheter size lies within PER visible constraint */
+
+ if(csiz->effective_bits >= 0) {
+ if((int)sizeinunits < csiz->lower_bound
+ || (int)sizeinunits > csiz->upper_bound) {
+ if(ct_extensible) {
+ cval = &asn_DEF_OCTET_STRING_constraints.value;
+ csiz = &asn_DEF_OCTET_STRING_constraints.size;
+ unit_bits = canonical_unit_bits;
+ inext = 1;
+ } else
+ _ASN_ENCODE_FAILED;
+ }
+ } else {
+ inext = 0;
+ }
+
+
+ if(ct_extensible) {
+ /* Declare whether length is [not] within extension root */
+ if(per_put_few_bits(po, inext, 1))
+ _ASN_ENCODE_FAILED;
+ }
+
+ /* X.691, #16.5: zero-length encoding */
+ /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
+ /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
+ if(csiz->effective_bits >= 0) {
+ ASN_DEBUG("Encoding %d bytes (%lld), length in %d bits",
+ st->size, sizeinunits - csiz->lower_bound,
+ csiz->effective_bits);
+ ret = per_put_few_bits(po, sizeinunits - csiz->lower_bound,
+ csiz->effective_bits);
+ if(ret) _ASN_ENCODE_FAILED;
+ if (st->size > 2) { /* X.691 #16 NOTE 1 */
+ if (aper_put_align(po) < 0)
+ _ASN_ENCODE_FAILED;
+ }
+ if(bpc) {
+ ret = OCTET_STRING_per_put_characters(po, st->buf,
+ sizeinunits, bpc, unit_bits,
+ cval->lower_bound, cval->upper_bound, pc);
+ } else {
+ ret = per_put_many_bits(po, st->buf,
+ sizeinunits * unit_bits);
+ }
+ if(ret) _ASN_ENCODE_FAILED;
+ _ASN_ENCODED_OK(er);
+ }
+
+ ASN_DEBUG("Encoding %d bytes", st->size);
+
+ if(sizeinunits == 0) {
+ if(aper_put_length(po, -1, 0))
+ _ASN_ENCODE_FAILED;
+ _ASN_ENCODED_OK(er);
+ }
+
+ buf = st->buf;
+ while(sizeinunits) {
+ ssize_t maySave = aper_put_length(po, -1, sizeinunits);
+
+ if(maySave < 0) _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Encoding %ld of %ld",
+ (long)maySave, (long)sizeinunits);
+
+ if(bpc) {
+ ret = OCTET_STRING_per_put_characters(po, buf,
+ maySave, bpc, unit_bits,
+ cval->lower_bound, cval->upper_bound, pc);
+ } else {
+ ret = per_put_many_bits(po, buf, maySave * unit_bits);
+ }
+ if(ret) _ASN_ENCODE_FAILED;
+
+ if(bpc)
+ buf += maySave * bpc;
+ else
+ buf += maySave >> 3;
+ sizeinunits -= maySave;
+ assert(!(maySave & 0x07) || !sizeinunits);
+ }
+
+ _ASN_ENCODED_OK(er);
+}
+
int
OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
diff --git a/skeletons/OCTET_STRING.h b/skeletons/OCTET_STRING.h
index 013c7b1..bc25666 100644
--- a/skeletons/OCTET_STRING.h
+++ b/skeletons/OCTET_STRING.h
@@ -32,6 +32,8 @@
xer_type_encoder_f OCTET_STRING_encode_xer_utf8;
per_type_decoder_f OCTET_STRING_decode_uper;
per_type_encoder_f OCTET_STRING_encode_uper;
+per_type_decoder_f OCTET_STRING_decode_aper;
+per_type_encoder_f OCTET_STRING_encode_aper;
/******************************
* Handy conversion routines. *
diff --git a/skeletons/ObjectDescriptor.c b/skeletons/ObjectDescriptor.c
index 31bc1b2..f049c1c 100644
--- a/skeletons/ObjectDescriptor.c
+++ b/skeletons/ObjectDescriptor.c
@@ -24,6 +24,8 @@
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_ObjectDescriptor_tags,
sizeof(asn_DEF_ObjectDescriptor_tags)
diff --git a/skeletons/PrintableString.c b/skeletons/PrintableString.c
index 7b6828d..a0b263d 100644
--- a/skeletons/PrintableString.c
+++ b/skeletons/PrintableString.c
@@ -59,6 +59,8 @@
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_PrintableString_tags,
sizeof(asn_DEF_PrintableString_tags)
diff --git a/skeletons/REAL.c b/skeletons/REAL.c
index 0a25062..a157d9b 100644
--- a/skeletons/REAL.c
+++ b/skeletons/REAL.c
@@ -51,6 +51,8 @@
REAL_encode_xer,
REAL_decode_uper,
REAL_encode_uper,
+ REAL_decode_aper,
+ REAL_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_REAL_tags,
sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]),
@@ -390,6 +392,21 @@
return OCTET_STRING_encode_uper(td, 0, sptr, po);
}
+asn_dec_rval_t
+REAL_decode_aper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void **sptr, asn_per_data_t *pd) {
+ (void)constraints; /* No PER visible constraints */
+ return OCTET_STRING_decode_aper(opt_codec_ctx, td, 0, sptr, pd);
+}
+
+asn_enc_rval_t
+REAL_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ (void)constraints; /* No PER visible constraints */
+ return OCTET_STRING_encode_aper(td, 0, sptr, po);
+}
+
int
asn_REAL2double(const REAL_t *st, double *dbl_value) {
unsigned int octv;
diff --git a/skeletons/REAL.h b/skeletons/REAL.h
index af3e84c..503e254 100644
--- a/skeletons/REAL.h
+++ b/skeletons/REAL.h
@@ -21,6 +21,8 @@
xer_type_encoder_f REAL_encode_xer;
per_type_decoder_f REAL_decode_uper;
per_type_encoder_f REAL_encode_uper;
+per_type_decoder_f REAL_decode_aper;
+per_type_encoder_f REAL_encode_aper;
/***********************************
* Some handy conversion routines. *
diff --git a/skeletons/RELATIVE-OID.c b/skeletons/RELATIVE-OID.c
index 352ce79..eaaa9f3 100644
--- a/skeletons/RELATIVE-OID.c
+++ b/skeletons/RELATIVE-OID.c
@@ -28,6 +28,8 @@
RELATIVE_OID_encode_xer,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_RELATIVE_OID_tags,
sizeof(asn_DEF_RELATIVE_OID_tags)
diff --git a/skeletons/T61String.c b/skeletons/T61String.c
index 115d7d4..4a6ad47 100644
--- a/skeletons/T61String.c
+++ b/skeletons/T61String.c
@@ -24,6 +24,8 @@
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_T61String_tags,
sizeof(asn_DEF_T61String_tags)
diff --git a/skeletons/TeletexString.c b/skeletons/TeletexString.c
index faad697..40b5c4e 100644
--- a/skeletons/TeletexString.c
+++ b/skeletons/TeletexString.c
@@ -24,6 +24,8 @@
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_TeletexString_tags,
sizeof(asn_DEF_TeletexString_tags)
diff --git a/skeletons/UTCTime.c b/skeletons/UTCTime.c
index 3983d76..1666a8e 100644
--- a/skeletons/UTCTime.c
+++ b/skeletons/UTCTime.c
@@ -40,6 +40,8 @@
UTCTime_encode_xer,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_UTCTime_tags,
sizeof(asn_DEF_UTCTime_tags)
diff --git a/skeletons/UTF8String.c b/skeletons/UTF8String.c
index d666a4e..43a8e83 100644
--- a/skeletons/UTF8String.c
+++ b/skeletons/UTF8String.c
@@ -25,6 +25,8 @@
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_UTF8String_tags,
sizeof(asn_DEF_UTF8String_tags)
diff --git a/skeletons/UniversalString.c b/skeletons/UniversalString.c
index 21753eb..b5d63ab 100644
--- a/skeletons/UniversalString.c
+++ b/skeletons/UniversalString.c
@@ -35,6 +35,8 @@
UniversalString_encode_xer, /* Convert into UTF-8 */
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_UniversalString_tags,
sizeof(asn_DEF_UniversalString_tags)
diff --git a/skeletons/VideotexString.c b/skeletons/VideotexString.c
index 09967db..e6fc423 100644
--- a/skeletons/VideotexString.c
+++ b/skeletons/VideotexString.c
@@ -24,6 +24,8 @@
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_VideotexString_tags,
sizeof(asn_DEF_VideotexString_tags)
diff --git a/skeletons/VisibleString.c b/skeletons/VisibleString.c
index 0f4dec5..83bdb75 100644
--- a/skeletons/VisibleString.c
+++ b/skeletons/VisibleString.c
@@ -29,6 +29,8 @@
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_VisibleString_tags,
sizeof(asn_DEF_VisibleString_tags)
diff --git a/skeletons/asn_internal.h b/skeletons/asn_internal.h
index 9c94ca6..56d4651 100644
--- a/skeletons/asn_internal.h
+++ b/skeletons/asn_internal.h
@@ -20,7 +20,7 @@
#endif
/* Environment version might be used to avoid running with the old library */
-#define ASN1C_ENVIRONMENT_VERSION 923 /* Compile-time version */
+#define ASN1C_ENVIRONMENT_VERSION 924 /* Compile-time version */
int get_asn1c_environment_version(void); /* Run-time version */
#define CALLOC(nmemb, size) calloc(nmemb, size)
@@ -47,13 +47,17 @@
int asn_debug_indent;
#define ASN_DEBUG_INDENT_ADD(i) do { asn_debug_indent += i; } while(0)
#endif /* ASN_THREAD_SAFE */
-#define ASN_DEBUG(fmt, args...) do { \
+extern int asn_debug; /* Allow option on execution */
+#define ASN_DEBUG(fmt, args...) \
+if (asn_debug) { \
+ do { \
int adi = asn_debug_indent; \
while(adi--) fprintf(stderr, " "); \
fprintf(stderr, fmt, ##args); \
fprintf(stderr, " (%s:%d)\n", \
__FILE__, __LINE__); \
- } while(0)
+ } while(0); \
+}
#else /* !__GNUC__ */
void ASN_DEBUG_f(const char *fmt, ...);
#define ASN_DEBUG ASN_DEBUG_f
diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index 6116e6a..dbca5ae 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -905,7 +905,88 @@
elm->name, td->name, rv.code);
return rv;
}
-
+
+asn_dec_rval_t
+CHOICE_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+ asn_dec_rval_t rv;
+ asn_per_constraint_t *ct;
+ asn_TYPE_member_t *elm; /* CHOICE's element */
+ void *memb_ptr;
+ void **memb_ptr2;
+ void *st = *sptr;
+ int value;
+
+ if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
+ _ASN_DECODE_FAILED;
+
+ /*
+ * Create the target structure if it is not present already.
+ */
+ if(!st) {
+ st = *sptr = CALLOC(1, specs->struct_size);
+ if(!st) _ASN_DECODE_FAILED;
+ }
+
+ if(constraints) ct = &constraints->value;
+ else if(td->per_constraints) ct = &td->per_constraints->value;
+ else ct = 0;
+
+ if(ct && ct->flags & APC_EXTENSIBLE) {
+ value = per_get_few_bits(pd, 1);
+ if(value < 0) _ASN_DECODE_STARVED;
+ if(value) ct = 0; /* Not restricted */
+ }
+
+ if(ct && ct->range_bits >= 0) {
+ value = per_get_few_bits(pd, ct->range_bits);
+ if(value < 0) _ASN_DECODE_STARVED;
+ ASN_DEBUG("CHOICE %s got index %d in range %d",
+ td->name, value, ct->range_bits);
+ if(value > ct->upper_bound)
+ _ASN_DECODE_FAILED;
+ } else {
+ if(specs->ext_start == -1)
+ _ASN_DECODE_FAILED;
+ value = uper_get_nsnnwn(pd);
+ if(value < 0) _ASN_DECODE_STARVED;
+ value += specs->ext_start;
+ if(value >= td->elements_count)
+ _ASN_DECODE_FAILED;
+ }
+
+ /* Adjust if canonical order is different from natural order */
+ if(specs->canonical_order)
+ value = specs->canonical_order[value];
+
+ /* Set presence to be able to free it later */
+ _set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1);
+
+ elm = &td->elements[value];
+ if(elm->flags & ATF_POINTER) {
+ /* Member is a pointer to another structure */
+ memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+ } else {
+ memb_ptr = (char *)st + elm->memb_offset;
+ memb_ptr2 = &memb_ptr;
+ }
+ ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
+
+ if(ct && ct->range_bits >= 0) {
+ rv = elm->type->aper_decoder(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ } else {
+ rv = uper_open_type_get(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ }
+
+ if(rv.code != RC_OK)
+ ASN_DEBUG("Failed to decode %s in %s (CHOICE) %d",
+ elm->name, td->name, rv.code);
+ return rv;
+}
+
asn_enc_rval_t
CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
@@ -918,7 +999,7 @@
if(!sptr) ASN__ENCODE_FAILED;
- ASN_DEBUG("Encoding %s as CHOICE", td->name);
+ ASN_DEBUG("Encoding %s as CHOICE using UPER", td->name);
if(constraints) ct = &constraints->value;
else if(td->per_constraints) ct = &td->per_constraints->value;
@@ -988,7 +1069,87 @@
ASN__ENCODED_OK(rval);
}
}
-
+
+asn_enc_rval_t
+CHOICE_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+ asn_TYPE_member_t *elm; /* CHOICE's element */
+ asn_per_constraint_t *ct;
+ void *memb_ptr;
+ int present;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Encoding %s as CHOICE using ALIGNED PER", td->name);
+
+ if(constraints) ct = &constraints->value;
+ else if(td->per_constraints) ct = &td->per_constraints->value;
+ else ct = 0;
+
+ present = _fetch_present_idx(sptr,
+ specs->pres_offset, specs->pres_size);
+
+ /*
+ * If the structure was not initialized properly, it cannot be encoded:
+ * can't deduce what to encode in the choice type.
+ */
+ if(present <= 0 || present > td->elements_count)
+ _ASN_ENCODE_FAILED;
+ else
+ present--;
+
+ /* Adjust if canonical order is different from natural order */
+ if(specs->canonical_order)
+ present = specs->canonical_order[present];
+
+ ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
+
+ if(ct && ct->range_bits >= 0) {
+ if(present < ct->lower_bound
+ || present > ct->upper_bound) {
+ if(ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, 1, 1))
+ _ASN_ENCODE_FAILED;
+ } else {
+ _ASN_ENCODE_FAILED;
+ }
+ ct = 0;
+ }
+ }
+ if(ct && ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, 0, 1))
+ _ASN_ENCODE_FAILED;
+ }
+
+ elm = &td->elements[present];
+ if(elm->flags & ATF_POINTER) {
+ /* Member is a pointer to another structure */
+ memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+ if(!memb_ptr) _ASN_ENCODE_FAILED;
+ } else {
+ memb_ptr = (char *)sptr + elm->memb_offset;
+ }
+
+ if(ct && ct->range_bits >= 0) {
+ if(per_put_few_bits(po, present, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+
+ return elm->type->aper_encoder(elm->type, elm->per_constraints,
+ memb_ptr, po);
+ } else {
+ asn_enc_rval_t rval;
+ if(specs->ext_start == -1)
+ _ASN_ENCODE_FAILED;
+ if(aper_put_nsnnwn(po, ct->range_bits, present - specs->ext_start))
+ _ASN_ENCODE_FAILED;
+ if(aper_open_type_put(elm->type, elm->per_constraints,
+ memb_ptr, po))
+ _ASN_ENCODE_FAILED;
+ rval.encoded = 0;
+ _ASN_ENCODED_OK(rval);
+ }
+}
int
CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
diff --git a/skeletons/constr_CHOICE.h b/skeletons/constr_CHOICE.h
index e824a22..ddcbb39 100644
--- a/skeletons/constr_CHOICE.h
+++ b/skeletons/constr_CHOICE.h
@@ -48,6 +48,8 @@
xer_type_encoder_f CHOICE_encode_xer;
per_type_decoder_f CHOICE_decode_uper;
per_type_encoder_f CHOICE_encode_uper;
+per_type_decoder_f CHOICE_decode_aper;
+per_type_encoder_f CHOICE_encode_aper;
asn_outmost_tag_f CHOICE_outmost_tag;
#ifdef __cplusplus
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index 5923023..9e6cc16 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -1242,6 +1242,219 @@
return rv;
}
+asn_dec_rval_t
+SEQUENCE_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
+ void *st = *sptr; /* Target structure. */
+ int extpresent; /* Extension additions are present */
+ uint8_t *opres; /* Presence of optional root members */
+ asn_per_data_t opmd;
+ asn_dec_rval_t rv;
+ int edx;
+
+ (void)constraints;
+
+ if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
+ _ASN_DECODE_FAILED;
+
+ if(!st) {
+ st = *sptr = CALLOC(1, specs->struct_size);
+ if(!st) _ASN_DECODE_FAILED;
+ }
+
+ ASN_DEBUG("Decoding %s as SEQUENCE (APER)", td->name);
+
+ /* Handle extensions */
+ if(specs->ext_before >= 0) {
+ extpresent = per_get_few_bits(pd, 1);
+ if(extpresent < 0) _ASN_DECODE_STARVED;
+ } else {
+ extpresent = 0;
+ }
+
+ /* Prepare a place and read-in the presence bitmap */
+ memset(&opmd, 0, sizeof(opmd));
+ if(specs->roms_count) {
+ opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1);
+ if(!opres) _ASN_DECODE_FAILED;
+ /* Get the presence map */
+ if(per_get_many_bits(pd, opres, 0, specs->roms_count)) {
+ FREEMEM(opres);
+ _ASN_DECODE_STARVED;
+ }
+ opmd.buffer = opres;
+ opmd.nbits = specs->roms_count;
+ ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)",
+ td->name, specs->roms_count, *opres);
+ } else {
+ opres = 0;
+ }
+
+ /*
+ * Get the sequence ROOT elements.
+ */
+ for(edx = 0; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+
+ if(IN_EXTENSION_GROUP(specs, edx))
+ continue;
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+ } else {
+ memb_ptr = (char *)st + elm->memb_offset;
+ memb_ptr2 = &memb_ptr;
+ }
+
+ /* Deal with optionality */
+ if(elm->optional) {
+ int present = per_get_few_bits(&opmd, 1);
+ ASN_DEBUG("Member %s->%s is optional, p=%d (%d->%d)",
+ td->name, elm->name, present,
+ (int)opmd.nboff, (int)opmd.nbits);
+ if(present == 0) {
+ /* This element is not present */
+ if(elm->default_value) {
+ /* Fill-in DEFAULT */
+ if(elm->default_value(1, memb_ptr2)) {
+ FREEMEM(opres);
+ _ASN_DECODE_FAILED;
+ }
+ ASN_DEBUG("Filled-in default");
+ }
+ /* The member is just not present */
+ continue;
+ }
+ /* Fall through */
+ }
+
+ /* Fetch the member from the stream */
+ ASN_DEBUG("Decoding member %s in %s", elm->name, td->name);
+ rv = elm->type->aper_decoder(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ if(rv.code != RC_OK) {
+ ASN_DEBUG("Failed decode %s in %s",
+ elm->name, td->name);
+ FREEMEM(opres);
+ return rv;
+ }
+ }
+
+ /* Optionality map is not needed anymore */
+ FREEMEM(opres);
+
+ /*
+ * Deal with extensions.
+ */
+ if(extpresent) {
+ ssize_t bmlength;
+ uint8_t *epres; /* Presence of extension members */
+ asn_per_data_t epmd;
+
+ bmlength = uper_get_nslength(pd);
+ if(bmlength < 0) _ASN_DECODE_STARVED;
+
+ ASN_DEBUG("Extensions %d present in %s", bmlength, td->name);
+
+ epres = (uint8_t *)MALLOC((bmlength + 15) >> 3);
+ if(!epres) _ASN_DECODE_STARVED;
+
+ /* Get the extensions map */
+ if(per_get_many_bits(pd, epres, 0, bmlength))
+ _ASN_DECODE_STARVED;
+
+ memset(&epmd, 0, sizeof(epmd));
+ epmd.buffer = epres;
+ epmd.nbits = bmlength;
+ ASN_DEBUG("Read in extensions bitmap for %s of %d bits (%x..)",
+ td->name, bmlength, *epres);
+
+ /* Go over extensions and read them in */
+ for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+ int present;
+
+ if(!IN_EXTENSION_GROUP(specs, edx)) {
+ ASN_DEBUG("%d is not extension", edx);
+ continue;
+ }
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+ } else {
+ memb_ptr = (void *)((char *)st + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ }
+
+ present = per_get_few_bits(&epmd, 1);
+ if(present <= 0) {
+ if(present < 0) break; /* No more extensions */
+ continue;
+ }
+
+ ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2);
+ rv = uper_open_type_get(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ if(rv.code != RC_OK) {
+ FREEMEM(epres);
+ return rv;
+ }
+ }
+
+ /* Skip over overflow extensions which aren't present
+ * in this system's version of the protocol */
+ for(;;) {
+ ASN_DEBUG("Getting overflow extensions");
+ switch(per_get_few_bits(&epmd, 1)) {
+ case -1: break;
+ case 0: continue;
+ default:
+ if(uper_open_type_skip(opt_codec_ctx, pd)) {
+ FREEMEM(epres);
+ _ASN_DECODE_STARVED;
+ }
+ }
+ break;
+ }
+
+ FREEMEM(epres);
+ }
+
+ /* Fill DEFAULT members in extensions */
+ for(edx = specs->roms_count; edx < specs->roms_count
+ + specs->aoms_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void **memb_ptr2; /* Pointer to member pointer */
+
+ if(!elm->default_value) continue;
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)st
+ + elm->memb_offset);
+ if(*memb_ptr2) continue;
+ } else {
+ continue; /* Extensions are all optionals */
+ }
+
+ /* Set default value */
+ if(elm->default_value(1, memb_ptr2)) {
+ _ASN_DECODE_FAILED;
+ }
+ }
+
+ rv.consumed = 0;
+ rv.code = RC_OK;
+ return rv;
+}
+
static int
SEQUENCE_handle_extensions(asn_TYPE_descriptor_t *td, void *sptr,
asn_per_outp_t *po1, asn_per_outp_t *po2) {
@@ -1285,7 +1498,7 @@
if(po1 && per_put_few_bits(po1, present, 1))
return -1;
/* Encode as open type field */
- if(po2 && present && uper_open_type_put(elm->type,
+ if(po2 && present && aper_open_type_put(elm->type,
elm->per_constraints, *memb_ptr2, po2))
return -1;
@@ -1423,3 +1636,130 @@
ASN__ENCODED_OK(er);
}
+asn_enc_rval_t
+SEQUENCE_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_SEQUENCE_specifics_t *specs
+ = (asn_SEQUENCE_specifics_t *)td->specifics;
+ asn_enc_rval_t er;
+ int n_extensions;
+ int edx;
+ int i;
+
+ (void)constraints;
+
+ if(!sptr)
+ _ASN_ENCODE_FAILED;
+
+ er.encoded = 0;
+
+ ASN_DEBUG("Encoding %s as SEQUENCE (APER)", td->name);
+
+ /*
+ * X.691#18.1 Whether structure is extensible
+ * and whether to encode extensions
+ */
+ if(specs->ext_before >= 0) {
+ n_extensions = SEQUENCE_handle_extensions(td, sptr, 0, 0);
+ per_put_few_bits(po, n_extensions ? 1 : 0, 1);
+ } else {
+ n_extensions = 0; /* There are no extensions to encode */
+ }
+
+ /* Encode a presence bitmap */
+ for(i = 0; i < specs->roms_count; i++) {
+ asn_TYPE_member_t *elm;
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+ int present;
+
+ edx = specs->oms[i];
+ elm = &td->elements[edx];
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+ present = (*memb_ptr2 != 0);
+ } else {
+ memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ present = 1;
+ }
+
+ /* Eliminate default values */
+ if(present && elm->default_value
+ && elm->default_value(0, memb_ptr2) == 1)
+ present = 0;
+
+ ASN_DEBUG("Element %s %s %s->%s is %s",
+ elm->flags & ATF_POINTER ? "ptr" : "inline",
+ elm->default_value ? "def" : "wtv",
+ td->name, elm->name, present ? "present" : "absent");
+ if(per_put_few_bits(po, present, 1))
+ _ASN_ENCODE_FAILED;
+ }
+
+ /*
+ * Encode the sequence ROOT elements.
+ */
+ ASN_DEBUG("ext_after = %d, ec = %d, eb = %d", specs->ext_after, td->elements_count, specs->ext_before);
+ for(edx = 0; edx < ((specs->ext_after < 0)
+ ? td->elements_count : specs->ext_before - 1); edx++) {
+
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+
+ if(IN_EXTENSION_GROUP(specs, edx))
+ continue;
+
+ ASN_DEBUG("About to encode %s", elm->type->name);
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+ if(!*memb_ptr2) {
+ ASN_DEBUG("Element %s %d not present",
+ elm->name, edx);
+ if(elm->optional)
+ continue;
+ /* Mandatory element is missing */
+ _ASN_ENCODE_FAILED;
+ }
+ } else {
+ memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ }
+
+ /* Eliminate default values */
+ if(elm->default_value && elm->default_value(0, memb_ptr2) == 1)
+ continue;
+
+ ASN_DEBUG("Encoding %s->%s", td->name, elm->name);
+ er = elm->type->aper_encoder(elm->type, elm->per_constraints,
+ *memb_ptr2, po);
+ if(er.encoded == -1)
+ return er;
+ }
+
+ /* No extensions to encode */
+ if(!n_extensions) _ASN_ENCODED_OK(er);
+
+ ASN_DEBUG("Length of %d bit-map", n_extensions);
+ /* #18.8. Write down the presence bit-map length. */
+ if(aper_put_nslength(po, n_extensions))
+ _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Bit-map of %d elements", n_extensions);
+ /* #18.7. Encoding the extensions presence bit-map. */
+ /* TODO: act upon NOTE in #18.7 for canonical PER */
+ if(SEQUENCE_handle_extensions(td, sptr, po, 0) != n_extensions)
+ _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Writing %d extensions", n_extensions);
+ /* #18.9. Encode extensions as open type fields. */
+ if(SEQUENCE_handle_extensions(td, sptr, 0, po) != n_extensions)
+ _ASN_ENCODE_FAILED;
+
+ _ASN_ENCODED_OK(er);
+}
diff --git a/skeletons/constr_SEQUENCE.h b/skeletons/constr_SEQUENCE.h
index c2aeb66..d181848 100644
--- a/skeletons/constr_SEQUENCE.h
+++ b/skeletons/constr_SEQUENCE.h
@@ -52,6 +52,8 @@
xer_type_encoder_f SEQUENCE_encode_xer;
per_type_decoder_f SEQUENCE_decode_uper;
per_type_encoder_f SEQUENCE_encode_uper;
+per_type_decoder_f SEQUENCE_decode_aper;
+per_type_encoder_f SEQUENCE_encode_aper;
#ifdef __cplusplus
}
diff --git a/skeletons/constr_SEQUENCE_OF.c b/skeletons/constr_SEQUENCE_OF.c
index 8a08ee8..25f272b 100644
--- a/skeletons/constr_SEQUENCE_OF.c
+++ b/skeletons/constr_SEQUENCE_OF.c
@@ -164,7 +164,7 @@
if(ct) {
int not_in_root = (list->count < ct->lower_bound
|| list->count > ct->upper_bound);
- ASN_DEBUG("lb %ld ub %ld %s",
+ ASN_DEBUG("lb %lld ub %lld %s",
ct->lower_bound, ct->upper_bound,
ct->flags & APC_EXTENSIBLE ? "ext" : "fix");
if(ct->flags & APC_EXTENSIBLE) {
@@ -206,3 +206,70 @@
ASN__ENCODED_OK(er);
}
+asn_enc_rval_t
+SEQUENCE_OF_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_anonymous_sequence_ *list;
+ asn_per_constraint_t *ct;
+ asn_enc_rval_t er;
+ asn_TYPE_member_t *elm = td->elements;
+ int seq;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+ list = _A_SEQUENCE_FROM_VOID(sptr);
+
+ er.encoded = 0;
+
+ ASN_DEBUG("Encoding %s as SEQUENCE OF size (%d) using ALIGNED PER", td->name, list->count);
+
+ if(constraints) ct = &constraints->size;
+ else if(td->per_constraints) ct = &td->per_constraints->size;
+ else ct = 0;
+
+ /* If extensible constraint, check if size is in root */
+ if(ct) {
+ int not_in_root = (list->count < ct->lower_bound
+ || list->count > ct->upper_bound);
+ ASN_DEBUG("lb %lld ub %lld %s",
+ ct->lower_bound, ct->upper_bound,
+ ct->flags & APC_EXTENSIBLE ? "ext" : "fix");
+ if(ct->flags & APC_EXTENSIBLE) {
+ /* Declare whether size is in extension root */
+ if(per_put_few_bits(po, not_in_root, 1))
+ _ASN_ENCODE_FAILED;
+ if(not_in_root) ct = 0;
+ } else if(not_in_root && ct->effective_bits >= 0)
+ _ASN_ENCODE_FAILED;
+ }
+
+ if(ct && ct->effective_bits >= 0) {
+ /* X.691, #19.5: No length determinant */
+// if(per_put_few_bits(po, list->count - ct->lower_bound,
+// ct->effective_bits))
+// _ASN_ENCODE_FAILED;
+ if (aper_put_length(po, ct->upper_bound - ct->lower_bound + 1, list->count - ct->lower_bound) < 0)
+ _ASN_ENCODE_FAILED;
+ }
+
+ for(seq = -1; seq < list->count;) {
+ ssize_t mayEncode;
+ if(seq < 0) seq = 0;
+ if(ct && ct->effective_bits >= 0) {
+ mayEncode = list->count;
+ } else {
+ mayEncode = aper_put_length(po, -1, list->count - seq);
+ if(mayEncode < 0) _ASN_ENCODE_FAILED;
+ }
+
+ while(mayEncode--) {
+ void *memb_ptr = list->array[seq++];
+ if(!memb_ptr) _ASN_ENCODE_FAILED;
+ er = elm->type->aper_encoder(elm->type,
+ elm->per_constraints, memb_ptr, po);
+ if(er.encoded == -1)
+ _ASN_ENCODE_FAILED;
+ }
+ }
+
+ _ASN_ENCODED_OK(er);
+}
diff --git a/skeletons/constr_SEQUENCE_OF.h b/skeletons/constr_SEQUENCE_OF.h
index e2272f3..94a7cd5 100644
--- a/skeletons/constr_SEQUENCE_OF.h
+++ b/skeletons/constr_SEQUENCE_OF.h
@@ -22,9 +22,11 @@
#define SEQUENCE_OF_decode_ber SET_OF_decode_ber
#define SEQUENCE_OF_decode_xer SET_OF_decode_xer
#define SEQUENCE_OF_decode_uper SET_OF_decode_uper
+#define SEQUENCE_OF_decode_aper SET_OF_decode_aper
der_type_encoder_f SEQUENCE_OF_encode_der;
xer_type_encoder_f SEQUENCE_OF_encode_xer;
per_type_encoder_f SEQUENCE_OF_encode_uper;
+per_type_encoder_f SEQUENCE_OF_encode_aper;
#ifdef __cplusplus
}
diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c
index 55a0bad..b575b28 100644
--- a/skeletons/constr_SET.c
+++ b/skeletons/constr_SET.c
@@ -573,6 +573,181 @@
ASN__ENCODED_OK(er);
}
+asn_enc_rval_t
+SET_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints,
+ void *sptr,
+ asn_per_outp_t *po) {
+}
+
+asn_dec_rval_t
+SET_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+}
+
+asn_enc_rval_t
+SET_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints,
+ void *sptr,
+ asn_per_outp_t *po) {
+ asn_SET_specifics_t *specs = (asn_SET_specifics_t *)td->specifics;
+ asn_enc_rval_t er;
+ int edx, i;
+ int t2m_build_own = (specs->tag2el_count != td->elements_count);
+ asn_TYPE_tag2member_t *t2m;
+ int t2m_count;
+
+ (void)constraints;
+
+ if(!sptr)
+ _ASN_ENCODE_FAILED;
+
+ er.encoded = 0;
+
+ ASN_DEBUG("Encoding %s as SET (APER) map %d", td->name, specs->_mandatory_elements[0]);
+
+ /*
+ * Use existing, or build our own tags map.
+ */
+ if(t2m_build_own) {
+ t2m = (asn_TYPE_tag2member_t *)alloca(
+ td->elements_count * sizeof(t2m[0]));
+ if(!t2m) _ASN_ENCODE_FAILED; /* There are such platforms */
+ t2m_count = 0;
+ } else {
+ /*
+ * There is no untagged CHOICE in this SET.
+ * Employ existing table.
+ */
+ t2m = specs->tag2el;
+ t2m_count = specs->tag2el_count;
+ }
+
+ /*
+ * Gather the length of the underlying members sequence.
+ */
+ for(edx = 0; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ asn_enc_rval_t tmper;
+ void *memb_ptr;
+
+ /*
+ * Compute the length of the encoding of this member.
+ */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+ if(!memb_ptr) {
+ if(!elm->optional)
+ /* Mandatory elements missing */
+ _ASN_ENCODE_FAILED;
+ if(t2m_build_own) {
+ t2m[t2m_count].el_no = edx;
+ t2m[t2m_count].el_tag = 0;
+ t2m_count++;
+ }
+ continue;
+ }
+ } else {
+ memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+ }
+
+ /*
+ * Remember the outmost tag of this member.
+ */
+ if(t2m_build_own) {
+ t2m[t2m_count].el_no = edx;
+ t2m[t2m_count].el_tag = asn_TYPE_outmost_tag(
+ elm->type, memb_ptr, elm->tag_mode, elm->tag);
+ t2m_count++;
+ } else {
+ /*
+ * No dynamic sorting is necessary.
+ */
+ }
+ }
+
+ /*
+ * Finalize order of the components.
+ */
+ assert(t2m_count == td->elements_count);
+ if(t2m_build_own) {
+ /*
+ * Sort the underlying members according to their
+ * canonical tags order. DER encoding mandates it.
+ */
+ qsort(t2m, t2m_count, sizeof(specs->tag2el[0]), _t2e_cmp);
+ } else {
+ /*
+ * Tags are already sorted by the compiler.
+ */
+ }
+
+ for(edx = 0; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[t2m[edx].el_no];
+ asn_enc_rval_t tmper;
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+ int present;
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+ present = (*memb_ptr2 != 0);
+ } else {
+// memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+// memb_ptr2 = &memb_ptr;
+ present = 1;
+ continue;
+ }
+
+// /* Eliminate default values */
+// if(present && elm->default_value
+// && elm->default_value(0, memb_ptr2) == 1)
+// present = 0;
+
+ ASN_DEBUG("Element %s %s %s->%s is %s",
+ elm->flags & ATF_POINTER ? "ptr" : "inline",
+ elm->default_value ? "def" : "wtv",
+ td->name, elm->name, present ? "present" : "absent");
+ if(per_put_few_bits(po, present << 7, 8))
+ _ASN_ENCODE_FAILED;
+ }
+
+ /*
+ * Encode all members.
+ */
+ for(edx = 0; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ asn_enc_rval_t tmper;
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+
+ /* Encode according to the tag order */
+// elm = &td->elements[t2m[edx].el_no];
+
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+ if(!*memb_ptr2) {
+ ASN_DEBUG("Element %s %d not present",
+ elm->name, edx);
+ if(elm->optional)
+ continue;
+ /* Mandatory element is missing */
+ _ASN_ENCODE_FAILED;
+ }
+ } else {
+ memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ }
+ tmper = elm->type->aper_encoder(elm->type, elm->per_constraints,
+ *memb_ptr2, po);
+ if(tmper.encoded == -1)
+ return tmper;
+ }
+
+ _ASN_ENCODED_OK(er);
+}
+
#undef XER_ADVANCE
#define XER_ADVANCE(num_bytes) do { \
size_t num = num_bytes; \
diff --git a/skeletons/constr_SET.h b/skeletons/constr_SET.h
index 6a3a1aa..11b7153 100644
--- a/skeletons/constr_SET.h
+++ b/skeletons/constr_SET.h
@@ -53,7 +53,9 @@
xer_type_decoder_f SET_decode_xer;
xer_type_encoder_f SET_encode_xer;
per_type_decoder_f SET_decode_uper;
+per_type_decoder_f SET_decode_aper;
per_type_encoder_f SET_encode_uper;
+per_type_encoder_f SET_encode_aper;
/***********************
* Some handy helpers. *
diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c
index 2dbc6e5..152efab 100644
--- a/skeletons/constr_SET_OF.c
+++ b/skeletons/constr_SET_OF.c
@@ -885,7 +885,7 @@
if(!st) {
st = *sptr = CALLOC(1, specs->struct_size);
if(!st) ASN__DECODE_FAILED;
- }
+ }
list = _A_SET_FROM_VOID(st);
/* Figure out which constraints to use */
@@ -902,7 +902,7 @@
if(ct && ct->effective_bits >= 0) {
/* X.691, #19.5: No length determinant */
nelems = per_get_few_bits(pd, ct->effective_bits);
- ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s",
+ ASN_DEBUG("Preparing to fetch %ld+%lld elements from %s",
(long)nelems, ct->lower_bound, td->name);
if(nelems < 0) ASN__DECODE_STARVED;
nelems += ct->lower_bound;
@@ -952,3 +952,91 @@
return rv;
}
+asn_dec_rval_t
+SET_OF_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_dec_rval_t rv;
+ asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
+ asn_TYPE_member_t *elm = td->elements; /* Single one */
+ void *st = *sptr;
+ asn_anonymous_set_ *list;
+ asn_per_constraint_t *ct;
+ int repeat = 0;
+ ssize_t nelems;
+
+ if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
+ _ASN_DECODE_FAILED;
+
+ /*
+ * Create the target structure if it is not present already.
+ */
+ if(!st) {
+ st = *sptr = CALLOC(1, specs->struct_size);
+ if(!st) _ASN_DECODE_FAILED;
+ }
+ list = _A_SET_FROM_VOID(st);
+
+ /* Figure out which constraints to use */
+ if(constraints) ct = &constraints->size;
+ else if(td->per_constraints) ct = &td->per_constraints->size;
+ else ct = 0;
+
+ if(ct && ct->flags & APC_EXTENSIBLE) {
+ int value = per_get_few_bits(pd, 1);
+ if(value < 0) _ASN_DECODE_STARVED;
+ if(value) ct = 0; /* Not restricted! */
+ }
+
+ if(ct && ct->effective_bits >= 0) {
+ /* X.691, #19.5: No length determinant */
+// nelems = per_get_few_bits(pd, ct->effective_bits);
+ nelems = aper_get_nsnnwn(pd, ct->upper_bound - ct->lower_bound);
+ ASN_DEBUG("Preparing to fetch %ld+%lld elements from %s",
+ (long)nelems, ct->lower_bound, td->name);
+ if(nelems < 0) _ASN_DECODE_STARVED;
+ nelems += ct->lower_bound;
+ } else {
+ nelems = -1;
+ }
+
+ do {
+ int i;
+ if(nelems < 0) {
+ nelems = aper_get_length(pd, ct ? ct->upper_bound - ct->lower_bound + 1 : -1,
+ ct ? ct->effective_bits : -1, &repeat);
+ ASN_DEBUG("Got to decode %d elements (eff %d)",
+ (int)nelems, (int)ct ? ct->effective_bits : -1);
+ if(nelems < 0) _ASN_DECODE_STARVED;
+ }
+
+ for(i = 0; i < nelems; i++) {
+ void *ptr = 0;
+ ASN_DEBUG("SET OF %s decoding", elm->type->name);
+ rv = elm->type->aper_decoder(opt_codec_ctx, elm->type,
+ elm->per_constraints, &ptr, pd);
+ ASN_DEBUG("%s SET OF %s decoded %d, %p",
+ td->name, elm->type->name, rv.code, ptr);
+ if(rv.code == RC_OK) {
+ if(ASN_SET_ADD(list, ptr) == 0)
+ continue;
+ ASN_DEBUG("Failed to add element into %s",
+ td->name);
+ /* Fall through */
+ rv.code = RC_FAIL;
+ } else {
+ ASN_DEBUG("Failed decoding %s of %s (SET OF)",
+ elm->type->name, td->name);
+ }
+ if(ptr) ASN_STRUCT_FREE(*elm->type, ptr);
+ return rv;
+ }
+
+ nelems = -1; /* Allow uper_get_length() */
+ } while(repeat);
+
+ ASN_DEBUG("Decoded %s as SET OF", td->name);
+
+ rv.code = RC_OK;
+ rv.consumed = 0;
+ return rv;
+}
diff --git a/skeletons/constr_SET_OF.h b/skeletons/constr_SET_OF.h
index 75e18cf..8ddd0e3 100644
--- a/skeletons/constr_SET_OF.h
+++ b/skeletons/constr_SET_OF.h
@@ -34,6 +34,8 @@
xer_type_encoder_f SET_OF_encode_xer;
per_type_decoder_f SET_OF_decode_uper;
per_type_encoder_f SET_OF_encode_uper;
+per_type_decoder_f SET_OF_decode_aper;
+per_type_encoder_f SET_OF_encode_aper;
#ifdef __cplusplus
}
diff --git a/skeletons/constr_TYPE.h b/skeletons/constr_TYPE.h
index a9cd86d..13c60f3 100644
--- a/skeletons/constr_TYPE.h
+++ b/skeletons/constr_TYPE.h
@@ -99,6 +99,8 @@
xer_type_encoder_f *xer_encoder; /* [Canonical] XER encoder */
per_type_decoder_f *uper_decoder; /* Unaligned PER decoder */
per_type_encoder_f *uper_encoder; /* Unaligned PER encoder */
+ per_type_decoder_f *aper_decoder; /* Aligned PER decoder */
+ per_type_encoder_f *aper_encoder; /* Aligned PER encoder */
/***********************************************************************
* Internally useful members. Not to be used by applications directly. *
diff --git a/skeletons/per_decoder.c b/skeletons/per_decoder.c
index 461b726..a85efb8 100644
--- a/skeletons/per_decoder.c
+++ b/skeletons/per_decoder.c
@@ -37,6 +37,35 @@
}
asn_dec_rval_t
+aper_decode_complete(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size) {
+ asn_dec_rval_t rval;
+
+ rval = aper_decode(opt_codec_ctx, td, sptr, buffer, size, 0, 0);
+ if(rval.consumed) {
+ /*
+ * We've always given 8-aligned data,
+ * so convert bits to integral bytes.
+ */
+ rval.consumed += 7;
+ rval.consumed >>= 3;
+ } else if(rval.code == RC_OK) {
+ if(size) {
+ if(((uint8_t *)buffer)[0] == 0) {
+ rval.consumed = 1; /* 1 byte */
+ } else {
+ ASN_DEBUG("Expecting single zeroed byte");
+ rval.code = RC_FAIL;
+ }
+ } else {
+ /* Must contain at least 8 bits. */
+ rval.code = RC_WMORE;
+ }
+ }
+
+ return rval;
+}
+
+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, int skip_bits, int unused_bits) {
asn_codec_ctx_t s_codec_ctx;
asn_dec_rval_t rval;
@@ -91,3 +120,57 @@
return rval;
}
+asn_dec_rval_t
+aper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) {
+ asn_codec_ctx_t s_codec_ctx;
+ asn_dec_rval_t rval;
+ asn_per_data_t pd;
+
+ if(skip_bits < 0 || skip_bits > 7
+ || unused_bits < 0 || unused_bits > 7
+ || (unused_bits > 0 && !size))
+ _ASN_DECODE_FAILED;
+
+ /*
+ * Stack checker requires that the codec context
+ * must be allocated on the stack.
+ */
+ if(opt_codec_ctx) {
+ if(opt_codec_ctx->max_stack_size) {
+ s_codec_ctx = *opt_codec_ctx;
+ opt_codec_ctx = &s_codec_ctx;
+ }
+ } else {
+ /* If context is not given, be security-conscious anyway */
+ memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
+ s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX;
+ opt_codec_ctx = &s_codec_ctx;
+ }
+
+ /* Fill in the position indicator */
+ memset(&pd, 0, sizeof(pd));
+ pd.buffer = (const uint8_t *)buffer;
+ pd.nboff = skip_bits;
+ pd.nbits = 8 * size - unused_bits; /* 8 is CHAR_BIT from <limits.h> */
+ if(pd.nboff > pd.nbits)
+ _ASN_DECODE_FAILED;
+
+ /*
+ * Invoke type-specific decoder.
+ */
+ if(!td->aper_decoder)
+ _ASN_DECODE_FAILED; /* PER is not compiled in */
+ rval = td->aper_decoder(opt_codec_ctx, td, 0, sptr, &pd);
+ if(rval.code == RC_OK) {
+ /* Return the number of consumed bits */
+ rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3)
+ + pd.nboff - skip_bits;
+ ASN_DEBUG("PER decoding consumed %d, counted %d",
+ rval.consumed, pd.moved);
+ assert(rval.consumed == pd.moved);
+ } else {
+ /* PER codec is not a restartable */
+ rval.consumed = 0;
+ }
+ return rval;
+}
diff --git a/skeletons/per_decoder.h b/skeletons/per_decoder.h
index 8397a54..5541bae 100644
--- a/skeletons/per_decoder.h
+++ b/skeletons/per_decoder.h
@@ -38,8 +38,30 @@
int unused_bits /* Number of unused tailing bits, 0..7 */
);
+/*
+ * Aligned PER decoder of a "complete encoding" as per X.691#10.1.
+ * On success, this call always returns (.consumed >= 1), as per X.691#10.1.3.
+ */
+asn_dec_rval_t aper_decode_complete(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 */
+ );
/*
+ * Aligned PER decoder of any ASN.1 type. May be invoked by the application.
+ * WARNING: This call returns the number of BITS read from the stream. Beware.
+ */
+asn_dec_rval_t aper_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 */
+ int skip_bits, /* Number of unused leading bits, 0..7 */
+ int unused_bits /* Number of unused tailing bits, 0..7 */
+ );
+/*
* Type of the type-specific PER decoder function.
*/
typedef asn_dec_rval_t (per_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx,
diff --git a/skeletons/per_encoder.c b/skeletons/per_encoder.c
index 47f3c91..7939b97 100644
--- a/skeletons/per_encoder.c
+++ b/skeletons/per_encoder.c
@@ -4,6 +4,7 @@
static asn_enc_rval_t uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *, void *sptr, asn_app_consume_bytes_f *cb, void *app_key);
+static asn_enc_rval_t aper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *, void *sptr, asn_app_consume_bytes_f *cb, void *app_key);
asn_enc_rval_t
uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
return uper_encode_internal(td, 0, sptr, cb, app_key);
@@ -41,6 +42,18 @@
return uper_encode_internal(td, 0, sptr, encode_to_buffer_cb, &key);
}
+asn_enc_rval_t
+aper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) {
+ enc_to_buf_arg key;
+
+ key.buffer = buffer;
+ key.left = buffer_size;
+
+ if(td) ASN_DEBUG("Encoding \"%s\" using ALIGNED PER", td->name);
+
+ return aper_encode_internal(td, 0, sptr, encode_to_buffer_cb, &key);
+}
+
typedef struct enc_dyn_arg {
void *buffer;
size_t length;
@@ -93,6 +106,35 @@
}
}
+ssize_t
+aper_encode_to_new_buffer(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, void **buffer_r) {
+ asn_enc_rval_t er;
+ enc_dyn_arg key;
+
+ memset(&key, 0, sizeof(key));
+
+ er = aper_encode_internal(td, constraints, sptr, encode_dyn_cb, &key);
+ switch(er.encoded) {
+ case -1:
+ FREEMEM(key.buffer);
+ return -1;
+ case 0:
+ FREEMEM(key.buffer);
+ key.buffer = MALLOC(1);
+ if(key.buffer) {
+ *(char *)key.buffer = '\0';
+ *buffer_r = key.buffer;
+ return 1;
+ } else {
+ return -1;
+ }
+ default:
+ *buffer_r = key.buffer;
+ ASN_DEBUG("Complete encoded in %d bits", er.encoded);
+ return ((er.encoded + 7) >> 3);
+ }
+}
+
/*
* Internally useful functions.
*/
@@ -115,6 +157,23 @@
return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key);
}
+static int
+_aper_encode_flush_outp(asn_per_outp_t *po) {
+ uint8_t *buf;
+
+ if(po->nboff == 0 && po->buffer == po->tmpspace)
+ return 0;
+
+ buf = po->buffer + (po->nboff >> 3);
+ /* Make sure we account for the last, partially filled */
+ if(po->nboff & 0x07) {
+ buf[0] &= 0xff << (8 - (po->nboff & 0x07));
+ buf++;
+ }
+
+ return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key);
+}
+
static asn_enc_rval_t
uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
asn_per_outp_t po;
@@ -149,3 +208,37 @@
return er;
}
+static asn_enc_rval_t
+aper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
+ asn_per_outp_t po;
+ asn_enc_rval_t er;
+
+ /*
+ * Invoke type-specific encoder.
+ */
+ if(!td || !td->aper_encoder)
+ _ASN_ENCODE_FAILED; /* PER is not compiled in */
+
+ po.buffer = po.tmpspace;
+ po.nboff = 0;
+ po.nbits = 8 * sizeof(po.tmpspace);
+ po.outper = cb;
+ po.op_key = app_key;
+ po.flushed_bytes = 0;
+
+ er = td->aper_encoder(td, constraints, sptr, &po);
+ 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(_aper_encode_flush_outp(&po))
+ _ASN_ENCODE_FAILED;
+ }
+
+ return er;
+}
+
diff --git a/skeletons/per_encoder.h b/skeletons/per_encoder.h
index 95a6506..e3b9190 100644
--- a/skeletons/per_encoder.h
+++ b/skeletons/per_encoder.h
@@ -38,6 +38,12 @@
size_t buffer_size /* Initial buffer size (max) */
);
+asn_enc_rval_t aper_encode_to_buffer(
+ struct asn_TYPE_descriptor_s *type_descriptor,
+ void *struct_ptr, /* Structure to be encoded */
+ void *buffer, /* Pre-allocated buffer */
+ size_t buffer_size /* Initial buffer size (max) */
+);
/*
* A variant of uper_encode_to_buffer() which allocates buffer itself.
* Returns the number of bytes in the buffer or -1 in case of failure.
@@ -52,6 +58,11 @@
void **buffer_r /* Buffer allocated and returned */
);
+ssize_t
+aper_encode_to_new_buffer(struct asn_TYPE_descriptor_s *td,
+ asn_per_constraints_t *constraints,
+ void *sptr,
+ void **buffer_r);
/*
* Type of the generic PER encoder function.
*/
diff --git a/skeletons/per_opentype.c b/skeletons/per_opentype.c
index 404aa72..eb82bbc 100644
--- a/skeletons/per_opentype.c
+++ b/skeletons/per_opentype.c
@@ -53,6 +53,35 @@
return 0;
}
+int
+aper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ void *buf;
+ void *bptr;
+ ssize_t size;
+ size_t toGo;
+
+ ASN_DEBUG("Open type put %s ...", td->name);
+
+ size = aper_encode_to_new_buffer(td, constraints, sptr, &buf);
+ if(size <= 0) return -1;
+
+ for(bptr = buf, toGo = size; toGo;) {
+ ssize_t maySave = aper_put_length(po, -1, toGo);
+ if(maySave < 0) break;
+ if(per_put_many_bits(po, bptr, maySave * 8)) break;
+ bptr = (char *)bptr + maySave;
+ toGo -= maySave;
+ }
+
+ FREEMEM(buf);
+ if(toGo) return -1;
+
+ ASN_DEBUG("Open type put %s of length %d + overhead (1byte?)",
+ td->name, size);
+
+ return 0;
+}
+
static asn_dec_rval_t
uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
diff --git a/skeletons/per_opentype.h b/skeletons/per_opentype.h
index facfaa6..2117efe 100644
--- a/skeletons/per_opentype.h
+++ b/skeletons/per_opentype.h
@@ -15,6 +15,8 @@
int uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po);
+int aper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po);
+
#ifdef __cplusplus
}
#endif
diff --git a/skeletons/per_support.c b/skeletons/per_support.c
index 5ecdc2e..21ea239 100644
--- a/skeletons/per_support.c
+++ b/skeletons/per_support.c
@@ -31,6 +31,16 @@
}
}
+int32_t
+aper_get_align(asn_per_data_t *pd) {
+
+ if(pd->nboff & 0x7) {
+ ASN_DEBUG("Aligning %d bits", 8 - (pd->nboff & 0x7));
+ return per_get_few_bits(pd, 8 - (pd->nboff & 0x7));
+ }
+ return 0;
+}
+
/*
* Extract a small number of bits (<= 31) from the specified PER data pointer.
*/
@@ -104,7 +114,7 @@
accum &= (((uint32_t)1 << nbits) - 1);
- ASN_DEBUG(" [PER got %2d<=%2d bits => span %d %+ld[%d..%d]:%02x (%d) => 0x%x]",
+ ASN_DEBUG(" [PER got %2d<=%2d bits => span %d %+ld[%d..%d]:%02x (%d) => 0x%02x]",
(int)nbits, (int)nleft,
(int)pd->moved,
(((long)pd->buffer) & 0xf),
@@ -123,6 +133,8 @@
per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int alright, int nbits) {
int32_t value;
+ ASN_DEBUG("align: %s, nbits %d", alright ? "YES":"NO", nbits);
+
if(alright && (nbits & 7)) {
/* Perform right alignment of a first few bits */
value = per_get_few_bits(pd, nbits & 0x07);
@@ -187,6 +199,36 @@
return (16384 * value);
}
+ssize_t
+aper_get_length(asn_per_data_t *pd, int range, int ebits, int *repeat) {
+ ssize_t value;
+
+ *repeat = 0;
+
+ if (range <= 65536 && range >= 0)
+ return aper_get_nsnnwn(pd, range);
+
+ if (aper_get_align(pd) < 0)
+ return -1;
+
+ if(ebits >= 0) return per_get_few_bits(pd, ebits);
+
+ value = per_get_few_bits(pd, 8);
+ if(value < 0) return -1;
+ if((value & 128) == 0) /* #10.9.3.6 */
+ return (value & 0x7F);
+ if((value & 64) == 0) { /* #10.9.3.7 */
+ value = ((value & 63) << 8) | per_get_few_bits(pd, 8);
+ if(value < 0) return -1;
+ return value;
+ }
+ value &= 63; /* this is "m" from X.691, #10.9.3.8 */
+ if(value < 1 || value > 4)
+ return -1;
+ *repeat = 1;
+ return (16384 * value);
+}
+
/*
* Get the normally small length "n".
* This procedure used to decode length of extensions bit-maps
@@ -211,6 +253,25 @@
}
}
+ssize_t
+aper_get_nslength(asn_per_data_t *pd) {
+ ssize_t length;
+
+ ASN_DEBUG("Getting normally small length");
+
+ if(per_get_few_bits(pd, 1) == 0) {
+ length = per_get_few_bits(pd, 6) + 1;
+ if(length <= 0) return -1;
+ ASN_DEBUG("l=%d", length);
+ return length;
+ } else {
+ int repeat;
+ length = aper_get_length(pd, -1, -1, &repeat);
+ if(length >= 0 && !repeat) return length;
+ return -1; /* Error, or do not support >16K extensions */
+ }
+}
+
/*
* Get the normally small non-negative whole number.
* X.691, #10.6
@@ -237,6 +298,40 @@
return value;
}
+ssize_t
+aper_get_nsnnwn(asn_per_data_t *pd, int range) {
+ ssize_t value;
+ int bytes = 0;
+
+ ASN_DEBUG("getting nsnnwn with range %d", range);
+
+ if(range <= 255) {
+ if (range < 0) return -1;
+ /* 1 -> 8 bits */
+ int i;
+ for (i = 1; i <= 8; i++) {
+ int upper = 1 << i;
+ if (upper >= range)
+ break;
+ }
+ value = per_get_few_bits(pd, i);
+ return value;
+ } else if (range == 256){
+ /* 1 byte */
+ bytes = 1;
+ return -1;
+ } else if (range <= 65536) {
+ /* 2 bytes */
+ bytes = 2;
+ } else {
+ return -1;
+ }
+ if (aper_get_align(pd) < 0)
+ return -1;
+ value = per_get_few_bits(pd, 8 * bytes);
+ return value;
+}
+
/*
* X.691-11/2008, #11.6
* Encoding of a normally small non-negative whole number
@@ -245,6 +340,7 @@
uper_put_nsnnwn(asn_per_outp_t *po, int n) {
int bytes;
+ ASN_DEBUG("uper put nsnnwn n %d", n);
if(n <= 63) {
if(n < 0) return -1;
return per_put_few_bits(po, n, 7);
@@ -405,6 +501,61 @@
return 0;
}
+int
+aper_put_nsnnwn(asn_per_outp_t *po, int range, int number) {
+ int bytes;
+
+ ASN_DEBUG("aper put nsnnwn %d with range %d", number, range);
+ /* 10.5.7.1 X.691 */
+ if(range < 0) {
+ int i;
+ for (i = 1; ; i++) {
+ int bits = 1 << (8 * i);
+ if (number <= bits)
+ break;
+ }
+ bytes = i;
+ assert(i <= 4);
+ }
+ if(range <= 255) {
+ int i;
+ for (i = 1; i <= 8; i++) {
+ int bits = 1 << i;
+ if (range <= bits)
+ break;
+ }
+ return per_put_few_bits(po, number, i);
+ } else if(range == 256) {
+ bytes = 1;
+ } else if(range <= 65536) {
+ bytes = 2;
+ } else { /* Ranges > 64K */
+ int i;
+ for (i = 1; ; i++) {
+ int bits = 1 << (8 * i);
+ if (range <= bits)
+ break;
+ }
+ assert(i <= 4);
+ bytes = i;
+ }
+ if(aper_put_align(po) < 0) /* Aligning on octet */
+ return -1;
+// if(per_put_few_bits(po, bytes, 8))
+// return -1;
+
+ return per_put_few_bits(po, number, 8 * bytes);
+}
+
+int aper_put_align(asn_per_outp_t *po) {
+
+ if(po->nboff & 0x7) {
+ ASN_DEBUG("Aligning %d bits", 8 - (po->nboff & 0x7));
+ if(per_put_few_bits(po, 0x00, (8 - (po->nboff & 0x7))))
+ return -1;
+ }
+ return 0;
+}
/*
* Output a large number of bits.
@@ -444,6 +595,8 @@
ssize_t
uper_put_length(asn_per_outp_t *po, size_t length) {
+ ASN_DEBUG("UPER put length %d", length);
+
if(length <= 127) /* #10.9.3.6 */
return per_put_few_bits(po, length, 8)
? -1 : (ssize_t)length;
@@ -458,6 +611,33 @@
? -1 : (ssize_t)(length << 14);
}
+ssize_t
+aper_put_length(asn_per_outp_t *po, int range, size_t length) {
+
+ ASN_DEBUG("APER put length %d with range %d", length, range);
+
+ /* 10.9 X.691 Note 2 */
+ if (range <= 65536 && range >= 0)
+ return aper_put_nsnnwn(po, range, length);
+
+ if (aper_put_align(po) < 0)
+ return -1;
+
+ if(length <= 127) /* #10.9.3.6 */{
+ return per_put_few_bits(po, length, 8)
+ ? -1 : (ssize_t)length;
+ }
+ else if(length < 16384) /* #10.9.3.7 */
+ return per_put_few_bits(po, length|0x8000, 16)
+ ? -1 : (ssize_t)length;
+
+ length >>= 14;
+ if(length > 4) length = 4;
+
+ return per_put_few_bits(po, 0xC0 | length, 8)
+ ? -1 : (ssize_t)(length << 14);
+}
+
/*
* Put the normally small length "n" into the stream.
@@ -481,3 +661,19 @@
return 0;
}
+int
+aper_put_nslength(asn_per_outp_t *po, size_t length) {
+
+ if(length <= 64) {
+ /* #10.9.3.4 */
+ if(length == 0) return -1;
+ return per_put_few_bits(po, length-1, 7) ? -1 : 0;
+ } else {
+ if(aper_put_length(po, -1, length) != (ssize_t)length) {
+ /* This might happen in case of >16K extensions */
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/skeletons/per_support.h b/skeletons/per_support.h
index a75ac94..181fe24 100644
--- a/skeletons/per_support.h
+++ b/skeletons/per_support.h
@@ -24,8 +24,8 @@
} flags;
int range_bits; /* Full number of bits in the range */
int effective_bits; /* Effective bits */
- long lower_bound; /* "lb" value */
- long upper_bound; /* "ub" value */
+ int64_t lower_bound; /* "lb" value */
+ int64_t upper_bound; /* "ub" value */
} asn_per_constraint_t;
typedef const struct asn_per_constraints_s {
struct asn_per_constraint_s value;
@@ -39,9 +39,9 @@
*/
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 */
- size_t moved; /* Number of bits moved through this bit 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;
@@ -71,15 +71,22 @@
int effective_bound_bits,
int *repeat);
+ssize_t aper_get_length(asn_per_data_t *pd,
+ int range,
+ int effective_bound_bits,
+ int *repeat);
+
/*
* Get the normally small length "n".
*/
ssize_t uper_get_nslength(asn_per_data_t *pd);
+ssize_t aper_get_nslength(asn_per_data_t *pd);
/*
* Get the normally small non-negative whole number.
*/
ssize_t uper_get_nsnnwn(asn_per_data_t *pd);
+ssize_t aper_get_nsnnwn(asn_per_data_t *pd, int range);
/* X.691-2008/11, #11.5.6 */
int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *v, int nbits);
@@ -110,6 +117,10 @@
int uper_put_constrained_whole_number_s(asn_per_outp_t *po, long v, int nbits);
int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int nbits);
+/* Align the current bit position to octet bundary */
+int aper_put_align(asn_per_outp_t *po);
+int32_t aper_get_align(asn_per_data_t *pd);
+
/*
* Put the length "n" to the Unaligned PER stream.
* This function returns the number of units which may be flushed
@@ -117,17 +128,23 @@
*/
ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length);
+ssize_t aper_put_length(asn_per_outp_t *po, int range, size_t length);
+
/*
* Put the normally small length "n" to the Unaligned PER stream.
* Returns 0 or -1.
*/
int uper_put_nslength(asn_per_outp_t *po, size_t length);
+int aper_put_nslength(asn_per_outp_t *po, size_t length);
+
/*
* Put the normally small non-negative whole number.
*/
int uper_put_nsnnwn(asn_per_outp_t *po, int n);
+int aper_put_nsnnwn(asn_per_outp_t *po, int range, int number);
+
#ifdef __cplusplus
}
#endif