mirror of https://gerrit.osmocom.org/asn1c
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.
This commit is contained in:
parent
62913d8b8e
commit
498c97170c
|
@ -775,4 +775,8 @@ asn_dec_rval_t OCTET_STRING_decode_uper(asn_codec_ctx_t *ctx, asn_TYPE_descripto
|
|||
|
||||
asn_enc_rval_t OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *cts, void *sptr, asn_per_outp_t *po) { asn_enc_rval_t er = { 0, 0, 0 }; (void)td; (void)cts; (void)sptr; (void)po; return er; }
|
||||
|
||||
asn_dec_rval_t OCTET_STRING_decode_aper(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *cts, void **sptr, asn_per_data_t *pd) { asn_dec_rval_t rv = { 0, 0 }; (void)ctx; (void)td; (void)cts; (void)sptr; (void)pd; return rv; }
|
||||
|
||||
asn_enc_rval_t OCTET_STRING_encode_aper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *cts, void *sptr, asn_per_outp_t *po) { asn_enc_rval_t er = { 0, 0, 0 }; (void)td; (void)cts; (void)sptr; (void)po; return er; }
|
||||
|
||||
size_t xer_whitespace_span(const void *chunk_buf, size_t chunk_size) { (void)chunk_buf; (void)chunk_size; return 0; }
|
||||
|
|
|
@ -1243,6 +1243,8 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
|
|||
OUT("td->xer_encoder = asn_DEF_%s.xer_encoder;\n", type_name);
|
||||
OUT("td->uper_decoder = asn_DEF_%s.uper_decoder;\n", type_name);
|
||||
OUT("td->uper_encoder = asn_DEF_%s.uper_encoder;\n", type_name);
|
||||
OUT("td->aper_decoder = asn_DEF_%s.aper_decoder;\n", type_name);
|
||||
OUT("td->aper_encoder = asn_DEF_%s.aper_encoder;\n", type_name);
|
||||
if(!terminal && !tags_count) {
|
||||
OUT("/* The next four lines are here because of -fknown-extern-type */\n");
|
||||
OUT("td->tags = asn_DEF_%s.tags;\n", type_name);
|
||||
|
@ -1395,7 +1397,39 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
|
|||
);
|
||||
OUT("}\n");
|
||||
OUT("\n");
|
||||
}
|
||||
|
||||
p = MKID(expr);
|
||||
if(HIDE_INNER_DEFS) OUT("static ");
|
||||
OUT("asn_enc_rval_t\n");
|
||||
OUT("%s", p);
|
||||
if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
|
||||
OUT("_encode_aper(asn_TYPE_descriptor_t *td,\n");
|
||||
INDENTED(
|
||||
OUT("\tasn_per_constraints_t *constraints,\n");
|
||||
OUT("\tvoid *structure, asn_per_outp_t *per_out) {\n");
|
||||
OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
|
||||
p, expr->_type_unique_index);
|
||||
OUT("return td->aper_encoder(td, constraints, structure, per_out);\n");
|
||||
);
|
||||
OUT("}\n");
|
||||
OUT("\n");
|
||||
|
||||
p = MKID(expr);
|
||||
|
||||
if(HIDE_INNER_DEFS) OUT("static ");
|
||||
OUT("asn_dec_rval_t\n");
|
||||
OUT("%s", p);
|
||||
if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
|
||||
OUT("_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
|
||||
INDENTED(
|
||||
OUT("\tasn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {\n");
|
||||
OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
|
||||
p, expr->_type_unique_index);
|
||||
OUT("return td->aper_decoder(opt_codec_ctx, td, constraints, structure, per_data);\n");
|
||||
);
|
||||
OUT("}\n");
|
||||
OUT("\n");
|
||||
}
|
||||
|
||||
REDIR(OT_FUNC_DECLS);
|
||||
|
||||
|
@ -1416,6 +1450,8 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
|
|||
if(arg->flags & A1C_GEN_PER) {
|
||||
OUT("per_type_decoder_f %s_decode_uper;\n", p);
|
||||
OUT("per_type_encoder_f %s_encode_uper;\n", p);
|
||||
OUT("per_type_decoder_f %s_decode_aper;\n", p);
|
||||
OUT("per_type_encoder_f %s_encode_aper;\n", p);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2003,7 +2039,7 @@ emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
|
|||
break;
|
||||
case ASN_STRING_UniversalString:
|
||||
OUT("{ APC_CONSTRAINED,\t32, 32,"
|
||||
" 0, 2147483647 }"
|
||||
" 0, 2147483647L }"
|
||||
" /* special case 1 */\n");
|
||||
goto avoid;
|
||||
default:
|
||||
|
@ -2456,8 +2492,12 @@ emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_
|
|||
if(arg->flags & A1C_GEN_PER) {
|
||||
FUNCREF(decode_uper);
|
||||
FUNCREF(encode_uper);
|
||||
FUNCREF(decode_aper);
|
||||
FUNCREF(encode_aper);
|
||||
} else {
|
||||
OUT("0, 0,\t/* No PER support, "
|
||||
OUT("0, 0,\t/* No UPER support, "
|
||||
"use \"-gen-PER\" to enable */\n");
|
||||
OUT("0, 0,\t/* No APER support, "
|
||||
"use \"-gen-PER\" to enable */\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -383,7 +383,7 @@ asn1c_type_fits_long(arg_t *arg, asn1p_expr_t *expr) {
|
|||
if(left.type == ARE_VALUE
|
||||
&& left.value >= 0
|
||||
&& right.type == ARE_VALUE
|
||||
&& right.value > 2147483647
|
||||
&& right.value > 2147483647L
|
||||
&& right.value <= 4294967295UL)
|
||||
return FL_FITS_UNSIGN;
|
||||
|
||||
|
|
|
@ -117,17 +117,25 @@ int asn1c_compiled_output(arg_t *arg, const char *fmt, ...);
|
|||
* Format LONG_MIN according to C90 rules.
|
||||
*/
|
||||
#define OINT(iv) do { \
|
||||
if(iv == (-2147483647L - 1)) \
|
||||
if(iv == (-2147483647L - 1)) \
|
||||
OUT("(-2147483647L - 1)"); \
|
||||
else \
|
||||
OUT("%" PRIdASN, iv); \
|
||||
else if (iv > 4294967296UL) \
|
||||
OUT("%" PRIdASN "ull", iv); \
|
||||
else if (iv > 2147483647L) \
|
||||
OUT("%" PRIdASN "ul", iv); \
|
||||
else \
|
||||
OUT("%" PRIdASN "l", iv); \
|
||||
} while(0)
|
||||
|
||||
#define OINTS(iv) do { \
|
||||
if(iv == (-2147483647L - 1)) \
|
||||
if(iv == (-2147483647L - 1)) \
|
||||
OUT("(-2147483647L - 1)"); \
|
||||
else \
|
||||
OUT("% " PRIdASN, iv); \
|
||||
else if (iv > 4294967296UL) \
|
||||
OUT("%" PRIdASN "ull", iv); \
|
||||
else if (iv > 2147483647L) \
|
||||
OUT("%" PRIdASN "ul", iv); \
|
||||
else \
|
||||
OUT("% " PRIdASN "l", iv); \
|
||||
} while(0)
|
||||
|
||||
#endif /* _ASN1_COMPILED_OUTPUT_H_ */
|
||||
|
|
|
@ -21,7 +21,10 @@ asn_TYPE_descriptor_t asn_DEF_ANY = {
|
|||
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 @@ ANY_fromType(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
|
|||
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_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -32,10 +32,13 @@ xer_type_encoder_f ANY_encode_xer;
|
|||
|
||||
/* 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( \
|
||||
|
|
|
@ -29,6 +29,8 @@ asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
|
|||
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)
|
||||
|
|
|
@ -35,6 +35,8 @@ asn_TYPE_descriptor_t asn_DEF_BMPString = {
|
|||
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)
|
||||
|
|
|
@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
|
|||
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 @@ BOOLEAN_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
|||
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 @@ BOOLEAN_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
|
||||
_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);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ xer_type_decoder_f BOOLEAN_decode_xer;
|
|||
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
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ asn_TYPE_descriptor_t asn_DEF_ENUMERATED = {
|
|||
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 @@ ENUMERATED_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td
|
|||
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 @@ ENUMERATED_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ extern asn_TYPE_descriptor_t asn_DEF_ENUMERATED;
|
|||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_GeneralString = {
|
|||
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)
|
||||
|
|
|
@ -178,6 +178,8 @@ asn_TYPE_descriptor_t asn_DEF_GeneralizedTime = {
|
|||
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)
|
||||
|
|
|
@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_GraphicString = {
|
|||
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)
|
||||
|
|
|
@ -29,6 +29,8 @@ asn_TYPE_descriptor_t asn_DEF_IA5String = {
|
|||
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)
|
||||
|
|
|
@ -30,6 +30,8 @@ asn_TYPE_descriptor_t asn_DEF_INTEGER = {
|
|||
#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 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
|
|||
(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 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
|||
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 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
|||
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) {
|
||||
|
@ -698,7 +843,7 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
|| 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");
|
||||
|
@ -715,7 +860,7 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
|| 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");
|
||||
|
@ -742,7 +887,7 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -761,6 +906,129 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
|
||||
#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;
|
||||
|
@ -821,6 +1089,66 @@ asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -853,6 +1181,38 @@ asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -878,6 +1238,86 @@ asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -18,7 +18,7 @@ extern asn_TYPE_descriptor_t asn_DEF_INTEGER;
|
|||
|
||||
/* 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_decoder_f INTEGER_decode_xer;
|
|||
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 @@ per_type_encoder_f INTEGER_encode_uper;
|
|||
* -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);
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ asn_TYPE_descriptor_t asn_DEF_ISO646String = {
|
|||
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)
|
||||
|
|
|
@ -25,6 +25,8 @@ asn_TYPE_descriptor_t asn_DEF_NULL = {
|
|||
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 @@ NULL_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
|||
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 @@ NULL_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ xer_type_decoder_f NULL_decode_xer;
|
|||
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
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
|
|||
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 @@ NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
|
|||
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 @@ NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
_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);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
|
|||
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
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
|
|||
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 @@ NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
|
|||
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 @@ NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -29,6 +29,8 @@ xer_type_decoder_f NativeInteger_decode_xer;
|
|||
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
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ asn_TYPE_descriptor_t asn_DEF_NativeReal = {
|
|||
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 @@ NativeReal_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
|
|||
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 @@ NativeReal_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -27,6 +27,8 @@ xer_type_decoder_f NativeReal_decode_xer;
|
|||
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
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ asn_TYPE_descriptor_t asn_DEF_NumericString = {
|
|||
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)
|
||||
|
|
|
@ -27,6 +27,8 @@ asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = {
|
|||
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)
|
||||
|
|
|
@ -36,6 +36,8 @@ asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
|
|||
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 @@ OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx,
|
|||
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 @@ OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
|
|||
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 @@ OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
|
|||
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 @@ OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
|
|||
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 @@ OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
|
|||
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 @@ OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
|
|||
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 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
|
|||
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 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
|
|||
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 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
|
|||
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 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
}
|
||||
|
||||
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 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
/* 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 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
_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) {
|
||||
|
|
|
@ -32,6 +32,8 @@ xer_type_encoder_f OCTET_STRING_encode_xer;
|
|||
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. *
|
||||
|
|
|
@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_ObjectDescriptor = {
|
|||
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)
|
||||
|
|
|
@ -59,6 +59,8 @@ asn_TYPE_descriptor_t asn_DEF_PrintableString = {
|
|||
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)
|
||||
|
|
|
@ -51,6 +51,8 @@ asn_TYPE_descriptor_t asn_DEF_REAL = {
|
|||
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]),
|
||||
|
@ -367,6 +369,21 @@ REAL_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
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;
|
||||
|
|
|
@ -21,6 +21,8 @@ xer_type_decoder_f REAL_decode_xer;
|
|||
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. *
|
||||
|
|
|
@ -28,6 +28,8 @@ asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = {
|
|||
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)
|
||||
|
|
|
@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_T61String = {
|
|||
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)
|
||||
|
|
|
@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_TeletexString = {
|
|||
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)
|
||||
|
|
|
@ -40,6 +40,8 @@ asn_TYPE_descriptor_t asn_DEF_UTCTime = {
|
|||
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)
|
||||
|
|
|
@ -25,6 +25,8 @@ asn_TYPE_descriptor_t asn_DEF_UTF8String = {
|
|||
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)
|
||||
|
|
|
@ -35,6 +35,8 @@ asn_TYPE_descriptor_t asn_DEF_UniversalString = {
|
|||
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)
|
||||
|
|
|
@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_VideotexString = {
|
|||
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)
|
||||
|
|
|
@ -29,6 +29,8 @@ asn_TYPE_descriptor_t asn_DEF_VisibleString = {
|
|||
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)
|
||||
|
|
|
@ -20,7 +20,7 @@ extern "C" {
|
|||
#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 get_asn1c_environment_version(void); /* Run-time version */
|
|||
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
|
||||
|
|
|
@ -904,7 +904,88 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
|||
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) {
|
||||
|
@ -917,7 +998,7 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
|
||||
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;
|
||||
|
@ -987,7 +1068,87 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
_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,
|
||||
|
|
|
@ -48,6 +48,8 @@ xer_type_decoder_f CHOICE_decode_xer;
|
|||
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
|
||||
|
|
|
@ -1239,6 +1239,219 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
|||
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) {
|
||||
|
@ -1282,7 +1495,7 @@ SEQUENCE_handle_extensions(asn_TYPE_descriptor_t *td, void *sptr,
|
|||
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;
|
||||
|
||||
|
@ -1420,3 +1633,130 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
_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);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,8 @@ xer_type_decoder_f SEQUENCE_decode_xer;
|
|||
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
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ SEQUENCE_OF_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
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 @@ SEQUENCE_OF_encode_uper(asn_TYPE_descriptor_t *td,
|
|||
_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);
|
||||
}
|
||||
|
|
|
@ -22,9 +22,11 @@ extern "C" {
|
|||
#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
|
||||
}
|
||||
|
|
|
@ -573,6 +573,181 @@ SET_encode_der(asn_TYPE_descriptor_t *td,
|
|||
_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; \
|
||||
|
|
|
@ -53,7 +53,9 @@ der_type_encoder_f SET_encode_der;
|
|||
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. *
|
||||
|
|
|
@ -884,7 +884,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
|||
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 */
|
||||
|
@ -901,7 +901,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
|||
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;
|
||||
|
@ -951,3 +951,91 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ xer_type_decoder_f SET_OF_decode_xer;
|
|||
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
|
||||
}
|
||||
|
|
|
@ -99,6 +99,8 @@ typedef struct asn_TYPE_descriptor_s {
|
|||
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. *
|
||||
|
|
|
@ -36,6 +36,35 @@ uper_decode_complete(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
|||
return rval;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -91,3 +120,57 @@ uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sp
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,29 @@ asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx,
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -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 @@ uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_
|
|||
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 @@ uper_encode_to_new_buffer(asn_TYPE_descriptor_t *td, asn_per_constraints_t *cons
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ _uper_encode_flush_outp(asn_per_outp_t *po) {
|
|||
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 @@ uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constrain
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,12 @@ asn_enc_rval_t uper_encode_to_buffer(
|
|||
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 @@ ssize_t uper_encode_to_new_buffer(
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -53,6 +53,35 @@ uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints
|
|||
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) {
|
||||
|
|
|
@ -15,6 +15,8 @@ int uper_open_type_skip(asn_codec_ctx_t *opt_codec_ctx, asn_per_data_t *pd);
|
|||
|
||||
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
|
||||
|
|
|
@ -31,6 +31,16 @@ per_get_undo(asn_per_data_t *pd, int nbits) {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ per_get_few_bits(asn_per_data_t *pd, int nbits) {
|
|||
|
||||
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 @@ int
|
|||
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 @@ uper_get_length(asn_per_data_t *pd, int ebits, int *repeat) {
|
|||
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 @@ uper_get_nslength(asn_per_data_t *pd) {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ uper_get_nsnnwn(asn_per_data_t *pd) {
|
|||
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 @@ int
|
|||
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 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
|
|||
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 @@ per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int nbits) {
|
|||
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 @@ uper_put_length(asn_per_outp_t *po, size_t length) {
|
|||
? -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 @@ uper_put_nslength(asn_per_outp_t *po, size_t length) {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ typedef const struct asn_per_constraint_s {
|
|||
} 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 const struct asn_per_constraints_s {
|
|||
*/
|
||||
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 @@ ssize_t uper_get_length(asn_per_data_t *pd,
|
|||
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 per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits);
|
|||
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 @@ int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int
|
|||
*/
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue