Adding initial code jy.oak@samsung.com
[ric-app/kpimon.git] / asn1c_defs / all-defs / INTEGER.c
diff --git a/asn1c_defs/all-defs/INTEGER.c b/asn1c_defs/all-defs/INTEGER.c
new file mode 100755 (executable)
index 0000000..1cefce4
--- /dev/null
@@ -0,0 +1,1735 @@
+/*-\r
+ * Copyright (c) 2003-2014 Lev Walkin <vlm@lionet.info>.\r
+ * All rights reserved.\r
+ * Redistribution and modifications are permitted subject to BSD license.\r
+ */\r
+#include <asn_internal.h>\r
+#include <INTEGER.h>\r
+#include <asn_codecs_prim.h>   /* Encoder and decoder of a primitive type */\r
+#include <errno.h>\r
+\r
+/*\r
+ * INTEGER basic type description.\r
+ */\r
+static const ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {\r
+       (ASN_TAG_CLASS_UNIVERSAL | (2 << 2))\r
+};\r
+asn_TYPE_operation_t asn_OP_INTEGER = {\r
+       INTEGER_free,\r
+       INTEGER_print,\r
+       INTEGER_compare,\r
+       ber_decode_primitive,\r
+       INTEGER_encode_der,\r
+       INTEGER_decode_xer,\r
+       INTEGER_encode_xer,\r
+#ifdef  ASN_DISABLE_OER_SUPPORT\r
+       0,\r
+       0,\r
+#else\r
+       INTEGER_decode_oer,     /* OER decoder */\r
+       INTEGER_encode_oer,     /* Canonical OER encoder */\r
+#endif  /* ASN_DISABLE_OER_SUPPORT */\r
+#ifdef ASN_DISABLE_PER_SUPPORT\r
+       0,\r
+       0,\r
+       0,\r
+       0,\r
+#else\r
+       INTEGER_decode_uper,    /* Unaligned PER decoder */\r
+       INTEGER_encode_uper,    /* Unaligned PER encoder */\r
+       INTEGER_decode_aper,    /* Aligned PER decoder */\r
+       INTEGER_encode_aper,    /* Aligned PER encoder */\r
+#endif /* ASN_DISABLE_PER_SUPPORT */\r
+       INTEGER_random_fill,\r
+       0       /* Use generic outmost tag fetcher */\r
+};\r
+asn_TYPE_descriptor_t asn_DEF_INTEGER = {\r
+       "INTEGER",\r
+       "INTEGER",\r
+       &asn_OP_INTEGER,\r
+       asn_DEF_INTEGER_tags,\r
+       sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),\r
+       asn_DEF_INTEGER_tags,   /* Same as above */\r
+       sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),\r
+       { 0, 0, asn_generic_no_constraint },\r
+       0, 0,   /* No members */\r
+       0       /* No specifics */\r
+};\r
+\r
+/*\r
+ * Encode INTEGER type using DER.\r
+ */\r
+asn_enc_rval_t\r
+INTEGER_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,\r
+                   int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb,\r
+                   void *app_key) {\r
+    const INTEGER_t *st = (const INTEGER_t *)sptr;\r
+    asn_enc_rval_t rval;\r
+    INTEGER_t effective_integer;\r
+\r
+       ASN_DEBUG("%s %s as INTEGER (tm=%d)",\r
+               cb?"Encoding":"Estimating", td->name, tag_mode);\r
+\r
+       /*\r
+        * Canonicalize integer in the buffer.\r
+        * (Remove too long sign extension, remove some first 0x00 bytes)\r
+        */\r
+       if(st->buf) {\r
+               uint8_t *buf = st->buf;\r
+               uint8_t *end1 = buf + st->size - 1;\r
+               int shift;\r
+\r
+               /* Compute the number of superfluous leading bytes */\r
+               for(; buf < end1; buf++) {\r
+                       /*\r
+                        * If the contents octets of an integer value encoding\r
+                        * consist of more than one octet, then the bits of the\r
+                        * first octet and bit 8 of the second octet:\r
+                        * a) shall not all be ones; and\r
+                        * b) shall not all be zero.\r
+                        */\r
+                       switch(*buf) {\r
+                       case 0x00: if((buf[1] & 0x80) == 0)\r
+                                       continue;\r
+                               break;\r
+                       case 0xff: if((buf[1] & 0x80))\r
+                                       continue;\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+\r
+               /* Remove leading superfluous bytes from the integer */\r
+               shift = buf - st->buf;\r
+               if(shift) {\r
+            union {\r
+                const uint8_t *c_buf;\r
+                uint8_t *nc_buf;\r
+            } unconst;\r
+            unconst.c_buf = st->buf;\r
+            effective_integer.buf = unconst.nc_buf + shift;\r
+            effective_integer.size = st->size - shift;\r
+\r
+            st = &effective_integer;\r
+        }\r
+    }\r
+\r
+    rval = der_encode_primitive(td, st, tag_mode, tag, cb, app_key);\r
+    if(rval.structure_ptr == &effective_integer) {\r
+        rval.structure_ptr = sptr;\r
+    }\r
+    return rval;\r
+}\r
+\r
+static const asn_INTEGER_enum_map_t *INTEGER_map_enum2value(\r
+    const asn_INTEGER_specifics_t *specs, const char *lstart,\r
+    const char *lstop);\r
+\r
+/*\r
+ * INTEGER specific human-readable output.\r
+ */\r
+static ssize_t\r
+INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {\r
+    const asn_INTEGER_specifics_t *specs =\r
+        (const asn_INTEGER_specifics_t *)td->specifics;\r
+       char scratch[32];\r
+       uint8_t *buf = st->buf;\r
+       uint8_t *buf_end = st->buf + st->size;\r
+       intmax_t value;\r
+       ssize_t wrote = 0;\r
+       char *p;\r
+       int ret;\r
+\r
+       if(specs && specs->field_unsigned)\r
+               ret = asn_INTEGER2umax(st, (uintmax_t *)&value);\r
+       else\r
+               ret = asn_INTEGER2imax(st, &value);\r
+\r
+       /* Simple case: the integer size is small */\r
+       if(ret == 0) {\r
+               const asn_INTEGER_enum_map_t *el;\r
+               el = (value >= 0 || !specs || !specs->field_unsigned)\r
+                       ? INTEGER_map_value2enum(specs, value) : 0;\r
+               if(el) {\r
+                       if(plainOrXER == 0)\r
+                               return asn__format_to_callback(cb, app_key,\r
+                                       "%" ASN_PRIdMAX " (%s)", value, el->enum_name);\r
+                       else\r
+                               return asn__format_to_callback(cb, app_key,\r
+                                       "<%s/>", el->enum_name);\r
+               } else if(plainOrXER && specs && specs->strict_enumeration) {\r
+                       ASN_DEBUG("ASN.1 forbids dealing with "\r
+                               "unknown value of ENUMERATED type");\r
+                       errno = EPERM;\r
+                       return -1;\r
+               } else {\r
+            return asn__format_to_callback(cb, app_key,\r
+                                           (specs && specs->field_unsigned)\r
+                                               ? "%" ASN_PRIuMAX\r
+                                               : "%" ASN_PRIdMAX,\r
+                                           value);\r
+        }\r
+       } else if(plainOrXER && specs && specs->strict_enumeration) {\r
+               /*\r
+                * Here and earlier, we cannot encode the ENUMERATED values\r
+                * if there is no corresponding identifier.\r
+                */\r
+               ASN_DEBUG("ASN.1 forbids dealing with "\r
+                       "unknown value of ENUMERATED type");\r
+               errno = EPERM;\r
+               return -1;\r
+       }\r
+\r
+       /* Output in the long xx:yy:zz... format */\r
+       /* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */\r
+       for(p = scratch; buf < buf_end; buf++) {\r
+               const char * const h2c = "0123456789ABCDEF";\r
+               if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {\r
+                       /* Flush buffer */\r
+                       if(cb(scratch, p - scratch, app_key) < 0)\r
+                               return -1;\r
+                       wrote += p - scratch;\r
+                       p = scratch;\r
+               }\r
+               *p++ = h2c[*buf >> 4];\r
+               *p++ = h2c[*buf & 0x0F];\r
+               *p++ = 0x3a;    /* ":" */\r
+       }\r
+       if(p != scratch)\r
+               p--;    /* Remove the last ":" */\r
+\r
+       wrote += p - scratch;\r
+       return (cb(scratch, p - scratch, app_key) < 0) ? -1 : wrote;\r
+}\r
+\r
+/*\r
+ * INTEGER specific human-readable output.\r
+ */\r
+int\r
+INTEGER_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,\r
+              asn_app_consume_bytes_f *cb, void *app_key) {\r
+    const INTEGER_t *st = (const INTEGER_t *)sptr;\r
+       ssize_t ret;\r
+\r
+       (void)ilevel;\r
+\r
+       if(!st || !st->buf)\r
+               ret = cb("<absent>", 8, app_key);\r
+       else\r
+               ret = INTEGER__dump(td, st, cb, app_key, 0);\r
+\r
+       return (ret < 0) ? -1 : 0;\r
+}\r
+\r
+struct e2v_key {\r
+       const char *start;\r
+       const char *stop;\r
+       const asn_INTEGER_enum_map_t *vemap;\r
+       const unsigned int *evmap;\r
+};\r
+static int\r
+INTEGER__compar_enum2value(const void *kp, const void *am) {\r
+       const struct e2v_key *key = (const struct e2v_key *)kp;\r
+       const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;\r
+       const char *ptr, *end, *name;\r
+\r
+       /* Remap the element (sort by different criterion) */\r
+       el = key->vemap + key->evmap[el - key->vemap];\r
+\r
+       /* Compare strings */\r
+       for(ptr = key->start, end = key->stop, name = el->enum_name;\r
+                       ptr < end; ptr++, name++) {\r
+               if(*ptr != *name || !*name)\r
+                       return *(const unsigned char *)ptr\r
+                               - *(const unsigned char *)name;\r
+       }\r
+       return name[0] ? -1 : 0;\r
+}\r
+\r
+static const asn_INTEGER_enum_map_t *\r
+INTEGER_map_enum2value(const asn_INTEGER_specifics_t *specs, const char *lstart,\r
+                       const char *lstop) {\r
+    const asn_INTEGER_enum_map_t *el_found;\r
+       int count = specs ? specs->map_count : 0;\r
+       struct e2v_key key;\r
+       const char *lp;\r
+\r
+       if(!count) return NULL;\r
+\r
+       /* Guaranteed: assert(lstart < lstop); */\r
+       /* Figure out the tag name */\r
+       for(lstart++, lp = lstart; lp < lstop; lp++) {\r
+               switch(*lp) {\r
+               case 9: case 10: case 11: case 12: case 13: case 32: /* WSP */\r
+               case 0x2f: /* '/' */ case 0x3e: /* '>' */\r
+                       break;\r
+               default:\r
+                       continue;\r
+               }\r
+               break;\r
+       }\r
+       if(lp == lstop) return NULL;    /* No tag found */\r
+       lstop = lp;\r
+\r
+       key.start = lstart;\r
+       key.stop = lstop;\r
+       key.vemap = specs->value2enum;\r
+       key.evmap = specs->enum2value;\r
+       el_found = (asn_INTEGER_enum_map_t *)bsearch(&key,\r
+               specs->value2enum, count, sizeof(specs->value2enum[0]),\r
+               INTEGER__compar_enum2value);\r
+       if(el_found) {\r
+               /* Remap enum2value into value2enum */\r
+               el_found = key.vemap + key.evmap[el_found - key.vemap];\r
+       }\r
+       return el_found;\r
+}\r
+\r
+static int\r
+INTEGER__compar_value2enum(const void *kp, const void *am) {\r
+       long a = *(const long *)kp;\r
+       const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;\r
+       long b = el->nat_value;\r
+       if(a < b) return -1;\r
+       else if(a == b) return 0;\r
+       else return 1;\r
+}\r
+\r
+const asn_INTEGER_enum_map_t *\r
+INTEGER_map_value2enum(const asn_INTEGER_specifics_t *specs, long value) {\r
+       int count = specs ? specs->map_count : 0;\r
+       if(!count) return 0;\r
+       return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum,\r
+               count, sizeof(specs->value2enum[0]),\r
+               INTEGER__compar_value2enum);\r
+}\r
+\r
+static int\r
+INTEGER_st_prealloc(INTEGER_t *st, int min_size) {\r
+       void *p = MALLOC(min_size + 1);\r
+       if(p) {\r
+               void *b = st->buf;\r
+               st->size = 0;\r
+               st->buf = p;\r
+               FREEMEM(b);\r
+               return 0;\r
+       } else {\r
+               return -1;\r
+       }\r
+}\r
+\r
+/*\r
+ * Decode the chunk of XML text encoding INTEGER.\r
+ */\r
+static enum xer_pbd_rval\r
+INTEGER__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,\r
+                         const void *chunk_buf, size_t chunk_size) {\r
+    const asn_INTEGER_specifics_t *specs =\r
+        (const asn_INTEGER_specifics_t *)td->specifics;\r
+    INTEGER_t *st = (INTEGER_t *)sptr;\r
+       intmax_t dec_value;\r
+       intmax_t hex_value = 0;\r
+       const char *lp;\r
+       const char *lstart = (const char *)chunk_buf;\r
+       const char *lstop = lstart + chunk_size;\r
+       enum {\r
+               ST_LEADSPACE,\r
+               ST_SKIPSPHEX,\r
+               ST_WAITDIGITS,\r
+               ST_DIGITS,\r
+               ST_DIGITS_TRAILSPACE,\r
+               ST_HEXDIGIT1,\r
+               ST_HEXDIGIT2,\r
+               ST_HEXDIGITS_TRAILSPACE,\r
+               ST_HEXCOLON,\r
+               ST_END_ENUM,\r
+               ST_UNEXPECTED\r
+       } state = ST_LEADSPACE;\r
+       const char *dec_value_start = 0; /* INVARIANT: always !0 in ST_DIGITS */\r
+       const char *dec_value_end = 0;\r
+\r
+       if(chunk_size)\r
+               ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x",\r
+                       (long)chunk_size, *lstart, lstop[-1]);\r
+\r
+       if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))\r
+               return XPBD_SYSTEM_FAILURE;\r
+\r
+       /*\r
+        * We may have received a tag here. It will be processed inline.\r
+        * Use strtoul()-like code and serialize the result.\r
+        */\r
+       for(lp = lstart; lp < lstop; lp++) {\r
+               int lv = *lp;\r
+               switch(lv) {\r
+               case 0x09: case 0x0a: case 0x0d: case 0x20:\r
+                       switch(state) {\r
+                       case ST_LEADSPACE:\r
+                       case ST_DIGITS_TRAILSPACE:\r
+                       case ST_HEXDIGITS_TRAILSPACE:\r
+                       case ST_SKIPSPHEX:\r
+                               continue;\r
+                       case ST_DIGITS:\r
+                               dec_value_end = lp;\r
+                               state = ST_DIGITS_TRAILSPACE;\r
+                               continue;\r
+                       case ST_HEXCOLON:\r
+                               state = ST_HEXDIGITS_TRAILSPACE;\r
+                               continue;\r
+                       default:\r
+                               break;\r
+                       }\r
+                       break;\r
+               case 0x2d:      /* '-' */\r
+                       if(state == ST_LEADSPACE) {\r
+                               dec_value = 0;\r
+                               dec_value_start = lp;\r
+                               state = ST_WAITDIGITS;\r
+                               continue;\r
+                       }\r
+                       break;\r
+               case 0x2b:      /* '+' */\r
+                       if(state == ST_LEADSPACE) {\r
+                               dec_value = 0;\r
+                               dec_value_start = lp;\r
+                               state = ST_WAITDIGITS;\r
+                               continue;\r
+                       }\r
+                       break;\r
+               case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:\r
+               case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:\r
+                       switch(state) {\r
+                       case ST_DIGITS: continue;\r
+                       case ST_SKIPSPHEX:      /* Fall through */\r
+                       case ST_HEXDIGIT1:\r
+                               hex_value = (lv - 0x30) << 4;\r
+                               state = ST_HEXDIGIT2;\r
+                               continue;\r
+                       case ST_HEXDIGIT2:\r
+                               hex_value += (lv - 0x30);\r
+                               state = ST_HEXCOLON;\r
+                               st->buf[st->size++] = (uint8_t)hex_value;\r
+                               continue;\r
+                       case ST_HEXCOLON:\r
+                               return XPBD_BROKEN_ENCODING;\r
+                       case ST_LEADSPACE:\r
+                               dec_value = 0;\r
+                               dec_value_start = lp;\r
+                               /* FALL THROUGH */\r
+                       case ST_WAITDIGITS:\r
+                               state = ST_DIGITS;\r
+                               continue;\r
+                       default:\r
+                               break;\r
+                       }\r
+                       break;\r
+               case 0x3c:      /* '<', start of XML encoded enumeration */\r
+                       if(state == ST_LEADSPACE) {\r
+                               const asn_INTEGER_enum_map_t *el;\r
+                               el = INTEGER_map_enum2value(\r
+                                       (const asn_INTEGER_specifics_t *)\r
+                                       td->specifics, lstart, lstop);\r
+                               if(el) {\r
+                                       ASN_DEBUG("Found \"%s\" => %ld",\r
+                                               el->enum_name, el->nat_value);\r
+                                       dec_value = el->nat_value;\r
+                                       state = ST_END_ENUM;\r
+                                       lp = lstop - 1;\r
+                                       continue;\r
+                               }\r
+                               ASN_DEBUG("Unknown identifier for INTEGER");\r
+                       }\r
+                       return XPBD_BROKEN_ENCODING;\r
+               case 0x3a:      /* ':' */\r
+                       if(state == ST_HEXCOLON) {\r
+                               /* This colon is expected */\r
+                               state = ST_HEXDIGIT1;\r
+                               continue;\r
+                       } else if(state == ST_DIGITS) {\r
+                               /* The colon here means that we have\r
+                                * decoded the first two hexadecimal\r
+                                * places as a decimal value.\r
+                                * Switch decoding mode. */\r
+                               ASN_DEBUG("INTEGER re-evaluate as hex form");\r
+                               state = ST_SKIPSPHEX;\r
+                               dec_value_start = 0;\r
+                               lp = lstart - 1;\r
+                               continue;\r
+                       } else {\r
+                               ASN_DEBUG("state %d at %ld", state, (long)(lp - lstart));\r
+                               break;\r
+                       }\r
+               /* [A-Fa-f] */\r
+               case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:\r
+               case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:\r
+                       switch(state) {\r
+                       case ST_SKIPSPHEX:\r
+                       case ST_LEADSPACE: /* Fall through */\r
+                       case ST_HEXDIGIT1:\r
+                               hex_value = lv - ((lv < 0x61) ? 0x41 : 0x61);\r
+                               hex_value += 10;\r
+                               hex_value <<= 4;\r
+                               state = ST_HEXDIGIT2;\r
+                               continue;\r
+                       case ST_HEXDIGIT2:\r
+                               hex_value += lv - ((lv < 0x61) ? 0x41 : 0x61);\r
+                               hex_value += 10;\r
+                               st->buf[st->size++] = (uint8_t)hex_value;\r
+                               state = ST_HEXCOLON;\r
+                               continue;\r
+                       case ST_DIGITS:\r
+                               ASN_DEBUG("INTEGER re-evaluate as hex form");\r
+                               state = ST_SKIPSPHEX;\r
+                               dec_value_start = 0;\r
+                               lp = lstart - 1;\r
+                               continue;\r
+                       default:\r
+                               break;\r
+                       }\r
+                       break;\r
+               }\r
+\r
+               /* Found extra non-numeric stuff */\r
+               ASN_DEBUG("INTEGER :: Found non-numeric 0x%2x at %ld",\r
+                       lv, (long)(lp - lstart));\r
+               state = ST_UNEXPECTED;\r
+               break;\r
+       }\r
+\r
+       switch(state) {\r
+       case ST_END_ENUM:\r
+               /* Got a complete and valid enumeration encoded as a tag. */\r
+               break;\r
+       case ST_DIGITS:\r
+               dec_value_end = lstop;\r
+               /* FALL THROUGH */\r
+       case ST_DIGITS_TRAILSPACE:\r
+               /* The last symbol encountered was a digit. */\r
+        switch(asn_strtoimax_lim(dec_value_start, &dec_value_end, &dec_value)) {\r
+        case ASN_STRTOX_OK:\r
+            if(specs && specs->field_unsigned && (uintmax_t) dec_value <= ULONG_MAX) {\r
+                break;\r
+            } else if(dec_value >= LONG_MIN && dec_value <= LONG_MAX) {\r
+                break;\r
+            } else {\r
+                /*\r
+                 * We model INTEGER on long for XER,\r
+                 * to avoid rewriting all the tests at once.\r
+                 */\r
+                ASN_DEBUG("INTEGER exceeds long range");\r
+            }\r
+            /* Fall through */\r
+        case ASN_STRTOX_ERROR_RANGE:\r
+            ASN_DEBUG("INTEGER decode %s hit range limit", td->name);\r
+            return XPBD_DECODER_LIMIT;\r
+               case ASN_STRTOX_ERROR_INVAL:\r
+               case ASN_STRTOX_EXPECT_MORE:\r
+               case ASN_STRTOX_EXTRA_DATA:\r
+                       return XPBD_BROKEN_ENCODING;\r
+               }\r
+               break;\r
+       case ST_HEXCOLON:\r
+       case ST_HEXDIGITS_TRAILSPACE:\r
+               st->buf[st->size] = 0;  /* Just in case termination */\r
+               return XPBD_BODY_CONSUMED;\r
+       case ST_HEXDIGIT1:\r
+       case ST_HEXDIGIT2:\r
+       case ST_SKIPSPHEX:\r
+               return XPBD_BROKEN_ENCODING;\r
+       case ST_LEADSPACE:\r
+               /* Content not found */\r
+               return XPBD_NOT_BODY_IGNORE;\r
+       case ST_WAITDIGITS:\r
+       case ST_UNEXPECTED:\r
+               ASN_DEBUG("INTEGER: No useful digits (state %d)", state);\r
+               return XPBD_BROKEN_ENCODING;    /* No digits */\r
+       }\r
+\r
+       /*\r
+        * Convert the result of parsing of enumeration or a straight\r
+        * decimal value into a BER representation.\r
+        */\r
+       if(asn_imax2INTEGER(st, dec_value)) {\r
+                ASN_DEBUG("INTEGER decode %s conversion failed", td->name);\r
+               return XPBD_SYSTEM_FAILURE;\r
+        }\r
+\r
+       return XPBD_BODY_CONSUMED;\r
+}\r
+\r
+asn_dec_rval_t\r
+INTEGER_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,\r
+                   const asn_TYPE_descriptor_t *td, void **sptr,\r
+                   const char *opt_mname, const void *buf_ptr, size_t size) {\r
+    return xer_decode_primitive(opt_codec_ctx, td,\r
+               sptr, sizeof(INTEGER_t), opt_mname,\r
+               buf_ptr, size, INTEGER__xer_body_decode);\r
+}\r
+\r
+asn_enc_rval_t\r
+INTEGER_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 INTEGER_t *st = (const INTEGER_t *)sptr;\r
+       asn_enc_rval_t er = {0,0,0};\r
+\r
+       (void)ilevel;\r
+       (void)flags;\r
+       \r
+       if(!st || !st->buf)\r
+               ASN__ENCODE_FAILED;\r
+\r
+       er.encoded = INTEGER__dump(td, st, cb, app_key, 1);\r
+       if(er.encoded < 0) ASN__ENCODE_FAILED;\r
+\r
+       ASN__ENCODED_OK(er);\r
+}\r
+\r
+#ifndef        ASN_DISABLE_PER_SUPPORT\r
+\r
+asn_dec_rval_t\r
+INTEGER_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,\r
+                    const asn_TYPE_descriptor_t *td,\r
+                    const asn_per_constraints_t *constraints, void **sptr,\r
+                    asn_per_data_t *pd) {\r
+    const asn_INTEGER_specifics_t *specs =\r
+        (const asn_INTEGER_specifics_t *)td->specifics;\r
+    asn_dec_rval_t rval = { RC_OK, 0 };\r
+       INTEGER_t *st = (INTEGER_t *)*sptr;\r
+       const asn_per_constraint_t *ct;\r
+       int repeat;\r
+\r
+       (void)opt_codec_ctx;\r
+\r
+       if(!st) {\r
+               st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));\r
+               if(!st) ASN__DECODE_FAILED;\r
+       }\r
+\r
+       if(!constraints) constraints = td->encoding_constraints.per_constraints;\r
+       ct = constraints ? &constraints->value : 0;\r
+\r
+       if(ct && 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
+       FREEMEM(st->buf);\r
+       st->buf = 0;\r
+       st->size = 0;\r
+       if(ct) {\r
+               if(ct->flags & APC_SEMI_CONSTRAINED) {\r
+                       st->buf = (uint8_t *)CALLOC(1, 2);\r
+                       if(!st->buf) ASN__DECODE_FAILED;\r
+                       st->size = 1;\r
+               } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {\r
+                       size_t size = (ct->range_bits + 7) >> 3;\r
+                       st->buf = (uint8_t *)MALLOC(1 + size + 1);\r
+                       if(!st->buf) ASN__DECODE_FAILED;\r
+                       st->size = size;\r
+               }\r
+       }\r
+\r
+       /* X.691-2008/11, #13.2.2, constrained whole number */\r
+       if(ct && ct->flags != APC_UNCONSTRAINED) {\r
+               /* #11.5.6 */\r
+               ASN_DEBUG("Integer with range %d bits", ct->range_bits);\r
+               if(ct->range_bits >= 0) {\r
+                       if((size_t)ct->range_bits > 8 * sizeof(unsigned long))\r
+                               ASN__DECODE_FAILED;\r
+\r
+                       if(specs && specs->field_unsigned) {\r
+                               unsigned long uvalue = 0;\r
+                               if(uper_get_constrained_whole_number(pd,\r
+                                       &uvalue, ct->range_bits))\r
+                                       ASN__DECODE_STARVED;\r
+                               ASN_DEBUG("Got value %lu + low %ld",\r
+                                       uvalue, ct->lower_bound);\r
+                               uvalue += ct->lower_bound;\r
+                               if(asn_ulong2INTEGER(st, uvalue))\r
+                                       ASN__DECODE_FAILED;\r
+                       } else {\r
+                               unsigned long uvalue = 0;\r
+                               long svalue;\r
+                               if(uper_get_constrained_whole_number(pd,\r
+                                       &uvalue, ct->range_bits))\r
+                                       ASN__DECODE_STARVED;\r
+                               ASN_DEBUG("Got value %lu + low %ld",\r
+                                       uvalue, ct->lower_bound);\r
+                if(per_long_range_unrebase(uvalue, ct->lower_bound,\r
+                                           ct->upper_bound, &svalue)\r
+                   || asn_long2INTEGER(st, svalue)) {\r
+                    ASN__DECODE_FAILED;\r
+                }\r
+                       }\r
+                       return rval;\r
+               }\r
+       } else {\r
+               ASN_DEBUG("Decoding unconstrained integer %s", td->name);\r
+       }\r
+\r
+       /* X.691, #12.2.3, #12.2.4 */\r
+       do {\r
+               ssize_t len = 0;\r
+               void *p = NULL;\r
+               int ret = 0;\r
+\r
+               /* Get the PER length */\r
+               len = uper_get_length(pd, -1, 0, &repeat);\r
+               if(len < 0) ASN__DECODE_STARVED;\r
+\r
+               p = REALLOC(st->buf, st->size + len + 1);\r
+               if(!p) ASN__DECODE_FAILED;\r
+               st->buf = (uint8_t *)p;\r
+\r
+               ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);\r
+               if(ret < 0) ASN__DECODE_STARVED;\r
+               st->size += len;\r
+       } while(repeat);\r
+       st->buf[st->size] = 0;  /* JIC */\r
+\r
+       /* #12.2.3 */\r
+       if(ct && ct->lower_bound) {\r
+               /*\r
+                * TODO: replace by in-place arithmetics.\r
+                */\r
+               long value = 0;\r
+               if(asn_INTEGER2long(st, &value))\r
+                       ASN__DECODE_FAILED;\r
+               if(asn_imax2INTEGER(st, value + ct->lower_bound))\r
+                       ASN__DECODE_FAILED;\r
+       }\r
+\r
+       return rval;\r
+}\r
+\r
+asn_enc_rval_t\r
+INTEGER_encode_uper(const asn_TYPE_descriptor_t *td,\r
+                    const asn_per_constraints_t *constraints, const void *sptr,\r
+                    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
+       const INTEGER_t *st = (const INTEGER_t *)sptr;\r
+       const uint8_t *buf;\r
+       const uint8_t *end;\r
+       const asn_per_constraint_t *ct;\r
+       long value = 0;\r
+\r
+       if(!st || st->size == 0) ASN__ENCODE_FAILED;\r
+\r
+       if(!constraints) constraints = td->encoding_constraints.per_constraints;\r
+       ct = constraints ? &constraints->value : 0;\r
+\r
+       er.encoded = 0;\r
+\r
+       if(ct) {\r
+               int inext = 0;\r
+               if(specs && specs->field_unsigned) {\r
+                       unsigned long uval;\r
+                       if(asn_INTEGER2ulong(st, &uval))\r
+                               ASN__ENCODE_FAILED;\r
+                       /* Check proper range */\r
+                       if(ct->flags & APC_SEMI_CONSTRAINED) {\r
+                               if(uval < (unsigned long)ct->lower_bound)\r
+                                       inext = 1;\r
+                       } else if(ct->range_bits >= 0) {\r
+                               if(uval < (unsigned long)ct->lower_bound\r
+                               || uval > (unsigned long)ct->upper_bound)\r
+                                       inext = 1;\r
+                       }\r
+                       ASN_DEBUG("Value %lu (%02x/%" ASN_PRI_SIZE ") lb %lu ub %lu %s",\r
+                               uval, st->buf[0], st->size,\r
+                               ct->lower_bound, ct->upper_bound,\r
+                               inext ? "ext" : "fix");\r
+                       value = uval;\r
+               } else {\r
+                       if(asn_INTEGER2long(st, &value))\r
+                               ASN__ENCODE_FAILED;\r
+                       /* Check proper range */\r
+                       if(ct->flags & APC_SEMI_CONSTRAINED) {\r
+                               if(value < ct->lower_bound)\r
+                                       inext = 1;\r
+                       } else if(ct->range_bits >= 0) {\r
+                               if(value < ct->lower_bound\r
+                               || value > ct->upper_bound)\r
+                                       inext = 1;\r
+                       }\r
+                       ASN_DEBUG("Value %ld (%02x/%" ASN_PRI_SIZE ") lb %ld ub %ld %s",\r
+                               value, st->buf[0], st->size,\r
+                               ct->lower_bound, ct->upper_bound,\r
+                               inext ? "ext" : "fix");\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
+\r
+\r
+       /* X.691-11/2008, #13.2.2, test if constrained whole number */\r
+       if(ct && ct->range_bits >= 0) {\r
+        unsigned long v;\r
+               /* #11.5.6 -> #11.3 */\r
+               ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",\r
+                       value, value - ct->lower_bound, ct->range_bits);\r
+       if(specs && specs->field_unsigned) {\r
+               if (  ((unsigned long)ct->lower_bound > (unsigned long)(ct->upper_bound)\r
+                  || ((unsigned long)value < (unsigned long)ct->lower_bound))\r
+                  || ((unsigned long)value > (unsigned long)ct->upper_bound)\r
+               ) {\r
+                       ASN_DEBUG("Value %lu to-be-encoded is outside the bounds [%lu, %lu]!",\r
+                               value, ct->lower_bound, ct->upper_bound);\r
+                       ASN__ENCODE_FAILED;\r
+               }\r
+               v = (unsigned long)value - (unsigned long)ct->lower_bound;\r
+       } else {\r
+               if(per_long_range_rebase(value, ct->lower_bound, ct->upper_bound, &v)) {\r
+                       ASN__ENCODE_FAILED;\r
+               }\r
+       }\r
+        if(uper_put_constrained_whole_number_u(po, v, ct->range_bits))\r
+               ASN__ENCODE_FAILED;\r
+       ASN__ENCODED_OK(er);\r
+       }\r
+\r
+       if(ct && ct->lower_bound) {\r
+               ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);\r
+               /* TODO: adjust lower bound */\r
+               ASN__ENCODE_FAILED;\r
+       }\r
+\r
+       for(buf = st->buf, end = st->buf + st->size; buf < end;) {\r
+        int need_eom = 0;\r
+        ssize_t mayEncode = uper_put_length(po, end - buf, &need_eom);\r
+        if(mayEncode < 0)\r
+                       ASN__ENCODE_FAILED;\r
+               if(per_put_many_bits(po, buf, 8 * mayEncode))\r
+                       ASN__ENCODE_FAILED;\r
+               buf += mayEncode;\r
+        if(need_eom && uper_put_length(po, 0, 0)) ASN__ENCODE_FAILED;\r
+    }\r
+\r
+       ASN__ENCODED_OK(er);\r
+}\r
+\r
+asn_dec_rval_t\r
+INTEGER_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,\r
+                    const asn_TYPE_descriptor_t *td,\r
+                    const asn_per_constraints_t *constraints, 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
+       INTEGER_t *st = (INTEGER_t *)*sptr;\r
+       const asn_per_constraint_t *ct;\r
+       int repeat;\r
+\r
+       (void)opt_codec_ctx;\r
+\r
+       if(!st) {\r
+               st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));\r
+               if(!st) ASN__DECODE_FAILED;\r
+       }\r
+\r
+       if(!constraints) constraints = td->encoding_constraints.per_constraints;\r
+       ct = constraints ? &constraints->value : 0;\r
+\r
+       if(ct && 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
+       FREEMEM(st->buf);\r
+       st->buf = 0;\r
+       st->size = 0;\r
+       if(ct) {\r
+               if(ct->flags & APC_SEMI_CONSTRAINED) {\r
+                       st->buf = (uint8_t *)CALLOC(1, 2);\r
+                       if(!st->buf) ASN__DECODE_FAILED;\r
+                       st->size = 1;\r
+               } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {\r
+                       size_t size = (ct->range_bits + 7) >> 3;\r
+                       st->buf = (uint8_t *)MALLOC(1 + size + 1);\r
+                       if(!st->buf) ASN__DECODE_FAILED;\r
+                       st->size = size;\r
+               }\r
+       }\r
+\r
+       /* X.691, #12.2.2 */\r
+       if(ct && ct->flags != APC_UNCONSTRAINED) {\r
+               /* #10.5.6 */\r
+               ASN_DEBUG("Integer with range %d bits", ct->range_bits);\r
+               if(ct->range_bits >= 0) {\r
+                       if (ct->range_bits > 16) {\r
+                               int max_range_bytes = (ct->range_bits >> 3) +\r
+                                                     (((ct->range_bits % 8) > 0) ? 1 : 0);\r
+                               int length = 0, i;\r
+                               long value = 0;\r
+\r
+                               for (i = 1; ; i++) {\r
+                                       int upper = 1 << i;\r
+                                       if (upper >= max_range_bytes)\r
+                                               break;\r
+                               }\r
+                               ASN_DEBUG("Can encode %d (%d bytes) in %d bits", ct->range_bits,\r
+                                         max_range_bytes, i);\r
+\r
+                               if ((length = per_get_few_bits(pd, i)) < 0)\r
+                                       ASN__DECODE_FAILED;\r
+\r
+                               /* X.691 #12.2.6 length determinant + lb (1) */\r
+                               length += 1;\r
+                               ASN_DEBUG("Got length %d", length);\r
+                               if (aper_get_align(pd) != 0)\r
+                                       ASN__DECODE_FAILED;\r
+                               while (length--) {\r
+                                       int buf = per_get_few_bits(pd, 8);\r
+                                       if (buf < 0)\r
+                                               ASN__DECODE_FAILED;\r
+                                       value += (((long)buf) << (8 * length));\r
+                               }\r
+\r
+                               value += ct->lower_bound;\r
+                               if((specs && specs->field_unsigned)\r
+                                       ? asn_uint642INTEGER(st, (unsigned long)value)\r
+                                       : asn_int642INTEGER(st, value))\r
+                                       ASN__DECODE_FAILED;\r
+                               ASN_DEBUG("Got value %ld + low %ld",\r
+                                         value, ct->lower_bound);\r
+                       } else {\r
+                               long value = 0;\r
+                               if (ct->range_bits < 8) {\r
+                                       value = per_get_few_bits(pd, ct->range_bits);\r
+                                       if(value < 0) ASN__DECODE_STARVED;\r
+                               } else if (ct->range_bits == 8) {\r
+                                       if (aper_get_align(pd) < 0)\r
+                                               ASN__DECODE_FAILED;\r
+                                       value = per_get_few_bits(pd, ct->range_bits);\r
+                                       if(value < 0) ASN__DECODE_STARVED;\r
+                               } else {\r
+                                       /* Align */\r
+                                       if (aper_get_align(pd) < 0)\r
+                                               ASN__DECODE_FAILED;\r
+                                       value = per_get_few_bits(pd, 16);\r
+                                       if(value < 0) ASN__DECODE_STARVED;\r
+                               }\r
+                               value += ct->lower_bound;\r
+                               if((specs && specs->field_unsigned)\r
+                                       ? asn_ulong2INTEGER(st, value)\r
+                                       : asn_long2INTEGER(st, value))\r
+                                       ASN__DECODE_FAILED;\r
+                               ASN_DEBUG("Got value %ld + low %ld",\r
+                                         value, ct->lower_bound);\r
+                       }\r
+                       return rval;\r
+               } else {\r
+                       ASN__DECODE_FAILED;\r
+               }\r
+       } else {\r
+               ASN_DEBUG("Decoding unconstrained integer %s", td->name);\r
+       }\r
+\r
+       /* X.691, #12.2.3, #12.2.4 */\r
+       do {\r
+               ssize_t len;\r
+               void *p;\r
+               int ret;\r
+\r
+               /* Get the PER length */\r
+               len = aper_get_length(pd, -1, -1, &repeat);\r
+               if(len < 0) ASN__DECODE_STARVED;\r
+\r
+               p = REALLOC(st->buf, st->size + len + 1);\r
+               if(!p) ASN__DECODE_FAILED;\r
+               st->buf = (uint8_t *)p;\r
+\r
+               ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);\r
+               if(ret < 0) ASN__DECODE_STARVED;\r
+               st->size += len;\r
+       } while(repeat);\r
+       st->buf[st->size] = 0;  /* JIC */\r
+\r
+       /* #12.2.3 */\r
+       if(ct && ct->lower_bound) {\r
+               /*\r
+                * TODO: replace by in-place arithmetics.\r
+                */\r
+               long value;\r
+               if(asn_INTEGER2long(st, &value))\r
+                       ASN__DECODE_FAILED;\r
+               if(asn_long2INTEGER(st, value + ct->lower_bound))\r
+                       ASN__DECODE_FAILED;\r
+       }\r
+\r
+       return rval;\r
+}\r
+\r
+asn_enc_rval_t\r
+INTEGER_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
+       const INTEGER_t *st = (const INTEGER_t *)sptr;\r
+       const uint8_t *buf;\r
+       const uint8_t *end;\r
+       const asn_per_constraint_t *ct;\r
+       long value = 0;\r
+\r
+       if(!st || st->size == 0) ASN__ENCODE_FAILED;\r
+\r
+       if(!constraints) constraints = td->encoding_constraints.per_constraints;\r
+       ct = constraints ? &constraints->value : 0;\r
+\r
+       er.encoded = 0;\r
+\r
+       if(ct) {\r
+               int inext = 0;\r
+               if(specs && specs->field_unsigned) {\r
+                       unsigned long uval;\r
+                       if(asn_INTEGER2ulong(st, &uval))\r
+                               ASN__ENCODE_FAILED;\r
+                       /* Check proper range */\r
+                       if(ct->flags & APC_SEMI_CONSTRAINED) {\r
+                               if(uval < (unsigned long)ct->lower_bound)\r
+                                       inext = 1;\r
+                       } else if(ct->range_bits >= 0) {\r
+                               if(uval < (unsigned long)ct->lower_bound\r
+                                       || uval > (unsigned long)ct->upper_bound)\r
+                                       inext = 1;\r
+                       }\r
+                       ASN_DEBUG("Value %lu (%02x/%lu) lb %ld ub %ld %s",\r
+                                 uval, st->buf[0], st->size,\r
+                                 ct->lower_bound, ct->upper_bound,\r
+                                 inext ? "ext" : "fix");\r
+                       value = uval;\r
+               } else {\r
+                       if(asn_INTEGER2long(st, &value)) ASN__ENCODE_FAILED;\r
+                       /* Check proper range */\r
+                       if(ct->flags & APC_SEMI_CONSTRAINED) {\r
+                               if(value < ct->lower_bound)\r
+                                       inext = 1;\r
+                       } else if(ct->range_bits >= 0) {\r
+                               if(value < ct->lower_bound\r
+                                       || value > ct->upper_bound)\r
+                                       inext = 1;\r
+                       }\r
+                       ASN_DEBUG("Value %lu (%02x/%lu) lb %ld ub %ld %s",\r
+                                 value, st->buf[0], st->size,\r
+                                 ct->lower_bound, ct->upper_bound,\r
+                                 inext ? "ext" : "fix");\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
+\r
+       /* X.691, #12.2.2 */\r
+       if(ct && ct->range_bits >= 0) {\r
+               unsigned long v;\r
+\r
+               /* #10.5.6 */\r
+               ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",\r
+                         value, value - ct->lower_bound, ct->range_bits);\r
+\r
+               v = value - ct->lower_bound;\r
+\r
+               /* #12 <= 8 -> alignment ? */\r
+               if (ct->range_bits < 8) {\r
+                       if(per_put_few_bits(po, 0x00 | v, ct->range_bits))\r
+                               ASN__ENCODE_FAILED;\r
+               } else if (ct->range_bits == 8) {\r
+                       if(aper_put_align(po) < 0)\r
+                               ASN__ENCODE_FAILED;\r
+                       if(per_put_few_bits(po, 0x00 | v, ct->range_bits))\r
+                               ASN__ENCODE_FAILED;\r
+               } else if (ct->range_bits <= 16) {\r
+                       /* Consume the bytes to align on octet */\r
+                       if(aper_put_align(po) < 0)\r
+                               ASN__ENCODE_FAILED;\r
+                       if(per_put_few_bits(po, 0x0000 | v,\r
+                                           16))\r
+                               ASN__ENCODE_FAILED;\r
+               } else {\r
+                       /* TODO: extend to >64 bits */\r
+                       int64_t v64 = v;\r
+                       int i, j;\r
+                       int max_range_bytes = (ct->range_bits >> 3) +\r
+                                             (((ct->range_bits % 8) > 0) ? 1 : 0);\r
+\r
+                       for (i = 1; ; i++) {\r
+                               int upper = 1 << i;\r
+                               if (upper >= max_range_bytes)\r
+                                       break;\r
+                       }\r
+\r
+                       for (j = sizeof(int64_t) -1; j != 0; j--) {\r
+                               int64_t val;\r
+                               val = v64 >> (j * 8);\r
+                               if (val != 0)\r
+                                       break;\r
+                       }\r
+\r
+                       /* Putting length in the minimum number of bits ex: 5 = 3bits */\r
+                       if (per_put_few_bits(po, j, i))\r
+                               ASN__ENCODE_FAILED;\r
+\r
+                       /* Consume the bits to align on octet */\r
+                       if (aper_put_align(po) < 0)\r
+                               ASN__ENCODE_FAILED;\r
+                       /* Put the value */\r
+                       for (i = 0; i <= j; i++) {\r
+                               if(per_put_few_bits(po, (v64 >> (8 * (j - i))) & 0xff, 8))\r
+                                       ASN__ENCODE_FAILED;\r
+                       }\r
+               }\r
+               ASN__ENCODED_OK(er);\r
+       }\r
+\r
+       if(ct && ct->lower_bound) {\r
+               ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);\r
+               /* TODO: adjust lower bound */\r
+               ASN__ENCODE_FAILED;\r
+       }\r
+\r
+       for(buf = st->buf, end = st->buf + st->size; buf < end;) {\r
+               ssize_t mayEncode = aper_put_length(po, -1, end - buf);\r
+               if(mayEncode < 0)\r
+                       ASN__ENCODE_FAILED;\r
+               if(per_put_many_bits(po, buf, 8 * mayEncode))\r
+                       ASN__ENCODE_FAILED;\r
+               buf += mayEncode;\r
+       }\r
+\r
+       ASN__ENCODED_OK(er);\r
+}\r
+\r
+#endif /* ASN_DISABLE_PER_SUPPORT */\r
+\r
+static intmax_t\r
+asn__integer_convert(const uint8_t *b, const uint8_t *end) {\r
+    uintmax_t value;\r
+\r
+    /* Perform the sign initialization */\r
+    /* Actually value = -(*b >> 7); gains nothing, yet unreadable! */\r
+    if((*b >> 7)) {\r
+        value = (uintmax_t)(-1);\r
+    } else {\r
+        value = 0;\r
+    }\r
+\r
+    /* Conversion engine */\r
+    for(; b < end; b++) {\r
+        value = (value << 8) | *b;\r
+    }\r
+\r
+    return value;\r
+}\r
+\r
+int\r
+asn_INTEGER2imax(const INTEGER_t *iptr, intmax_t *lptr) {\r
+       uint8_t *b, *end;\r
+       size_t size;\r
+\r
+       /* Sanity checking */\r
+       if(!iptr || !iptr->buf || !lptr) {\r
+               errno = EINVAL;\r
+               return -1;\r
+       }\r
+\r
+       /* Cache the begin/end of the buffer */\r
+       b = iptr->buf;  /* Start of the INTEGER buffer */\r
+       size = iptr->size;\r
+       end = b + size; /* Where to stop */\r
+\r
+       if(size > sizeof(intmax_t)) {\r
+               uint8_t *end1 = end - 1;\r
+               /*\r
+                * Slightly more advanced processing,\r
+                * able to process INTEGERs with >sizeof(intmax_t) bytes\r
+                * when the actual value is small, e.g. for intmax_t == int32_t\r
+                * (0x0000000000abcdef INTEGER would yield a fine 0x00abcdef int32_t)\r
+                */\r
+               /* Skip out the insignificant leading bytes */\r
+               for(; b < end1; b++) {\r
+                       switch(*b) {\r
+                               case 0x00: if((b[1] & 0x80) == 0) continue; break;\r
+                               case 0xff: if((b[1] & 0x80) != 0) continue; break;\r
+                       }\r
+                       break;\r
+               }\r
+\r
+               size = end - b;\r
+               if(size > sizeof(intmax_t)) {\r
+                       /* Still cannot fit the sizeof(intmax_t) */\r
+                       errno = ERANGE;\r
+                       return -1;\r
+               }\r
+       }\r
+\r
+       /* Shortcut processing of a corner case */\r
+       if(end == b) {\r
+               *lptr = 0;\r
+               return 0;\r
+       }\r
+\r
+       *lptr = asn__integer_convert(b, end);\r
+       return 0;\r
+}\r
+\r
+/* FIXME: negative INTEGER values are silently interpreted as large unsigned ones. */\r
+int\r
+asn_INTEGER2umax(const INTEGER_t *iptr, uintmax_t *lptr) {\r
+       uint8_t *b, *end;\r
+       uintmax_t value;\r
+       size_t size;\r
+\r
+       if(!iptr || !iptr->buf || !lptr) {\r
+               errno = EINVAL;\r
+               return -1;\r
+       }\r
+\r
+       b = iptr->buf;\r
+       size = iptr->size;\r
+       end = b + size;\r
+\r
+       /* If all extra leading bytes are zeroes, ignore them */\r
+       for(; size > sizeof(value); b++, size--) {\r
+               if(*b) {\r
+                       /* Value won't fit into uintmax_t */\r
+                       errno = ERANGE;\r
+                       return -1;\r
+               }\r
+       }\r
+\r
+       /* Conversion engine */\r
+       for(value = 0; b < end; b++)\r
+               value = (value << 8) | *b;\r
+\r
+       *lptr = value;\r
+       return 0;\r
+}\r
+\r
+int\r
+asn_umax2INTEGER(INTEGER_t *st, uintmax_t value) {\r
+    uint8_t *buf;\r
+    uint8_t *end;\r
+    uint8_t *b;\r
+    int shr;\r
+\r
+    if(value <= ((~(uintmax_t)0) >> 1)) {\r
+        return asn_imax2INTEGER(st, value);\r
+    }\r
+\r
+    buf = (uint8_t *)MALLOC(1 + sizeof(value));\r
+    if(!buf) return -1;\r
+\r
+    end = buf + (sizeof(value) + 1);\r
+    buf[0] = 0; /* INTEGERs are signed. 0-byte indicates positive. */\r
+    for(b = buf + 1, shr = (sizeof(value) - 1) * 8; b < end; shr -= 8, b++)\r
+        *b = (uint8_t)(value >> shr);\r
+\r
+    if(st->buf) FREEMEM(st->buf);\r
+    st->buf = buf;\r
+    st->size = 1 + sizeof(value);\r
+\r
+       return 0;\r
+}\r
+\r
+int\r
+asn_imax2INTEGER(INTEGER_t *st, intmax_t value) {\r
+       uint8_t *buf, *bp;\r
+       uint8_t *p;\r
+       uint8_t *pstart;\r
+       uint8_t *pend1;\r
+       int littleEndian = 1;   /* Run-time detection */\r
+       int add;\r
+\r
+       if(!st) {\r
+               errno = EINVAL;\r
+               return -1;\r
+       }\r
+\r
+       buf = (uint8_t *)(long *)MALLOC(sizeof(value));\r
+       if(!buf) return -1;\r
+\r
+       if(*(char *)&littleEndian) {\r
+               pstart = (uint8_t *)&value + sizeof(value) - 1;\r
+               pend1 = (uint8_t *)&value;\r
+               add = -1;\r
+       } else {\r
+               pstart = (uint8_t *)&value;\r
+               pend1 = pstart + sizeof(value) - 1;\r
+               add = 1;\r
+       }\r
+\r
+       /*\r
+        * If the contents octet consists of more than one octet,\r
+        * then bits of the first octet and bit 8 of the second octet:\r
+        * a) shall not all be ones; and\r
+        * b) shall not all be zero.\r
+        */\r
+       for(p = pstart; p != pend1; p += add) {\r
+               switch(*p) {\r
+               case 0x00: if((*(p+add) & 0x80) == 0)\r
+                               continue;\r
+                       break;\r
+               case 0xff: if((*(p+add) & 0x80))\r
+                               continue;\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+       /* Copy the integer body */\r
+       for(bp = buf, pend1 += add; p != pend1; p += add)\r
+               *bp++ = *p;\r
+\r
+       if(st->buf) FREEMEM(st->buf);\r
+       st->buf = buf;\r
+       st->size = bp - buf;\r
+\r
+       return 0;\r
+}\r
+\r
+int\r
+asn_INTEGER2long(const INTEGER_t *iptr, long *l) {\r
+    intmax_t v;\r
+    if(asn_INTEGER2imax(iptr, &v) == 0) {\r
+        if(v < LONG_MIN || v > LONG_MAX) {\r
+            errno = ERANGE;\r
+            return -1;\r
+        }\r
+        *l = v;\r
+        return 0;\r
+    } else {\r
+        return -1;\r
+    }\r
+}\r
+\r
+int\r
+asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *l) {\r
+    uintmax_t v;\r
+    if(asn_INTEGER2umax(iptr, &v) == 0) {\r
+        if(v > ULONG_MAX) {\r
+            errno = ERANGE;\r
+            return -1;\r
+        }\r
+        *l = v;\r
+        return 0;\r
+    } else {\r
+        return -1;\r
+    }\r
+}\r
+\r
+int\r
+asn_long2INTEGER(INTEGER_t *st, long value) {\r
+    return asn_imax2INTEGER(st, value);\r
+}\r
+\r
+int\r
+asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {\r
+    return asn_imax2INTEGER(st, value);\r
+}\r
+\r
+\r
+int\r
+asn_uint642INTEGER(INTEGER_t *st, uint64_t value) {\r
+       uint8_t *buf;\r
+       uint8_t *end;\r
+       uint8_t *b;\r
+       int shr;\r
+\r
+       if(value <= INT64_MAX)\r
+               return asn_int642INTEGER(st, value);\r
+\r
+       buf = (uint8_t *)MALLOC(1 + sizeof(value));\r
+       if(!buf) return -1;\r
+\r
+       end = buf + (sizeof(value) + 1);\r
+       buf[0] = 0;\r
+       for(b = buf + 1, shr = (sizeof(value)-1)*8; b < end; shr -= 8, b++)\r
+               *b = (uint8_t)(value >> shr);\r
+\r
+       if(st->buf) FREEMEM(st->buf);\r
+       st->buf = buf;\r
+       st->size = 1 + sizeof(value);\r
+\r
+       return 0;\r
+}\r
+\r
+int\r
+asn_int642INTEGER(INTEGER_t *st, int64_t value) {\r
+       uint8_t *buf, *bp;\r
+       uint8_t *p;\r
+       uint8_t *pstart;\r
+       uint8_t *pend1;\r
+       int littleEndian = 1;   /* Run-time detection */\r
+       int add;\r
+\r
+       if(!st) {\r
+               errno = EINVAL;\r
+               return -1;\r
+       }\r
+\r
+       buf = (uint8_t *)MALLOC(sizeof(value));\r
+       if(!buf) return -1;\r
+\r
+       if(*(char *)&littleEndian) {\r
+               pstart = (uint8_t *)&value + sizeof(value) - 1;\r
+               pend1 = (uint8_t *)&value;\r
+               add = -1;\r
+       } else {\r
+               pstart = (uint8_t *)&value;\r
+               pend1 = pstart + sizeof(value) - 1;\r
+               add = 1;\r
+       }\r
+\r
+       /*\r
+        * If the contents octet consists of more than one octet,\r
+        * then bits of the first octet and bit 8 of the second octet:\r
+        * a) shall not all be ones; and\r
+        * b) shall not all be zero.\r
+        */\r
+       for(p = pstart; p != pend1; p += add) {\r
+               switch(*p) {\r
+               case 0x00: if((*(p+add) & 0x80) == 0)\r
+                               continue;\r
+                       break;\r
+               case 0xff: if((*(p+add) & 0x80))\r
+                               continue;\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+       /* Copy the integer body */\r
+       for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)\r
+               *bp++ = *p;\r
+\r
+       if(st->buf) FREEMEM(st->buf);\r
+       st->buf = buf;\r
+       st->size = bp - buf;\r
+\r
+       return 0;\r
+}\r
+\r
+/*\r
+ * Parse the number in the given string until the given *end position,\r
+ * returning the position after the last parsed character back using the\r
+ * same (*end) pointer.\r
+ * WARNING: This behavior is different from the standard strtol/strtoimax(3).\r
+ */\r
+enum asn_strtox_result_e\r
+asn_strtoimax_lim(const char *str, const char **end, intmax_t *intp) {\r
+       int sign = 1;\r
+       intmax_t value;\r
+\r
+#define ASN1_INTMAX_MAX ((~(uintmax_t)0) >> 1)\r
+    const intmax_t upper_boundary = ASN1_INTMAX_MAX / 10;\r
+       intmax_t last_digit_max = ASN1_INTMAX_MAX % 10;\r
+#undef  ASN1_INTMAX_MAX\r
+\r
+       if(str >= *end) return ASN_STRTOX_ERROR_INVAL;\r
+\r
+       switch(*str) {\r
+       case '-':\r
+               last_digit_max++;\r
+               sign = -1;\r
+               /* FALL THROUGH */\r
+       case '+':\r
+               str++;\r
+               if(str >= *end) {\r
+                       *end = str;\r
+                       return ASN_STRTOX_EXPECT_MORE;\r
+               }\r
+       }\r
+\r
+       for(value = 0; str < (*end); str++) {\r
+               switch(*str) {\r
+               case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:\r
+               case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: {\r
+                       int d = *str - '0';\r
+                       if(value < upper_boundary) {\r
+                               value = value * 10 + d;\r
+                       } else if(value == upper_boundary) {\r
+                               if(d <= last_digit_max) {\r
+                                       if(sign > 0) {\r
+                                               value = value * 10 + d;\r
+                                       } else {\r
+                                               sign = 1;\r
+                                               value = -value * 10 - d;\r
+                                       }\r
+                               } else {\r
+                                       *end = str;\r
+                                       return ASN_STRTOX_ERROR_RANGE;\r
+                               }\r
+                       } else {\r
+                               *end = str;\r
+                               return ASN_STRTOX_ERROR_RANGE;\r
+                       }\r
+                   }\r
+                   continue;\r
+               default:\r
+                   *end = str;\r
+                   *intp = sign * value;\r
+                   return ASN_STRTOX_EXTRA_DATA;\r
+               }\r
+       }\r
+\r
+       *end = str;\r
+       *intp = sign * value;\r
+       return ASN_STRTOX_OK;\r
+}\r
+\r
+/*\r
+ * Parse the number in the given string until the given *end position,\r
+ * returning the position after the last parsed character back using the\r
+ * same (*end) pointer.\r
+ * WARNING: This behavior is different from the standard strtoul/strtoumax(3).\r
+ */\r
+enum asn_strtox_result_e\r
+asn_strtoumax_lim(const char *str, const char **end, uintmax_t *uintp) {\r
+       uintmax_t value;\r
+\r
+#define ASN1_UINTMAX_MAX ((~(uintmax_t)0))\r
+    const uintmax_t upper_boundary = ASN1_UINTMAX_MAX / 10;\r
+    uintmax_t last_digit_max = ASN1_UINTMAX_MAX % 10;\r
+#undef ASN1_UINTMAX_MAX\r
+\r
+    if(str >= *end) return ASN_STRTOX_ERROR_INVAL;\r
+\r
+       switch(*str) {\r
+       case '-':\r
+        return ASN_STRTOX_ERROR_INVAL;\r
+       case '+':\r
+               str++;\r
+               if(str >= *end) {\r
+                       *end = str;\r
+                       return ASN_STRTOX_EXPECT_MORE;\r
+               }\r
+       }\r
+\r
+       for(value = 0; str < (*end); str++) {\r
+               switch(*str) {\r
+               case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:\r
+               case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: {\r
+                       unsigned int d = *str - '0';\r
+                       if(value < upper_boundary) {\r
+                               value = value * 10 + d;\r
+                       } else if(value == upper_boundary) {\r
+                               if(d <= last_digit_max) {\r
+                    value = value * 10 + d;\r
+                } else {\r
+                                       *end = str;\r
+                                       return ASN_STRTOX_ERROR_RANGE;\r
+                               }\r
+                       } else {\r
+                               *end = str;\r
+                               return ASN_STRTOX_ERROR_RANGE;\r
+                       }\r
+                   }\r
+                   continue;\r
+               default:\r
+                   *end = str;\r
+                   *uintp = value;\r
+                   return ASN_STRTOX_EXTRA_DATA;\r
+               }\r
+       }\r
+\r
+       *end = str;\r
+       *uintp = value;\r
+       return ASN_STRTOX_OK;\r
+}\r
+\r
+enum asn_strtox_result_e\r
+asn_strtol_lim(const char *str, const char **end, long *lp) {\r
+    intmax_t value;\r
+    switch(asn_strtoimax_lim(str, end, &value)) {\r
+    case ASN_STRTOX_ERROR_RANGE:\r
+        return ASN_STRTOX_ERROR_RANGE;\r
+    case ASN_STRTOX_ERROR_INVAL:\r
+        return ASN_STRTOX_ERROR_INVAL;\r
+    case ASN_STRTOX_EXPECT_MORE:\r
+        return ASN_STRTOX_EXPECT_MORE;\r
+    case ASN_STRTOX_OK:\r
+        if(value >= LONG_MIN && value <= LONG_MAX) {\r
+            *lp = value;\r
+            return ASN_STRTOX_OK;\r
+        } else {\r
+            return ASN_STRTOX_ERROR_RANGE;\r
+        }\r
+    case ASN_STRTOX_EXTRA_DATA:\r
+        if(value >= LONG_MIN && value <= LONG_MAX) {\r
+            *lp = value;\r
+            return ASN_STRTOX_EXTRA_DATA;\r
+        } else {\r
+            return ASN_STRTOX_ERROR_RANGE;\r
+        }\r
+    }\r
+\r
+    assert(!"Unreachable");\r
+    return ASN_STRTOX_ERROR_INVAL;\r
+}\r
+\r
+enum asn_strtox_result_e\r
+asn_strtoul_lim(const char *str, const char **end, unsigned long *ulp) {\r
+    uintmax_t value;\r
+    switch(asn_strtoumax_lim(str, end, &value)) {\r
+    case ASN_STRTOX_ERROR_RANGE:\r
+        return ASN_STRTOX_ERROR_RANGE;\r
+    case ASN_STRTOX_ERROR_INVAL:\r
+        return ASN_STRTOX_ERROR_INVAL;\r
+    case ASN_STRTOX_EXPECT_MORE:\r
+        return ASN_STRTOX_EXPECT_MORE;\r
+    case ASN_STRTOX_OK:\r
+        if(value <= ULONG_MAX) {\r
+            *ulp = value;\r
+            return ASN_STRTOX_OK;\r
+        } else {\r
+            return ASN_STRTOX_ERROR_RANGE;\r
+        }\r
+    case ASN_STRTOX_EXTRA_DATA:\r
+        if(value <= ULONG_MAX) {\r
+            *ulp = value;\r
+            return ASN_STRTOX_EXTRA_DATA;\r
+        } else {\r
+            return ASN_STRTOX_ERROR_RANGE;\r
+        }\r
+    }\r
+\r
+    assert(!"Unreachable");\r
+    return ASN_STRTOX_ERROR_INVAL;\r
+}\r
+\r
+int\r
+INTEGER_compare(const asn_TYPE_descriptor_t *td, const void *aptr,\r
+                     const void *bptr) {\r
+    const INTEGER_t *a = aptr;\r
+    const INTEGER_t *b = bptr;\r
+\r
+    (void)td;\r
+\r
+    if(a && b) {\r
+        if(a->size && b->size) {\r
+            int sign_a = (a->buf[0] & 0x80) ? -1 : 1;\r
+            int sign_b = (b->buf[0] & 0x80) ? -1 : 1;\r
+\r
+            if(sign_a < sign_b) return -1;\r
+            if(sign_a > sign_b) return 1;\r
+\r
+            /* The shortest integer wins, unless comparing negatives */\r
+            if(a->size < b->size) {\r
+                return -1 * sign_a;\r
+            } else if(a->size > b->size) {\r
+                return 1 * sign_b;\r
+            }\r
+\r
+            return sign_a * memcmp(a->buf, b->buf, a->size);\r
+        } else if(a->size) {\r
+            int sign = (a->buf[0] & 0x80) ? -1 : 1;\r
+            return (1) * sign;\r
+        } else if(b->size) {\r
+            int sign = (a->buf[0] & 0x80) ? -1 : 1;\r
+            return (-1) * sign;\r
+        } else {\r
+            return 0;\r
+        }\r
+    } else if(!a && !b) {\r
+        return 0;\r
+    } else if(!a) {\r
+        return -1;\r
+    } else {\r
+        return 1;\r
+    }\r
+\r
+}\r
+\r
+asn_random_fill_result_t\r
+INTEGER_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,\r
+                    const asn_encoding_constraints_t *constraints,\r
+                    size_t max_length) {\r
+    const asn_INTEGER_specifics_t *specs =\r
+        (const asn_INTEGER_specifics_t *)td->specifics;\r
+    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};\r
+    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};\r
+    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};\r
+    INTEGER_t *st = *sptr;\r
+    const asn_INTEGER_enum_map_t *emap;\r
+    size_t emap_len;\r
+    intmax_t value;\r
+    int find_inside_map;\r
+\r
+    if(max_length == 0) return result_skipped;\r
+\r
+    if(st == NULL) {\r
+        st = (INTEGER_t *)CALLOC(1, sizeof(*st));\r
+        if(st == NULL) {\r
+            return result_failed;\r
+        }\r
+    }\r
+\r
+    if(specs) {\r
+        emap = specs->value2enum;\r
+        emap_len = specs->map_count;\r
+        if(specs->strict_enumeration) {\r
+            find_inside_map = emap_len > 0;\r
+        } else {\r
+            find_inside_map = emap_len ? asn_random_between(0, 1) : 0;\r
+        }\r
+    } else {\r
+        emap = 0;\r
+        emap_len = 0;\r
+        find_inside_map = 0;\r
+    }\r
+\r
+    if(find_inside_map) {\r
+        assert(emap_len > 0);\r
+        value = emap[asn_random_between(0, emap_len - 1)].nat_value;\r
+    } else {\r
+        const asn_per_constraints_t *ct;\r
+\r
+        static const long variants[] = {\r
+            -65536, -65535, -65534, -32769, -32768, -32767, -16385, -16384,\r
+            -16383, -257,   -256,   -255,   -254,   -129,   -128,   -127,\r
+            -126,   -1,     0,      1,      126,    127,    128,    129,\r
+            254,    255,    256,    257,    16383,  16384,  16385,  32767,\r
+            32768,  32769,  65534,  65535,  65536,  65537};\r
+        if(specs && specs->field_unsigned) {\r
+            assert(variants[18] == 0);\r
+            value = variants[asn_random_between(\r
+                18, sizeof(variants) / sizeof(variants[0]) - 1)];\r
+        } else {\r
+            value = variants[asn_random_between(\r
+                0, sizeof(variants) / sizeof(variants[0]) - 1)];\r
+        }\r
+\r
+        if(!constraints) constraints = &td->encoding_constraints;\r
+        ct = constraints ? constraints->per_constraints : 0;\r
+        if(ct && (ct->value.flags & APC_CONSTRAINED)) {\r
+            if(value < ct->value.lower_bound || value > ct->value.upper_bound) {\r
+                value = asn_random_between(ct->value.lower_bound,\r
+                                           ct->value.upper_bound);\r
+            }\r
+        }\r
+    }\r
+\r
+    if(asn_imax2INTEGER(st, value)) {\r
+        if(st == *sptr) {\r
+            ASN_STRUCT_RESET(*td, st);\r
+        } else {\r
+            ASN_STRUCT_FREE(*td, st);\r
+        }\r
+        return result_failed;\r
+    } else {\r
+        *sptr = st;\r
+        result_ok.length = st->size;\r
+        return result_ok;\r
+    }\r
+}\r