Compare commits

...

12 Commits

Author SHA1 Message Date
Harald Welte b9b7c9e54d aper fix for decoding constrained integer with lower boundary
When decoding a constrained integer with a lower boundary, we need
to make sure the lower bound is added after decoding the raw offset
inside the range.

Before this change, RANAP_CauseMisc_unspecified_failure (115) would be
encoded as 2 (115 - 113 = 2), but would be decoded as 2, rather than
113+2 = 115.

Code for this was taken from
openairinterface5g/openair3/S1AP/MESSAGES/ASN1/asn1cpatch.p0 which
unfortunately doesn't carry much of a revision history :/
2016-07-06 17:08:57 +02:00
Holger Hans Peter Freyther 2edc63e3aa automake: automake 1.11.1 does not have this macro, ignore it then 2016-07-06 17:08:57 +02:00
Harald Welte 5e2364f614 prefixing of generated types using a ASN1C_PREFIX environment variable
When generating code for multiple ASN.1 syntaxes that have clashing
names, we need to add a prefix in order to prevent clashes in the global
C symbol namespace.  Using the ASN1C_PREFIX environment variable and
this patch serves as a work-around to that.  All non-basic type names
as well as references to that type and source code + header file names
will be pre-fixed accordingly.
2016-07-06 17:08:57 +02:00
roux 840ee6d2c7 Fix a bug in asn1c PER code when skipping unknown extension
Basically when skiping an unknown extension, asn1c did read 24 bits per
24 bits and later on failed if the remaining bits (up to 23) were
superior to 8.  The patch reads 1 bit per 1 bit.

(imported from openairinterface5g/openair2/RRC/LITE/MESSAGES/asn1c/asn1cpatch.p0)
2016-07-06 17:05:48 +02:00
Harald Welte 17c282425a fix APER encoding of integer (backport from openairinterface)
The number of bytes used by an APER encoded integer depends on its
actually encoded value, not on the maximum value that could be possibly
encoded.

The old code would e.g. always use 24 bits if the maximum encoded value
would require 24 bits.

To give an example RANAP MaxBitrate (INTEER 1 .. 16000000) value 64000
was previously encoded as "80 00 f9 ff", while it is now the correct
representation "40 f9 ff".

Thanks to Dieter Spaar for detecting this problem in the Osmo-IUH
generated RANAP output, and thanks to openairinterface for fixing the
bug in their code (sadly not contributed to upstream asn1c, though).
2016-07-06 17:05:48 +02:00
Harald Welte 2b3068fb85 APER: Fix encoding of INTEGER with lower_bound != 0
When encoding an INTEGER, we need to subtract the lower bound before
encoding the value.  This is specified in Clause 10.5.7.x of X.691.

The decoder already does this correct, but the encoder was wrong.
2016-07-06 17:05:48 +02:00
Harald Welte b9068d4cac skeletons: Fix compiler warnings introduced by Eurecom aper patch
... some of which is related to the recent 'constification' of
mainline asn1c.
2016-07-06 17:05:48 +02:00
Sylvain Munaut cc803bd0b8 skeletons: Print member's name in CHOICE print
Sometimes, if the choice is a null or integer or ...
it's not easy to know what has really been selected without
the choice member name.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2016-07-06 17:05:48 +02:00
Sylvain Munaut 96ed86a274 skeletons: Add verbose pretty print for enumerated types
This is just much easier to read when reading the text dumps.
2016-07-06 17:05:48 +02:00
Harald Welte b3a2304ce0 aper: fixup after port 2016-07-06 17:05:48 +02:00
Harald Welte 7fd73b9274 Support automake-1.15
Without this, autoreconf with automake-1.15 fails due to the "-Werror"
2016-07-06 17:05:48 +02:00
Harald Welte 0b57b08e0d 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.
2016-07-06 17:03:12 +02:00
66 changed files with 2871 additions and 64 deletions

View File

@ -846,6 +846,30 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *cts,
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;

View File

@ -5,7 +5,10 @@ AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_MACRO_DIR([m4])
LT_INIT
AM_MAINTAINER_MODE
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AM_PROG_LIBTOOL
dnl Checks for programs.
AC_PROG_CC

View File

@ -1242,6 +1242,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);
@ -1394,7 +1396,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);
@ -1415,6 +1449,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");
}

View File

@ -50,6 +50,10 @@ asn1c_make_identifier(enum ami_flags_e flags, asn1p_expr_t *expr, ...) {
char *second = 0;
ssize_t size;
char *p;
char *prefix = NULL;
if (flags & AMI_USE_PREFIX)
prefix = getenv("ASN1C_PREFIX");
if(expr) {
/*
@ -74,6 +78,8 @@ asn1c_make_identifier(enum ami_flags_e flags, asn1p_expr_t *expr, ...) {
va_end(ap);
if(size == -1) return NULL;
if(prefix)
size += 1 + strlen(prefix);
/*
* Make sure we have this amount of storage.
*/
@ -93,8 +99,12 @@ asn1c_make_identifier(enum ami_flags_e flags, asn1p_expr_t *expr, ...) {
*/
va_start(ap, expr);
p = storage;
if(prefix) {
strcpy(storage, prefix);
p += strlen(prefix);
}
nextstr = "";
for(p = storage, str = 0; str || nextstr; str = nextstr) {
for(str = 0; str || nextstr; str = nextstr) {
int subst_made = 0;
nextstr = second ? second : va_arg(ap, char *);
@ -262,23 +272,34 @@ asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format) {
switch(_format) {
case TNF_UNMODIFIED:
return asn1c_make_identifier(AMI_MASK_ONLY_SPACES,
return asn1c_make_identifier(stdname ? AMI_MASK_ONLY_SPACES :
AMI_MASK_ONLY_SPACES | AMI_USE_PREFIX,
0, exprid ? exprid->Identifier : typename, 0);
case TNF_INCLUDE:
case TNF_INCLUDE: {
/* as we have the quote marks " or < preceding the type
* name, we cannot simply have asn1c_make_identifier
* generate the prefix. Then we would end up with
* strings like PREFIX_<foo.h>" */
char *prefix = getenv("ASN1C_PREFIX");
if (!prefix)
prefix = "";
return asn1c_make_identifier(
AMI_MASK_ONLY_SPACES | AMI_NODELIMITER,
0, ((!stdname || (arg->flags & A1C_INCLUDES_QUOTED))
? "\"" : "<"),
? "\"" : "<"), stdname ? "" : prefix,
exprid ? exprid->Identifier : typename,
((!stdname || (arg->flags & A1C_INCLUDES_QUOTED))
? ".h\"" : ".h>"), 0);
}
case TNF_SAFE:
return asn1c_make_identifier(0, exprid, typename, 0);
return asn1c_make_identifier(stdname ? 0 : AMI_USE_PREFIX,
exprid, typename, 0);
case TNF_CTYPE: /* C type */
return asn1c_make_identifier(0, exprid,
exprid?"t":typename, exprid?0:"t", 0);
return asn1c_make_identifier(stdname ? 0 : AMI_USE_PREFIX,
exprid, exprid?"t":typename, exprid?0:"t", 0);
case TNF_RSAFE: /* Recursion-safe type */
return asn1c_make_identifier(AMI_CHECK_RESERVED, 0,
return asn1c_make_identifier(stdname ? AMI_CHECK_RESERVED :
AMI_CHECK_RESERVED | AMI_USE_PREFIX, 0,
"struct", " ", typename, 0);
}
@ -383,7 +404,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 <= (asn1c_integer_t)(4294967295UL))
return FL_FITS_UNSIGN;

View File

@ -10,6 +10,7 @@ enum ami_flags_e {
AMI_MASK_ONLY_SPACES = 1, /* Mask only spaces, everything else's safe */
AMI_CHECK_RESERVED = 2, /* Check against reserved keywords */
AMI_NODELIMITER = 4, /* Do not put delimiter, just concatenate */
AMI_USE_PREFIX = 8, /* Use Prefix when generating identifier */
};
char *asn1c_make_identifier(enum ami_flags_e, asn1p_expr_t *expr, ...);

View File

@ -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 */

View File

@ -245,10 +245,19 @@ asn1f_fix_module__phase_2(arg_t *arg) {
asn1p_expr_t *expr;
int rvalue = 0;
int ret;
char *prefix = getenv("ASN1C_PREFIX");
TQ_FOR(expr, &(arg->mod->members), next) {
arg->expr = expr;
if (prefix) {
char *tmp = malloc(strlen(prefix)+strlen(expr->Identifier)+1);
sprintf(tmp, "%s%s", prefix, expr->Identifier);
expr->Identifier = tmp;
/* FIXME: what about old memory ? */
#warning "Fix this memory leak"
}
/*
* Dereference DEFAULT values.
*/

View File

@ -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;

View File

@ -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( \

View File

@ -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)

View File

@ -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)

View File

@ -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);
}

View File

@ -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
}

View File

@ -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);
}

View File

@ -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
}

View File

@ -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)

View File

@ -181,6 +181,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)

View File

@ -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)

View File

@ -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)

View File

@ -27,9 +27,13 @@ asn_TYPE_descriptor_t asn_DEF_INTEGER = {
#ifdef ASN_DISABLE_PER_SUPPORT
0,
0,
0,
0,
#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 +414,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 +612,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 +669,158 @@ 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) +
(((ct->range_bits % 8) > 0) ? 1 : 0);
int length = 0, i;
int64_t value = 0;
for (i = 1; ; i++) {
int upper = 1 << i;
if (upper >= max_range_bytes)
break;
}
ASN_DEBUG("Can encode %d (%d bytes) in %d bits", ct->range_bits,
max_range_bytes, i);
if ((length = per_get_few_bits(pd, i)) < 0)
_ASN_DECODE_FAILED;
/* X.691 #12.2.6 length determinant + lb (1) */
length += 1;
ASN_DEBUG("Got length %d", length);
if (aper_get_align(pd) != 0)
_ASN_DECODE_STARVED;
while (length--) {
int buf = per_get_few_bits(pd, 8);
if (buf < 0)
_ASN_DECODE_STARVED;
value += (((int64_t)buf) << (8 * length));
}
value += ct->lower_bound;
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);
} 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;
}
value += ct->lower_bound;
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);
}
return rval;
} else {
_ASN_DECODE_FAILED;
}
} else {
ASN_DEBUG("Decoding unconstrained integer %s", td->name);
}
/* X.691, #12.2.3, #12.2.4 */
do {
ssize_t len;
void *p;
int ret;
/* Get the PER length */
len = aper_get_length(pd, -1, -1, &repeat);
if(len < 0) _ASN_DECODE_STARVED;
p = REALLOC(st->buf, st->size + len + 1);
if(!p) _ASN_DECODE_FAILED;
st->buf = (uint8_t *)p;
ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
if(ret < 0) _ASN_DECODE_STARVED;
st->size += len;
} while(repeat);
st->buf[st->size] = 0; /* JIC */
/* #12.2.3 */
if(ct && ct->lower_bound) {
/*
* TODO: replace by in-place arithmetics.
*/
long value;
if(asn_INTEGER2long(st, &value))
_ASN_DECODE_FAILED;
if(asn_long2INTEGER(st, value + ct->lower_bound))
_ASN_DECODE_FAILED;
}
return rval;
}
asn_enc_rval_t
INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
@ -699,7 +855,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");
@ -716,7 +872,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");
@ -743,7 +899,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;
}
@ -760,6 +916,147 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
ASN__ENCODED_OK(er);
}
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 %ld (%lu) with range %d bits",
value, value - ct->lower_bound, ct->range_bits);
unsigned long v = value - ct->lower_bound;
/* #12 <= 8 -> alignment ? */
if (ct->range_bits < 8) {
if(per_put_few_bits(po, 0x00 | v, 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 | v, 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 | v,
16))
_ASN_ENCODE_FAILED;
} else {
/* TODO: extend to >64 bits */
int64_t v64 = v;
int i, j;
int max_range_bytes = (ct->range_bits >> 3) +
(((ct->range_bits % 8) > 0) ? 1 : 0);
for (i = 1; ; i++) {
int upper = 1 << i;
if (upper >= max_range_bytes)
break;
}
for (j = sizeof(int64_t) -1; j != 0; j--) {
uint8_t val;
val = v64 >> (j * 8);
if (val != 0)
break;
}
/* Putting length in the minimum number of bits ex: 5 = 3bits */
if (per_put_few_bits(po, j, i))
_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 <= j; i++) {
if(per_put_few_bits(po, (v64 >> (8 * (j - i))) & 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);
}
#endif /* ASN_DISABLE_PER_SUPPORT */
int
@ -822,6 +1119,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;
@ -854,6 +1211,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;
@ -879,6 +1268,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;

View File

@ -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);

View File

@ -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)

View File

@ -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);
}

View File

@ -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
}

View File

@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
"ENUMERATED", /* The ASN.1 type is still ENUMERATED */
"ENUMERATED",
NativeInteger_free,
NativeInteger_print,
NativeEnumerated_print,
asn_generic_no_constraint,
NativeInteger_decode_ber,
NativeInteger_encode_der,
@ -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,99 @@ 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);
}
int
NativeEnumerated_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
const long *native = (const long *)sptr;
char scratch[256];
int ret;
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(native) {
const asn_INTEGER_enum_map_t *map = INTEGER_map_value2enum(specs, *native);
if (map && map->enum_len && map->enum_name) {
ret = snprintf(scratch, sizeof(scratch),
"%s", map->enum_name);
} else {
ret = snprintf(scratch, sizeof(scratch),
(specs && specs->field_unsigned)
? "%lu" : "%ld", *native);
}
assert(ret > 0 && (size_t)ret < sizeof(scratch));
return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
} else {
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
}
}

View File

@ -24,6 +24,9 @@ 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;
asn_struct_print_f NativeEnumerated_print;
#ifdef __cplusplus
}

View File

@ -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.
*/

View File

@ -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
}

View File

@ -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.
*/

View File

@ -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
}

View File

@ -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)

View File

@ -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)

View File

@ -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) {

View File

@ -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. *

View File

@ -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)

View File

@ -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)

View File

@ -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]),
@ -390,6 +392,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;

View File

@ -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. *

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -905,7 +905,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) {
@ -918,7 +999,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;
@ -988,7 +1069,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,
@ -1018,11 +1179,9 @@ CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
}
/* Print member's name and stuff */
if(0) {
if(cb(elm->name, strlen(elm->name), app_key) < 0
|| cb(": ", 2, app_key) < 0)
return -1;
}
if(cb(elm->name, strlen(elm->name), app_key) < 0
|| cb(": ", 2, app_key) < 0)
return -1;
return elm->type->print_struct(elm->type, memb_ptr, ilevel,
cb, app_key);

View File

@ -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

View File

@ -1242,6 +1242,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) {
@ -1285,7 +1498,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;
@ -1423,3 +1636,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);
}

View File

@ -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
}

View File

@ -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);
}

View File

@ -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
}

View File

@ -573,6 +573,186 @@ 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_ENCODE_FAILED;
}
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_DECODE_FAILED;
}
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;
int t2m_build_own = (specs->tag2el_count != td->elements_count);
const asn_TYPE_tag2member_t *t2m;
asn_TYPE_tag2member_t *t2m_build;
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_build = (asn_TYPE_tag2member_t *)alloca(
td->elements_count * sizeof(t2m[0]));
if(!t2m_build) _ASN_ENCODE_FAILED; /* There are such platforms */
t2m_count = 0;
} else {
t2m_build = NULL;
/*
* There is no untagged CHOICE in this SET.
* Employ existing table.
*/
}
/*
* Gather the length of the underlying members sequence.
*/
for(edx = 0; edx < td->elements_count; edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
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_build[t2m_count].el_no = edx;
t2m_build[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_build[t2m_count].el_no = edx;
t2m_build[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_build, t2m_count, sizeof(specs->tag2el[0]), _t2e_cmp);
t2m = t2m_build;
} else {
/*
* Tags are already sorted by the compiler.
*/
t2m = specs->tag2el;
t2m_count = specs->tag2el_count;
}
assert(t2m_count == td->elements_count);
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; \

View File

@ -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. *

View File

@ -885,7 +885,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 */
@ -902,7 +902,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;
@ -952,3 +952,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;
}

View File

@ -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
}

View File

@ -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. *

View File

@ -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;
}

View File

@ -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.
*/

View File

@ -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;
}

View File

@ -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.
*/

View File

@ -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) {
@ -277,7 +306,7 @@ uper_sot_suck(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
(void)constraints;
(void)sptr;
while(per_get_few_bits(pd, 24) >= 0);
while(per_get_few_bits(pd, 1) >= 0);
rv.code = RC_OK;
rv.consumed = pd->moved;

View File

@ -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

View File

@ -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;
}

View File

@ -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