--- /dev/null
+/*-\r
+ * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.\r
+ * Redistribution and modifications are permitted subject to BSD license.\r
+ */\r
+/*\r
+ * Read the NativeInteger.h for the explanation wrt. differences between\r
+ * INTEGER and NativeInteger.\r
+ * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this\r
+ * implementation deals with the standard (machine-specific) representation\r
+ * of them instead of using the platform-independent buffer.\r
+ */\r
+#include <asn_internal.h>\r
+#include <NativeEnumerated.h>\r
+\r
+/*\r
+ * NativeEnumerated basic type description.\r
+ */\r
+static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {\r
+ (ASN_TAG_CLASS_UNIVERSAL | (10 << 2))\r
+};\r
+asn_TYPE_operation_t asn_OP_NativeEnumerated = {\r
+ NativeInteger_free,\r
+ NativeInteger_print,\r
+ NativeInteger_compare,\r
+ NativeInteger_decode_ber,\r
+ NativeInteger_encode_der,\r
+ NativeInteger_decode_xer,\r
+ NativeEnumerated_encode_xer,\r
+#ifdef ASN_DISABLE_OER_SUPPORT\r
+ 0,\r
+ 0,\r
+#else\r
+ NativeEnumerated_decode_oer,\r
+ NativeEnumerated_encode_oer,\r
+#endif /* ASN_DISABLE_OER_SUPPORT */\r
+#ifdef ASN_DISABLE_PER_SUPPORT\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+#else\r
+ NativeEnumerated_decode_uper,\r
+ NativeEnumerated_encode_uper,\r
+ NativeEnumerated_decode_aper,\r
+ NativeEnumerated_encode_aper,\r
+#endif /* ASN_DISABLE_PER_SUPPORT */\r
+ NativeEnumerated_random_fill,\r
+ 0 /* Use generic outmost tag fetcher */\r
+};\r
+asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {\r
+ "ENUMERATED", /* The ASN.1 type is still ENUMERATED */\r
+ "ENUMERATED",\r
+ &asn_OP_NativeEnumerated,\r
+ asn_DEF_NativeEnumerated_tags,\r
+ sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),\r
+ asn_DEF_NativeEnumerated_tags, /* Same as above */\r
+ sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),\r
+ { 0, 0, asn_generic_no_constraint },\r
+ 0, 0, /* No members */\r
+ 0 /* No specifics */\r
+};\r
+\r
+asn_enc_rval_t\r
+NativeEnumerated_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,\r
+ int ilevel, enum xer_encoder_flags_e flags,\r
+ asn_app_consume_bytes_f *cb, void *app_key) {\r
+ const asn_INTEGER_specifics_t *specs =\r
+ (const asn_INTEGER_specifics_t *)td->specifics;\r
+ asn_enc_rval_t er = {0,0,0};\r
+ const long *native = (const long *)sptr;\r
+ const asn_INTEGER_enum_map_t *el;\r
+\r
+ (void)ilevel;\r
+ (void)flags;\r
+\r
+ if(!native) ASN__ENCODE_FAILED;\r
+\r
+ el = INTEGER_map_value2enum(specs, *native);\r
+ if(el) {\r
+ er.encoded =\r
+ asn__format_to_callback(cb, app_key, "<%s/>", el->enum_name);\r
+ if(er.encoded < 0) ASN__ENCODE_FAILED;\r
+ ASN__ENCODED_OK(er);\r
+ } else {\r
+ ASN_DEBUG(\r
+ "ASN.1 forbids dealing with "\r
+ "unknown value of ENUMERATED type");\r
+ ASN__ENCODE_FAILED;\r
+ }\r
+}\r
+\r
+asn_dec_rval_t\r
+NativeEnumerated_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,\r
+ const asn_TYPE_descriptor_t *td,\r
+ const asn_per_constraints_t *constraints,\r
+ void **sptr, asn_per_data_t *pd) {\r
+ const asn_INTEGER_specifics_t *specs = td->specifics;\r
+ asn_dec_rval_t rval = { RC_OK, 0 };\r
+ long *native = (long *)*sptr;\r
+ const asn_per_constraint_t *ct;\r
+ long value;\r
+\r
+ (void)opt_codec_ctx;\r
+\r
+ if(constraints) ct = &constraints->value;\r
+ else if(td->encoding_constraints.per_constraints)\r
+ ct = &td->encoding_constraints.per_constraints->value;\r
+ else ASN__DECODE_FAILED; /* Mandatory! */\r
+ if(!specs) ASN__DECODE_FAILED;\r
+\r
+ if(!native) {\r
+ native = (long *)(*sptr = CALLOC(1, sizeof(*native)));\r
+ if(!native) ASN__DECODE_FAILED;\r
+ }\r
+\r
+ ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);\r
+\r
+ if(ct->flags & APC_EXTENSIBLE) {\r
+ int inext = per_get_few_bits(pd, 1);\r
+ if(inext < 0) ASN__DECODE_STARVED;\r
+ if(inext) ct = 0;\r
+ }\r
+\r
+ if(ct && ct->range_bits >= 0) {\r
+ value = per_get_few_bits(pd, ct->range_bits);\r
+ if(value < 0) ASN__DECODE_STARVED;\r
+ if(value >= (specs->extension\r
+ ? specs->extension - 1 : specs->map_count))\r
+ ASN__DECODE_FAILED;\r
+ } else {\r
+ if(!specs->extension)\r
+ ASN__DECODE_FAILED;\r
+ /*\r
+ * X.691, #10.6: normally small non-negative whole number;\r
+ */\r
+ value = uper_get_nsnnwn(pd);\r
+ if(value < 0) ASN__DECODE_STARVED;\r
+ value += specs->extension - 1;\r
+ if(value >= specs->map_count)\r
+ ASN__DECODE_FAILED;\r
+ }\r
+\r
+ *native = specs->value2enum[value].nat_value;\r
+ ASN_DEBUG("Decoded %s = %ld", td->name, *native);\r
+\r
+ return rval;\r
+}\r
+\r
+static int\r
+NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {\r
+ const asn_INTEGER_enum_map_t *a = ap;\r
+ const asn_INTEGER_enum_map_t *b = bp;\r
+ if(a->nat_value == b->nat_value)\r
+ return 0;\r
+ if(a->nat_value < b->nat_value)\r
+ return -1;\r
+ return 1;\r
+}\r
+\r
+asn_enc_rval_t\r
+NativeEnumerated_encode_uper(const asn_TYPE_descriptor_t *td,\r
+ const asn_per_constraints_t *constraints,\r
+ const void *sptr, asn_per_outp_t *po) {\r
+ const asn_INTEGER_specifics_t *specs =\r
+ (const asn_INTEGER_specifics_t *)td->specifics;\r
+ asn_enc_rval_t er = {0,0,0};\r
+ long native, value;\r
+ const asn_per_constraint_t *ct;\r
+ int inext = 0;\r
+ asn_INTEGER_enum_map_t key;\r
+ const asn_INTEGER_enum_map_t *kf;\r
+\r
+ if(!sptr) ASN__ENCODE_FAILED;\r
+ if(!specs) ASN__ENCODE_FAILED;\r
+\r
+ if(constraints) ct = &constraints->value;\r
+ else if(td->encoding_constraints.per_constraints)\r
+ ct = &td->encoding_constraints.per_constraints->value;\r
+ else ASN__ENCODE_FAILED; /* Mandatory! */\r
+\r
+ ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);\r
+\r
+ er.encoded = 0;\r
+\r
+ native = *(const long *)sptr;\r
+\r
+ key.nat_value = native;\r
+ kf = bsearch(&key, specs->value2enum, specs->map_count,\r
+ sizeof(key), NativeEnumerated__compar_value2enum);\r
+ if(!kf) {\r
+ ASN_DEBUG("No element corresponds to %ld", native);\r
+ ASN__ENCODE_FAILED;\r
+ }\r
+ value = kf - specs->value2enum;\r
+\r
+ if(ct->range_bits >= 0) {\r
+ int cmpWith = specs->extension\r
+ ? specs->extension - 1 : specs->map_count;\r
+ if(value >= cmpWith)\r
+ inext = 1;\r
+ }\r
+ if(ct->flags & APC_EXTENSIBLE) {\r
+ if(per_put_few_bits(po, inext, 1))\r
+ ASN__ENCODE_FAILED;\r
+ if(inext) ct = 0;\r
+ } else if(inext) {\r
+ ASN__ENCODE_FAILED;\r
+ }\r
+\r
+ if(ct && ct->range_bits >= 0) {\r
+ if(per_put_few_bits(po, value, ct->range_bits))\r
+ ASN__ENCODE_FAILED;\r
+ ASN__ENCODED_OK(er);\r
+ }\r
+\r
+ if(!specs->extension)\r
+ ASN__ENCODE_FAILED;\r
+\r
+ /*\r
+ * X.691, #10.6: normally small non-negative whole number;\r
+ */\r
+ ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",\r
+ value, specs->extension, inext,\r
+ value - (inext ? (specs->extension - 1) : 0));\r
+ if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))\r
+ ASN__ENCODE_FAILED;\r
+\r
+ ASN__ENCODED_OK(er);\r
+}\r
+\r
+asn_dec_rval_t\r
+NativeEnumerated_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,\r
+ const asn_TYPE_descriptor_t *td,\r
+ const asn_per_constraints_t *constraints,\r
+ void **sptr, asn_per_data_t *pd) {\r
+ const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;\r
+ asn_dec_rval_t rval = { RC_OK, 0 };\r
+ long *native = (long *)*sptr;\r
+ const asn_per_constraint_t *ct;\r
+ long value;\r
+\r
+ (void)opt_codec_ctx;\r
+\r
+ if(constraints) ct = &constraints->value;\r
+ else if(td->encoding_constraints.per_constraints)\r
+ ct = &td->encoding_constraints.per_constraints->value;\r
+ else ASN__DECODE_FAILED; /* Mandatory! */\r
+ if(!specs) ASN__DECODE_FAILED;\r
+\r
+ if(!native) {\r
+ native = (long *)(*sptr = CALLOC(1, sizeof(*native)));\r
+ if(!native) ASN__DECODE_FAILED;\r
+ }\r
+\r
+ ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);\r
+\r
+ if(ct->flags & APC_EXTENSIBLE) {\r
+ int inext = per_get_few_bits(pd, 1);\r
+ if(inext < 0) ASN__DECODE_STARVED;\r
+ if(inext) ct = 0;\r
+ }\r
+\r
+ /* Deal with APER padding */\r
+ if(ct && ct->upper_bound >= 255) {\r
+ int padding = 0;\r
+ padding = (8 - (pd->moved % 8)) % 8;\r
+ ASN_DEBUG("For NativeEnumerated %s,offset= %lu Padding bits = %d", td->name, pd->moved, padding);\r
+ ASN_DEBUG("For NativeEnumerated %s, upper bound = %lu", td->name, ct->upper_bound);\r
+ if(padding > 0)\r
+ per_get_few_bits(pd, padding);\r
+ }\r
+\r
+ if(ct && ct->range_bits >= 0) {\r
+ value = per_get_few_bits(pd, ct->range_bits);\r
+ if(value < 0) ASN__DECODE_STARVED;\r
+ if(value >= (specs->extension\r
+ ? specs->extension - 1 : specs->map_count))\r
+ ASN__DECODE_FAILED;\r
+ } else {\r
+ if(!specs->extension)\r
+ ASN__DECODE_FAILED;\r
+ /*\r
+ * X.691, #10.6: normally small non-negative whole number;\r
+ */\r
+ value = uper_get_nsnnwn(pd);\r
+ if(value < 0) ASN__DECODE_STARVED;\r
+ value += specs->extension - 1;\r
+ if(value >= specs->map_count)\r
+ ASN__DECODE_FAILED;\r
+ }\r
+\r
+ *native = specs->value2enum[value].nat_value;\r
+ ASN_DEBUG("Decoded %s = %ld", td->name, *native);\r
+\r
+ return rval;\r
+}\r
+\r
+asn_enc_rval_t\r
+NativeEnumerated_encode_aper(const asn_TYPE_descriptor_t *td,\r
+ const asn_per_constraints_t *constraints,\r
+ const void *sptr, asn_per_outp_t *po) {\r
+ const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;\r
+ asn_enc_rval_t er = {0,0,0};\r
+ long native, value;\r
+ const asn_per_constraint_t *ct;\r
+ int inext = 0;\r
+ asn_INTEGER_enum_map_t key;\r
+ asn_INTEGER_enum_map_t *kf;\r
+\r
+ if(!sptr) ASN__ENCODE_FAILED;\r
+ if(!specs) ASN__ENCODE_FAILED;\r
+\r
+ if(constraints) ct = &constraints->value;\r
+ else if(td->encoding_constraints.per_constraints)\r
+ ct = &td->encoding_constraints.per_constraints->value;\r
+ else ASN__ENCODE_FAILED; /* Mandatory! */\r
+\r
+ ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);\r
+\r
+ er.encoded = 0;\r
+\r
+ native = *(const long *)sptr;\r
+ if(native < 0) ASN__ENCODE_FAILED;\r
+\r
+ key.nat_value = native;\r
+ kf = bsearch(&key, specs->value2enum, specs->map_count,\r
+ sizeof(key), NativeEnumerated__compar_value2enum);\r
+ if(!kf) {\r
+ ASN_DEBUG("No element corresponds to %ld", native);\r
+ ASN__ENCODE_FAILED;\r
+ }\r
+ value = kf - specs->value2enum;\r
+\r
+ if(ct->range_bits >= 0) {\r
+ int cmpWith = specs->extension\r
+ ? specs->extension - 1 : specs->map_count;\r
+ if(value >= cmpWith)\r
+ inext = 1;\r
+ }\r
+ if(ct->flags & APC_EXTENSIBLE) {\r
+ if(per_put_few_bits(po, inext, 1))\r
+ ASN__ENCODE_FAILED;\r
+ if(inext) ct = 0;\r
+ } else if(inext) {\r
+ ASN__ENCODE_FAILED;\r
+ }\r
+\r
+ if(ct && ct->range_bits >= 0) {\r
+ if(per_put_few_bits(po, value, ct->range_bits))\r
+ ASN__ENCODE_FAILED;\r
+ ASN__ENCODED_OK(er);\r
+ }\r
+\r
+ if(!specs->extension)\r
+ ASN__ENCODE_FAILED;\r
+\r
+ /*\r
+ * X.691, #10.6: normally small non-negative whole number;\r
+ */\r
+ ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",\r
+ value, specs->extension, inext,\r
+ value - (inext ? (specs->extension - 1) : 0));\r
+ if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))\r
+ ASN__ENCODE_FAILED;\r
+\r
+ ASN__ENCODED_OK(er);\r
+}\r