Adding initial code jy.oak@samsung.com
[ric-app/kpimon.git] / asn1c_defs / all-defs / INTEGER.c
1 /*-\r
2  * Copyright (c) 2003-2014 Lev Walkin <vlm@lionet.info>.\r
3  * All rights reserved.\r
4  * Redistribution and modifications are permitted subject to BSD license.\r
5  */\r
6 #include <asn_internal.h>\r
7 #include <INTEGER.h>\r
8 #include <asn_codecs_prim.h>    /* Encoder and decoder of a primitive type */\r
9 #include <errno.h>\r
10 \r
11 /*\r
12  * INTEGER basic type description.\r
13  */\r
14 static const ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {\r
15         (ASN_TAG_CLASS_UNIVERSAL | (2 << 2))\r
16 };\r
17 asn_TYPE_operation_t asn_OP_INTEGER = {\r
18         INTEGER_free,\r
19         INTEGER_print,\r
20         INTEGER_compare,\r
21         ber_decode_primitive,\r
22         INTEGER_encode_der,\r
23         INTEGER_decode_xer,\r
24         INTEGER_encode_xer,\r
25 #ifdef  ASN_DISABLE_OER_SUPPORT\r
26         0,\r
27         0,\r
28 #else\r
29         INTEGER_decode_oer,     /* OER decoder */\r
30         INTEGER_encode_oer,     /* Canonical OER encoder */\r
31 #endif  /* ASN_DISABLE_OER_SUPPORT */\r
32 #ifdef  ASN_DISABLE_PER_SUPPORT\r
33         0,\r
34         0,\r
35         0,\r
36         0,\r
37 #else\r
38         INTEGER_decode_uper,    /* Unaligned PER decoder */\r
39         INTEGER_encode_uper,    /* Unaligned PER encoder */\r
40         INTEGER_decode_aper,    /* Aligned PER decoder */\r
41         INTEGER_encode_aper,    /* Aligned PER encoder */\r
42 #endif  /* ASN_DISABLE_PER_SUPPORT */\r
43         INTEGER_random_fill,\r
44         0       /* Use generic outmost tag fetcher */\r
45 };\r
46 asn_TYPE_descriptor_t asn_DEF_INTEGER = {\r
47         "INTEGER",\r
48         "INTEGER",\r
49         &asn_OP_INTEGER,\r
50         asn_DEF_INTEGER_tags,\r
51         sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),\r
52         asn_DEF_INTEGER_tags,   /* Same as above */\r
53         sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),\r
54         { 0, 0, asn_generic_no_constraint },\r
55         0, 0,   /* No members */\r
56         0       /* No specifics */\r
57 };\r
58 \r
59 /*\r
60  * Encode INTEGER type using DER.\r
61  */\r
62 asn_enc_rval_t\r
63 INTEGER_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,\r
64                    int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb,\r
65                    void *app_key) {\r
66     const INTEGER_t *st = (const INTEGER_t *)sptr;\r
67     asn_enc_rval_t rval;\r
68     INTEGER_t effective_integer;\r
69 \r
70         ASN_DEBUG("%s %s as INTEGER (tm=%d)",\r
71                 cb?"Encoding":"Estimating", td->name, tag_mode);\r
72 \r
73         /*\r
74          * Canonicalize integer in the buffer.\r
75          * (Remove too long sign extension, remove some first 0x00 bytes)\r
76          */\r
77         if(st->buf) {\r
78                 uint8_t *buf = st->buf;\r
79                 uint8_t *end1 = buf + st->size - 1;\r
80                 int shift;\r
81 \r
82                 /* Compute the number of superfluous leading bytes */\r
83                 for(; buf < end1; buf++) {\r
84                         /*\r
85                          * If the contents octets of an integer value encoding\r
86                          * consist of more than one octet, then the bits of the\r
87                          * first octet and bit 8 of the second octet:\r
88                          * a) shall not all be ones; and\r
89                          * b) shall not all be zero.\r
90                          */\r
91                         switch(*buf) {\r
92                         case 0x00: if((buf[1] & 0x80) == 0)\r
93                                         continue;\r
94                                 break;\r
95                         case 0xff: if((buf[1] & 0x80))\r
96                                         continue;\r
97                                 break;\r
98                         }\r
99                         break;\r
100                 }\r
101 \r
102                 /* Remove leading superfluous bytes from the integer */\r
103                 shift = buf - st->buf;\r
104                 if(shift) {\r
105             union {\r
106                 const uint8_t *c_buf;\r
107                 uint8_t *nc_buf;\r
108             } unconst;\r
109             unconst.c_buf = st->buf;\r
110             effective_integer.buf = unconst.nc_buf + shift;\r
111             effective_integer.size = st->size - shift;\r
112 \r
113             st = &effective_integer;\r
114         }\r
115     }\r
116 \r
117     rval = der_encode_primitive(td, st, tag_mode, tag, cb, app_key);\r
118     if(rval.structure_ptr == &effective_integer) {\r
119         rval.structure_ptr = sptr;\r
120     }\r
121     return rval;\r
122 }\r
123 \r
124 static const asn_INTEGER_enum_map_t *INTEGER_map_enum2value(\r
125     const asn_INTEGER_specifics_t *specs, const char *lstart,\r
126     const char *lstop);\r
127 \r
128 /*\r
129  * INTEGER specific human-readable output.\r
130  */\r
131 static ssize_t\r
132 INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {\r
133     const asn_INTEGER_specifics_t *specs =\r
134         (const asn_INTEGER_specifics_t *)td->specifics;\r
135         char scratch[32];\r
136         uint8_t *buf = st->buf;\r
137         uint8_t *buf_end = st->buf + st->size;\r
138         intmax_t value;\r
139         ssize_t wrote = 0;\r
140         char *p;\r
141         int ret;\r
142 \r
143         if(specs && specs->field_unsigned)\r
144                 ret = asn_INTEGER2umax(st, (uintmax_t *)&value);\r
145         else\r
146                 ret = asn_INTEGER2imax(st, &value);\r
147 \r
148         /* Simple case: the integer size is small */\r
149         if(ret == 0) {\r
150                 const asn_INTEGER_enum_map_t *el;\r
151                 el = (value >= 0 || !specs || !specs->field_unsigned)\r
152                         ? INTEGER_map_value2enum(specs, value) : 0;\r
153                 if(el) {\r
154                         if(plainOrXER == 0)\r
155                                 return asn__format_to_callback(cb, app_key,\r
156                                         "%" ASN_PRIdMAX " (%s)", value, el->enum_name);\r
157                         else\r
158                                 return asn__format_to_callback(cb, app_key,\r
159                                         "<%s/>", el->enum_name);\r
160                 } else if(plainOrXER && specs && specs->strict_enumeration) {\r
161                         ASN_DEBUG("ASN.1 forbids dealing with "\r
162                                 "unknown value of ENUMERATED type");\r
163                         errno = EPERM;\r
164                         return -1;\r
165                 } else {\r
166             return asn__format_to_callback(cb, app_key,\r
167                                            (specs && specs->field_unsigned)\r
168                                                ? "%" ASN_PRIuMAX\r
169                                                : "%" ASN_PRIdMAX,\r
170                                            value);\r
171         }\r
172         } else if(plainOrXER && specs && specs->strict_enumeration) {\r
173                 /*\r
174                  * Here and earlier, we cannot encode the ENUMERATED values\r
175                  * if there is no corresponding identifier.\r
176                  */\r
177                 ASN_DEBUG("ASN.1 forbids dealing with "\r
178                         "unknown value of ENUMERATED type");\r
179                 errno = EPERM;\r
180                 return -1;\r
181         }\r
182 \r
183         /* Output in the long xx:yy:zz... format */\r
184         /* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */\r
185         for(p = scratch; buf < buf_end; buf++) {\r
186                 const char * const h2c = "0123456789ABCDEF";\r
187                 if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {\r
188                         /* Flush buffer */\r
189                         if(cb(scratch, p - scratch, app_key) < 0)\r
190                                 return -1;\r
191                         wrote += p - scratch;\r
192                         p = scratch;\r
193                 }\r
194                 *p++ = h2c[*buf >> 4];\r
195                 *p++ = h2c[*buf & 0x0F];\r
196                 *p++ = 0x3a;    /* ":" */\r
197         }\r
198         if(p != scratch)\r
199                 p--;    /* Remove the last ":" */\r
200 \r
201         wrote += p - scratch;\r
202         return (cb(scratch, p - scratch, app_key) < 0) ? -1 : wrote;\r
203 }\r
204 \r
205 /*\r
206  * INTEGER specific human-readable output.\r
207  */\r
208 int\r
209 INTEGER_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,\r
210               asn_app_consume_bytes_f *cb, void *app_key) {\r
211     const INTEGER_t *st = (const INTEGER_t *)sptr;\r
212         ssize_t ret;\r
213 \r
214         (void)ilevel;\r
215 \r
216         if(!st || !st->buf)\r
217                 ret = cb("<absent>", 8, app_key);\r
218         else\r
219                 ret = INTEGER__dump(td, st, cb, app_key, 0);\r
220 \r
221         return (ret < 0) ? -1 : 0;\r
222 }\r
223 \r
224 struct e2v_key {\r
225         const char *start;\r
226         const char *stop;\r
227         const asn_INTEGER_enum_map_t *vemap;\r
228         const unsigned int *evmap;\r
229 };\r
230 static int\r
231 INTEGER__compar_enum2value(const void *kp, const void *am) {\r
232         const struct e2v_key *key = (const struct e2v_key *)kp;\r
233         const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;\r
234         const char *ptr, *end, *name;\r
235 \r
236         /* Remap the element (sort by different criterion) */\r
237         el = key->vemap + key->evmap[el - key->vemap];\r
238 \r
239         /* Compare strings */\r
240         for(ptr = key->start, end = key->stop, name = el->enum_name;\r
241                         ptr < end; ptr++, name++) {\r
242                 if(*ptr != *name || !*name)\r
243                         return *(const unsigned char *)ptr\r
244                                 - *(const unsigned char *)name;\r
245         }\r
246         return name[0] ? -1 : 0;\r
247 }\r
248 \r
249 static const asn_INTEGER_enum_map_t *\r
250 INTEGER_map_enum2value(const asn_INTEGER_specifics_t *specs, const char *lstart,\r
251                        const char *lstop) {\r
252     const asn_INTEGER_enum_map_t *el_found;\r
253         int count = specs ? specs->map_count : 0;\r
254         struct e2v_key key;\r
255         const char *lp;\r
256 \r
257         if(!count) return NULL;\r
258 \r
259         /* Guaranteed: assert(lstart < lstop); */\r
260         /* Figure out the tag name */\r
261         for(lstart++, lp = lstart; lp < lstop; lp++) {\r
262                 switch(*lp) {\r
263                 case 9: case 10: case 11: case 12: case 13: case 32: /* WSP */\r
264                 case 0x2f: /* '/' */ case 0x3e: /* '>' */\r
265                         break;\r
266                 default:\r
267                         continue;\r
268                 }\r
269                 break;\r
270         }\r
271         if(lp == lstop) return NULL;    /* No tag found */\r
272         lstop = lp;\r
273 \r
274         key.start = lstart;\r
275         key.stop = lstop;\r
276         key.vemap = specs->value2enum;\r
277         key.evmap = specs->enum2value;\r
278         el_found = (asn_INTEGER_enum_map_t *)bsearch(&key,\r
279                 specs->value2enum, count, sizeof(specs->value2enum[0]),\r
280                 INTEGER__compar_enum2value);\r
281         if(el_found) {\r
282                 /* Remap enum2value into value2enum */\r
283                 el_found = key.vemap + key.evmap[el_found - key.vemap];\r
284         }\r
285         return el_found;\r
286 }\r
287 \r
288 static int\r
289 INTEGER__compar_value2enum(const void *kp, const void *am) {\r
290         long a = *(const long *)kp;\r
291         const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;\r
292         long b = el->nat_value;\r
293         if(a < b) return -1;\r
294         else if(a == b) return 0;\r
295         else return 1;\r
296 }\r
297 \r
298 const asn_INTEGER_enum_map_t *\r
299 INTEGER_map_value2enum(const asn_INTEGER_specifics_t *specs, long value) {\r
300         int count = specs ? specs->map_count : 0;\r
301         if(!count) return 0;\r
302         return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum,\r
303                 count, sizeof(specs->value2enum[0]),\r
304                 INTEGER__compar_value2enum);\r
305 }\r
306 \r
307 static int\r
308 INTEGER_st_prealloc(INTEGER_t *st, int min_size) {\r
309         void *p = MALLOC(min_size + 1);\r
310         if(p) {\r
311                 void *b = st->buf;\r
312                 st->size = 0;\r
313                 st->buf = p;\r
314                 FREEMEM(b);\r
315                 return 0;\r
316         } else {\r
317                 return -1;\r
318         }\r
319 }\r
320 \r
321 /*\r
322  * Decode the chunk of XML text encoding INTEGER.\r
323  */\r
324 static enum xer_pbd_rval\r
325 INTEGER__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,\r
326                          const void *chunk_buf, size_t chunk_size) {\r
327     const asn_INTEGER_specifics_t *specs =\r
328         (const asn_INTEGER_specifics_t *)td->specifics;\r
329     INTEGER_t *st = (INTEGER_t *)sptr;\r
330         intmax_t dec_value;\r
331         intmax_t hex_value = 0;\r
332         const char *lp;\r
333         const char *lstart = (const char *)chunk_buf;\r
334         const char *lstop = lstart + chunk_size;\r
335         enum {\r
336                 ST_LEADSPACE,\r
337                 ST_SKIPSPHEX,\r
338                 ST_WAITDIGITS,\r
339                 ST_DIGITS,\r
340                 ST_DIGITS_TRAILSPACE,\r
341                 ST_HEXDIGIT1,\r
342                 ST_HEXDIGIT2,\r
343                 ST_HEXDIGITS_TRAILSPACE,\r
344                 ST_HEXCOLON,\r
345                 ST_END_ENUM,\r
346                 ST_UNEXPECTED\r
347         } state = ST_LEADSPACE;\r
348         const char *dec_value_start = 0; /* INVARIANT: always !0 in ST_DIGITS */\r
349         const char *dec_value_end = 0;\r
350 \r
351         if(chunk_size)\r
352                 ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x",\r
353                         (long)chunk_size, *lstart, lstop[-1]);\r
354 \r
355         if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))\r
356                 return XPBD_SYSTEM_FAILURE;\r
357 \r
358         /*\r
359          * We may have received a tag here. It will be processed inline.\r
360          * Use strtoul()-like code and serialize the result.\r
361          */\r
362         for(lp = lstart; lp < lstop; lp++) {\r
363                 int lv = *lp;\r
364                 switch(lv) {\r
365                 case 0x09: case 0x0a: case 0x0d: case 0x20:\r
366                         switch(state) {\r
367                         case ST_LEADSPACE:\r
368                         case ST_DIGITS_TRAILSPACE:\r
369                         case ST_HEXDIGITS_TRAILSPACE:\r
370                         case ST_SKIPSPHEX:\r
371                                 continue;\r
372                         case ST_DIGITS:\r
373                                 dec_value_end = lp;\r
374                                 state = ST_DIGITS_TRAILSPACE;\r
375                                 continue;\r
376                         case ST_HEXCOLON:\r
377                                 state = ST_HEXDIGITS_TRAILSPACE;\r
378                                 continue;\r
379                         default:\r
380                                 break;\r
381                         }\r
382                         break;\r
383                 case 0x2d:      /* '-' */\r
384                         if(state == ST_LEADSPACE) {\r
385                                 dec_value = 0;\r
386                                 dec_value_start = lp;\r
387                                 state = ST_WAITDIGITS;\r
388                                 continue;\r
389                         }\r
390                         break;\r
391                 case 0x2b:      /* '+' */\r
392                         if(state == ST_LEADSPACE) {\r
393                                 dec_value = 0;\r
394                                 dec_value_start = lp;\r
395                                 state = ST_WAITDIGITS;\r
396                                 continue;\r
397                         }\r
398                         break;\r
399                 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:\r
400                 case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:\r
401                         switch(state) {\r
402                         case ST_DIGITS: continue;\r
403                         case ST_SKIPSPHEX:      /* Fall through */\r
404                         case ST_HEXDIGIT1:\r
405                                 hex_value = (lv - 0x30) << 4;\r
406                                 state = ST_HEXDIGIT2;\r
407                                 continue;\r
408                         case ST_HEXDIGIT2:\r
409                                 hex_value += (lv - 0x30);\r
410                                 state = ST_HEXCOLON;\r
411                                 st->buf[st->size++] = (uint8_t)hex_value;\r
412                                 continue;\r
413                         case ST_HEXCOLON:\r
414                                 return XPBD_BROKEN_ENCODING;\r
415                         case ST_LEADSPACE:\r
416                                 dec_value = 0;\r
417                                 dec_value_start = lp;\r
418                                 /* FALL THROUGH */\r
419                         case ST_WAITDIGITS:\r
420                                 state = ST_DIGITS;\r
421                                 continue;\r
422                         default:\r
423                                 break;\r
424                         }\r
425                         break;\r
426                 case 0x3c:      /* '<', start of XML encoded enumeration */\r
427                         if(state == ST_LEADSPACE) {\r
428                                 const asn_INTEGER_enum_map_t *el;\r
429                                 el = INTEGER_map_enum2value(\r
430                                         (const asn_INTEGER_specifics_t *)\r
431                                         td->specifics, lstart, lstop);\r
432                                 if(el) {\r
433                                         ASN_DEBUG("Found \"%s\" => %ld",\r
434                                                 el->enum_name, el->nat_value);\r
435                                         dec_value = el->nat_value;\r
436                                         state = ST_END_ENUM;\r
437                                         lp = lstop - 1;\r
438                                         continue;\r
439                                 }\r
440                                 ASN_DEBUG("Unknown identifier for INTEGER");\r
441                         }\r
442                         return XPBD_BROKEN_ENCODING;\r
443                 case 0x3a:      /* ':' */\r
444                         if(state == ST_HEXCOLON) {\r
445                                 /* This colon is expected */\r
446                                 state = ST_HEXDIGIT1;\r
447                                 continue;\r
448                         } else if(state == ST_DIGITS) {\r
449                                 /* The colon here means that we have\r
450                                  * decoded the first two hexadecimal\r
451                                  * places as a decimal value.\r
452                                  * Switch decoding mode. */\r
453                                 ASN_DEBUG("INTEGER re-evaluate as hex form");\r
454                                 state = ST_SKIPSPHEX;\r
455                                 dec_value_start = 0;\r
456                                 lp = lstart - 1;\r
457                                 continue;\r
458                         } else {\r
459                                 ASN_DEBUG("state %d at %ld", state, (long)(lp - lstart));\r
460                                 break;\r
461                         }\r
462                 /* [A-Fa-f] */\r
463                 case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:\r
464                 case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:\r
465                         switch(state) {\r
466                         case ST_SKIPSPHEX:\r
467                         case ST_LEADSPACE: /* Fall through */\r
468                         case ST_HEXDIGIT1:\r
469                                 hex_value = lv - ((lv < 0x61) ? 0x41 : 0x61);\r
470                                 hex_value += 10;\r
471                                 hex_value <<= 4;\r
472                                 state = ST_HEXDIGIT2;\r
473                                 continue;\r
474                         case ST_HEXDIGIT2:\r
475                                 hex_value += lv - ((lv < 0x61) ? 0x41 : 0x61);\r
476                                 hex_value += 10;\r
477                                 st->buf[st->size++] = (uint8_t)hex_value;\r
478                                 state = ST_HEXCOLON;\r
479                                 continue;\r
480                         case ST_DIGITS:\r
481                                 ASN_DEBUG("INTEGER re-evaluate as hex form");\r
482                                 state = ST_SKIPSPHEX;\r
483                                 dec_value_start = 0;\r
484                                 lp = lstart - 1;\r
485                                 continue;\r
486                         default:\r
487                                 break;\r
488                         }\r
489                         break;\r
490                 }\r
491 \r
492                 /* Found extra non-numeric stuff */\r
493                 ASN_DEBUG("INTEGER :: Found non-numeric 0x%2x at %ld",\r
494                         lv, (long)(lp - lstart));\r
495                 state = ST_UNEXPECTED;\r
496                 break;\r
497         }\r
498 \r
499         switch(state) {\r
500         case ST_END_ENUM:\r
501                 /* Got a complete and valid enumeration encoded as a tag. */\r
502                 break;\r
503         case ST_DIGITS:\r
504                 dec_value_end = lstop;\r
505                 /* FALL THROUGH */\r
506         case ST_DIGITS_TRAILSPACE:\r
507                 /* The last symbol encountered was a digit. */\r
508         switch(asn_strtoimax_lim(dec_value_start, &dec_value_end, &dec_value)) {\r
509         case ASN_STRTOX_OK:\r
510             if(specs && specs->field_unsigned && (uintmax_t) dec_value <= ULONG_MAX) {\r
511                 break;\r
512             } else if(dec_value >= LONG_MIN && dec_value <= LONG_MAX) {\r
513                 break;\r
514             } else {\r
515                 /*\r
516                  * We model INTEGER on long for XER,\r
517                  * to avoid rewriting all the tests at once.\r
518                  */\r
519                 ASN_DEBUG("INTEGER exceeds long range");\r
520             }\r
521             /* Fall through */\r
522         case ASN_STRTOX_ERROR_RANGE:\r
523             ASN_DEBUG("INTEGER decode %s hit range limit", td->name);\r
524             return XPBD_DECODER_LIMIT;\r
525                 case ASN_STRTOX_ERROR_INVAL:\r
526                 case ASN_STRTOX_EXPECT_MORE:\r
527                 case ASN_STRTOX_EXTRA_DATA:\r
528                         return XPBD_BROKEN_ENCODING;\r
529                 }\r
530                 break;\r
531         case ST_HEXCOLON:\r
532         case ST_HEXDIGITS_TRAILSPACE:\r
533                 st->buf[st->size] = 0;  /* Just in case termination */\r
534                 return XPBD_BODY_CONSUMED;\r
535         case ST_HEXDIGIT1:\r
536         case ST_HEXDIGIT2:\r
537         case ST_SKIPSPHEX:\r
538                 return XPBD_BROKEN_ENCODING;\r
539         case ST_LEADSPACE:\r
540                 /* Content not found */\r
541                 return XPBD_NOT_BODY_IGNORE;\r
542         case ST_WAITDIGITS:\r
543         case ST_UNEXPECTED:\r
544                 ASN_DEBUG("INTEGER: No useful digits (state %d)", state);\r
545                 return XPBD_BROKEN_ENCODING;    /* No digits */\r
546         }\r
547 \r
548         /*\r
549          * Convert the result of parsing of enumeration or a straight\r
550          * decimal value into a BER representation.\r
551          */\r
552         if(asn_imax2INTEGER(st, dec_value)) {\r
553                 ASN_DEBUG("INTEGER decode %s conversion failed", td->name);\r
554                 return XPBD_SYSTEM_FAILURE;\r
555         }\r
556 \r
557         return XPBD_BODY_CONSUMED;\r
558 }\r
559 \r
560 asn_dec_rval_t\r
561 INTEGER_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,\r
562                    const asn_TYPE_descriptor_t *td, void **sptr,\r
563                    const char *opt_mname, const void *buf_ptr, size_t size) {\r
564     return xer_decode_primitive(opt_codec_ctx, td,\r
565                 sptr, sizeof(INTEGER_t), opt_mname,\r
566                 buf_ptr, size, INTEGER__xer_body_decode);\r
567 }\r
568 \r
569 asn_enc_rval_t\r
570 INTEGER_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,\r
571                    int ilevel, enum xer_encoder_flags_e flags,\r
572                    asn_app_consume_bytes_f *cb, void *app_key) {\r
573     const INTEGER_t *st = (const INTEGER_t *)sptr;\r
574         asn_enc_rval_t er = {0,0,0};\r
575 \r
576         (void)ilevel;\r
577         (void)flags;\r
578         \r
579         if(!st || !st->buf)\r
580                 ASN__ENCODE_FAILED;\r
581 \r
582         er.encoded = INTEGER__dump(td, st, cb, app_key, 1);\r
583         if(er.encoded < 0) ASN__ENCODE_FAILED;\r
584 \r
585         ASN__ENCODED_OK(er);\r
586 }\r
587 \r
588 #ifndef ASN_DISABLE_PER_SUPPORT\r
589 \r
590 asn_dec_rval_t\r
591 INTEGER_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,\r
592                     const asn_TYPE_descriptor_t *td,\r
593                     const asn_per_constraints_t *constraints, void **sptr,\r
594                     asn_per_data_t *pd) {\r
595     const asn_INTEGER_specifics_t *specs =\r
596         (const asn_INTEGER_specifics_t *)td->specifics;\r
597     asn_dec_rval_t rval = { RC_OK, 0 };\r
598         INTEGER_t *st = (INTEGER_t *)*sptr;\r
599         const asn_per_constraint_t *ct;\r
600         int repeat;\r
601 \r
602         (void)opt_codec_ctx;\r
603 \r
604         if(!st) {\r
605                 st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));\r
606                 if(!st) ASN__DECODE_FAILED;\r
607         }\r
608 \r
609         if(!constraints) constraints = td->encoding_constraints.per_constraints;\r
610         ct = constraints ? &constraints->value : 0;\r
611 \r
612         if(ct && ct->flags & APC_EXTENSIBLE) {\r
613                 int inext = per_get_few_bits(pd, 1);\r
614                 if(inext < 0) ASN__DECODE_STARVED;\r
615                 if(inext) ct = 0;\r
616         }\r
617 \r
618         FREEMEM(st->buf);\r
619         st->buf = 0;\r
620         st->size = 0;\r
621         if(ct) {\r
622                 if(ct->flags & APC_SEMI_CONSTRAINED) {\r
623                         st->buf = (uint8_t *)CALLOC(1, 2);\r
624                         if(!st->buf) ASN__DECODE_FAILED;\r
625                         st->size = 1;\r
626                 } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {\r
627                         size_t size = (ct->range_bits + 7) >> 3;\r
628                         st->buf = (uint8_t *)MALLOC(1 + size + 1);\r
629                         if(!st->buf) ASN__DECODE_FAILED;\r
630                         st->size = size;\r
631                 }\r
632         }\r
633 \r
634         /* X.691-2008/11, #13.2.2, constrained whole number */\r
635         if(ct && ct->flags != APC_UNCONSTRAINED) {\r
636                 /* #11.5.6 */\r
637                 ASN_DEBUG("Integer with range %d bits", ct->range_bits);\r
638                 if(ct->range_bits >= 0) {\r
639                         if((size_t)ct->range_bits > 8 * sizeof(unsigned long))\r
640                                 ASN__DECODE_FAILED;\r
641 \r
642                         if(specs && specs->field_unsigned) {\r
643                                 unsigned long uvalue = 0;\r
644                                 if(uper_get_constrained_whole_number(pd,\r
645                                         &uvalue, ct->range_bits))\r
646                                         ASN__DECODE_STARVED;\r
647                                 ASN_DEBUG("Got value %lu + low %ld",\r
648                                         uvalue, ct->lower_bound);\r
649                                 uvalue += ct->lower_bound;\r
650                                 if(asn_ulong2INTEGER(st, uvalue))\r
651                                         ASN__DECODE_FAILED;\r
652                         } else {\r
653                                 unsigned long uvalue = 0;\r
654                                 long svalue;\r
655                                 if(uper_get_constrained_whole_number(pd,\r
656                                         &uvalue, ct->range_bits))\r
657                                         ASN__DECODE_STARVED;\r
658                                 ASN_DEBUG("Got value %lu + low %ld",\r
659                                         uvalue, ct->lower_bound);\r
660                 if(per_long_range_unrebase(uvalue, ct->lower_bound,\r
661                                            ct->upper_bound, &svalue)\r
662                    || asn_long2INTEGER(st, svalue)) {\r
663                     ASN__DECODE_FAILED;\r
664                 }\r
665                         }\r
666                         return rval;\r
667                 }\r
668         } else {\r
669                 ASN_DEBUG("Decoding unconstrained integer %s", td->name);\r
670         }\r
671 \r
672         /* X.691, #12.2.3, #12.2.4 */\r
673         do {\r
674                 ssize_t len = 0;\r
675                 void *p = NULL;\r
676                 int ret = 0;\r
677 \r
678                 /* Get the PER length */\r
679                 len = uper_get_length(pd, -1, 0, &repeat);\r
680                 if(len < 0) ASN__DECODE_STARVED;\r
681 \r
682                 p = REALLOC(st->buf, st->size + len + 1);\r
683                 if(!p) ASN__DECODE_FAILED;\r
684                 st->buf = (uint8_t *)p;\r
685 \r
686                 ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);\r
687                 if(ret < 0) ASN__DECODE_STARVED;\r
688                 st->size += len;\r
689         } while(repeat);\r
690         st->buf[st->size] = 0;  /* JIC */\r
691 \r
692         /* #12.2.3 */\r
693         if(ct && ct->lower_bound) {\r
694                 /*\r
695                  * TODO: replace by in-place arithmetics.\r
696                  */\r
697                 long value = 0;\r
698                 if(asn_INTEGER2long(st, &value))\r
699                         ASN__DECODE_FAILED;\r
700                 if(asn_imax2INTEGER(st, value + ct->lower_bound))\r
701                         ASN__DECODE_FAILED;\r
702         }\r
703 \r
704         return rval;\r
705 }\r
706 \r
707 asn_enc_rval_t\r
708 INTEGER_encode_uper(const asn_TYPE_descriptor_t *td,\r
709                     const asn_per_constraints_t *constraints, const void *sptr,\r
710                     asn_per_outp_t *po) {\r
711         const asn_INTEGER_specifics_t *specs =\r
712                 (const asn_INTEGER_specifics_t *)td->specifics;\r
713         asn_enc_rval_t er = {0,0,0};\r
714         const INTEGER_t *st = (const INTEGER_t *)sptr;\r
715         const uint8_t *buf;\r
716         const uint8_t *end;\r
717         const asn_per_constraint_t *ct;\r
718         long value = 0;\r
719 \r
720         if(!st || st->size == 0) ASN__ENCODE_FAILED;\r
721 \r
722         if(!constraints) constraints = td->encoding_constraints.per_constraints;\r
723         ct = constraints ? &constraints->value : 0;\r
724 \r
725         er.encoded = 0;\r
726 \r
727         if(ct) {\r
728                 int inext = 0;\r
729                 if(specs && specs->field_unsigned) {\r
730                         unsigned long uval;\r
731                         if(asn_INTEGER2ulong(st, &uval))\r
732                                 ASN__ENCODE_FAILED;\r
733                         /* Check proper range */\r
734                         if(ct->flags & APC_SEMI_CONSTRAINED) {\r
735                                 if(uval < (unsigned long)ct->lower_bound)\r
736                                         inext = 1;\r
737                         } else if(ct->range_bits >= 0) {\r
738                                 if(uval < (unsigned long)ct->lower_bound\r
739                                 || uval > (unsigned long)ct->upper_bound)\r
740                                         inext = 1;\r
741                         }\r
742                         ASN_DEBUG("Value %lu (%02x/%" ASN_PRI_SIZE ") lb %lu ub %lu %s",\r
743                                 uval, st->buf[0], st->size,\r
744                                 ct->lower_bound, ct->upper_bound,\r
745                                 inext ? "ext" : "fix");\r
746                         value = uval;\r
747                 } else {\r
748                         if(asn_INTEGER2long(st, &value))\r
749                                 ASN__ENCODE_FAILED;\r
750                         /* Check proper range */\r
751                         if(ct->flags & APC_SEMI_CONSTRAINED) {\r
752                                 if(value < ct->lower_bound)\r
753                                         inext = 1;\r
754                         } else if(ct->range_bits >= 0) {\r
755                                 if(value < ct->lower_bound\r
756                                 || value > ct->upper_bound)\r
757                                         inext = 1;\r
758                         }\r
759                         ASN_DEBUG("Value %ld (%02x/%" ASN_PRI_SIZE ") lb %ld ub %ld %s",\r
760                                 value, st->buf[0], st->size,\r
761                                 ct->lower_bound, ct->upper_bound,\r
762                                 inext ? "ext" : "fix");\r
763                 }\r
764                 if(ct->flags & APC_EXTENSIBLE) {\r
765                         if(per_put_few_bits(po, inext, 1))\r
766                                 ASN__ENCODE_FAILED;\r
767                         if(inext) ct = 0;\r
768                 } else if(inext) {\r
769                         ASN__ENCODE_FAILED;\r
770                 }\r
771         }\r
772 \r
773 \r
774         /* X.691-11/2008, #13.2.2, test if constrained whole number */\r
775         if(ct && ct->range_bits >= 0) {\r
776         unsigned long v;\r
777                 /* #11.5.6 -> #11.3 */\r
778                 ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",\r
779                         value, value - ct->lower_bound, ct->range_bits);\r
780         if(specs && specs->field_unsigned) {\r
781                 if (  ((unsigned long)ct->lower_bound > (unsigned long)(ct->upper_bound)\r
782                    || ((unsigned long)value < (unsigned long)ct->lower_bound))\r
783                    || ((unsigned long)value > (unsigned long)ct->upper_bound)\r
784                 ) {\r
785                         ASN_DEBUG("Value %lu to-be-encoded is outside the bounds [%lu, %lu]!",\r
786                                 value, ct->lower_bound, ct->upper_bound);\r
787                         ASN__ENCODE_FAILED;\r
788                 }\r
789                 v = (unsigned long)value - (unsigned long)ct->lower_bound;\r
790         } else {\r
791                 if(per_long_range_rebase(value, ct->lower_bound, ct->upper_bound, &v)) {\r
792                         ASN__ENCODE_FAILED;\r
793                 }\r
794         }\r
795         if(uper_put_constrained_whole_number_u(po, v, ct->range_bits))\r
796                 ASN__ENCODE_FAILED;\r
797         ASN__ENCODED_OK(er);\r
798         }\r
799 \r
800         if(ct && ct->lower_bound) {\r
801                 ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);\r
802                 /* TODO: adjust lower bound */\r
803                 ASN__ENCODE_FAILED;\r
804         }\r
805 \r
806         for(buf = st->buf, end = st->buf + st->size; buf < end;) {\r
807         int need_eom = 0;\r
808         ssize_t mayEncode = uper_put_length(po, end - buf, &need_eom);\r
809         if(mayEncode < 0)\r
810                         ASN__ENCODE_FAILED;\r
811                 if(per_put_many_bits(po, buf, 8 * mayEncode))\r
812                         ASN__ENCODE_FAILED;\r
813                 buf += mayEncode;\r
814         if(need_eom && uper_put_length(po, 0, 0)) ASN__ENCODE_FAILED;\r
815     }\r
816 \r
817         ASN__ENCODED_OK(er);\r
818 }\r
819 \r
820 asn_dec_rval_t\r
821 INTEGER_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,\r
822                     const asn_TYPE_descriptor_t *td,\r
823                     const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {\r
824         const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;\r
825         asn_dec_rval_t rval = { RC_OK, 0 };\r
826         INTEGER_t *st = (INTEGER_t *)*sptr;\r
827         const asn_per_constraint_t *ct;\r
828         int repeat;\r
829 \r
830         (void)opt_codec_ctx;\r
831 \r
832         if(!st) {\r
833                 st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));\r
834                 if(!st) ASN__DECODE_FAILED;\r
835         }\r
836 \r
837         if(!constraints) constraints = td->encoding_constraints.per_constraints;\r
838         ct = constraints ? &constraints->value : 0;\r
839 \r
840         if(ct && ct->flags & APC_EXTENSIBLE) {\r
841                 int inext = per_get_few_bits(pd, 1);\r
842                 if(inext < 0) ASN__DECODE_STARVED;\r
843                 if(inext) ct = 0;\r
844         }\r
845 \r
846         FREEMEM(st->buf);\r
847         st->buf = 0;\r
848         st->size = 0;\r
849         if(ct) {\r
850                 if(ct->flags & APC_SEMI_CONSTRAINED) {\r
851                         st->buf = (uint8_t *)CALLOC(1, 2);\r
852                         if(!st->buf) ASN__DECODE_FAILED;\r
853                         st->size = 1;\r
854                 } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {\r
855                         size_t size = (ct->range_bits + 7) >> 3;\r
856                         st->buf = (uint8_t *)MALLOC(1 + size + 1);\r
857                         if(!st->buf) ASN__DECODE_FAILED;\r
858                         st->size = size;\r
859                 }\r
860         }\r
861 \r
862         /* X.691, #12.2.2 */\r
863         if(ct && ct->flags != APC_UNCONSTRAINED) {\r
864                 /* #10.5.6 */\r
865                 ASN_DEBUG("Integer with range %d bits", ct->range_bits);\r
866                 if(ct->range_bits >= 0) {\r
867                         if (ct->range_bits > 16) {\r
868                                 int max_range_bytes = (ct->range_bits >> 3) +\r
869                                                       (((ct->range_bits % 8) > 0) ? 1 : 0);\r
870                                 int length = 0, i;\r
871                                 long value = 0;\r
872 \r
873                                 for (i = 1; ; i++) {\r
874                                         int upper = 1 << i;\r
875                                         if (upper >= max_range_bytes)\r
876                                                 break;\r
877                                 }\r
878                                 ASN_DEBUG("Can encode %d (%d bytes) in %d bits", ct->range_bits,\r
879                                           max_range_bytes, i);\r
880 \r
881                                 if ((length = per_get_few_bits(pd, i)) < 0)\r
882                                         ASN__DECODE_FAILED;\r
883 \r
884                                 /* X.691 #12.2.6 length determinant + lb (1) */\r
885                                 length += 1;\r
886                                 ASN_DEBUG("Got length %d", length);\r
887                                 if (aper_get_align(pd) != 0)\r
888                                         ASN__DECODE_FAILED;\r
889                                 while (length--) {\r
890                                         int buf = per_get_few_bits(pd, 8);\r
891                                         if (buf < 0)\r
892                                                 ASN__DECODE_FAILED;\r
893                                         value += (((long)buf) << (8 * length));\r
894                                 }\r
895 \r
896                                 value += ct->lower_bound;\r
897                                 if((specs && specs->field_unsigned)\r
898                                         ? asn_uint642INTEGER(st, (unsigned long)value)\r
899                                         : asn_int642INTEGER(st, value))\r
900                                         ASN__DECODE_FAILED;\r
901                                 ASN_DEBUG("Got value %ld + low %ld",\r
902                                           value, ct->lower_bound);\r
903                         } else {\r
904                                 long value = 0;\r
905                                 if (ct->range_bits < 8) {\r
906                                         value = per_get_few_bits(pd, ct->range_bits);\r
907                                         if(value < 0) ASN__DECODE_STARVED;\r
908                                 } else if (ct->range_bits == 8) {\r
909                                         if (aper_get_align(pd) < 0)\r
910                                                 ASN__DECODE_FAILED;\r
911                                         value = per_get_few_bits(pd, ct->range_bits);\r
912                                         if(value < 0) ASN__DECODE_STARVED;\r
913                                 } else {\r
914                                         /* Align */\r
915                                         if (aper_get_align(pd) < 0)\r
916                                                 ASN__DECODE_FAILED;\r
917                                         value = per_get_few_bits(pd, 16);\r
918                                         if(value < 0) ASN__DECODE_STARVED;\r
919                                 }\r
920                                 value += ct->lower_bound;\r
921                                 if((specs && specs->field_unsigned)\r
922                                         ? asn_ulong2INTEGER(st, value)\r
923                                         : asn_long2INTEGER(st, value))\r
924                                         ASN__DECODE_FAILED;\r
925                                 ASN_DEBUG("Got value %ld + low %ld",\r
926                                           value, ct->lower_bound);\r
927                         }\r
928                         return rval;\r
929                 } else {\r
930                         ASN__DECODE_FAILED;\r
931                 }\r
932         } else {\r
933                 ASN_DEBUG("Decoding unconstrained integer %s", td->name);\r
934         }\r
935 \r
936         /* X.691, #12.2.3, #12.2.4 */\r
937         do {\r
938                 ssize_t len;\r
939                 void *p;\r
940                 int ret;\r
941 \r
942                 /* Get the PER length */\r
943                 len = aper_get_length(pd, -1, -1, &repeat);\r
944                 if(len < 0) ASN__DECODE_STARVED;\r
945 \r
946                 p = REALLOC(st->buf, st->size + len + 1);\r
947                 if(!p) ASN__DECODE_FAILED;\r
948                 st->buf = (uint8_t *)p;\r
949 \r
950                 ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);\r
951                 if(ret < 0) ASN__DECODE_STARVED;\r
952                 st->size += len;\r
953         } while(repeat);\r
954         st->buf[st->size] = 0;  /* JIC */\r
955 \r
956         /* #12.2.3 */\r
957         if(ct && ct->lower_bound) {\r
958                 /*\r
959                  * TODO: replace by in-place arithmetics.\r
960                  */\r
961                 long value;\r
962                 if(asn_INTEGER2long(st, &value))\r
963                         ASN__DECODE_FAILED;\r
964                 if(asn_long2INTEGER(st, value + ct->lower_bound))\r
965                         ASN__DECODE_FAILED;\r
966         }\r
967 \r
968         return rval;\r
969 }\r
970 \r
971 asn_enc_rval_t\r
972 INTEGER_encode_aper(const asn_TYPE_descriptor_t *td,\r
973                     const asn_per_constraints_t *constraints,\r
974                     const void *sptr, asn_per_outp_t *po) {\r
975         const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;\r
976         asn_enc_rval_t er = {0,0,0};\r
977         const INTEGER_t *st = (const INTEGER_t *)sptr;\r
978         const uint8_t *buf;\r
979         const uint8_t *end;\r
980         const asn_per_constraint_t *ct;\r
981         long value = 0;\r
982 \r
983         if(!st || st->size == 0) ASN__ENCODE_FAILED;\r
984 \r
985         if(!constraints) constraints = td->encoding_constraints.per_constraints;\r
986         ct = constraints ? &constraints->value : 0;\r
987 \r
988         er.encoded = 0;\r
989 \r
990         if(ct) {\r
991                 int inext = 0;\r
992                 if(specs && specs->field_unsigned) {\r
993                         unsigned long uval;\r
994                         if(asn_INTEGER2ulong(st, &uval))\r
995                                 ASN__ENCODE_FAILED;\r
996                         /* Check proper range */\r
997                         if(ct->flags & APC_SEMI_CONSTRAINED) {\r
998                                 if(uval < (unsigned long)ct->lower_bound)\r
999                                         inext = 1;\r
1000                         } else if(ct->range_bits >= 0) {\r
1001                                 if(uval < (unsigned long)ct->lower_bound\r
1002                                         || uval > (unsigned long)ct->upper_bound)\r
1003                                         inext = 1;\r
1004                         }\r
1005                         ASN_DEBUG("Value %lu (%02x/%lu) lb %ld ub %ld %s",\r
1006                                   uval, st->buf[0], st->size,\r
1007                                   ct->lower_bound, ct->upper_bound,\r
1008                                   inext ? "ext" : "fix");\r
1009                         value = uval;\r
1010                 } else {\r
1011                         if(asn_INTEGER2long(st, &value)) ASN__ENCODE_FAILED;\r
1012                         /* Check proper range */\r
1013                         if(ct->flags & APC_SEMI_CONSTRAINED) {\r
1014                                 if(value < ct->lower_bound)\r
1015                                         inext = 1;\r
1016                         } else if(ct->range_bits >= 0) {\r
1017                                 if(value < ct->lower_bound\r
1018                                         || value > ct->upper_bound)\r
1019                                         inext = 1;\r
1020                         }\r
1021                         ASN_DEBUG("Value %lu (%02x/%lu) lb %ld ub %ld %s",\r
1022                                   value, st->buf[0], st->size,\r
1023                                   ct->lower_bound, ct->upper_bound,\r
1024                                   inext ? "ext" : "fix");\r
1025                 }\r
1026                 if(ct->flags & APC_EXTENSIBLE) {\r
1027                         if(per_put_few_bits(po, inext, 1))\r
1028                                 ASN__ENCODE_FAILED;\r
1029                         if(inext) ct = 0;\r
1030                 } else if(inext) {\r
1031                         ASN__ENCODE_FAILED;\r
1032                 }\r
1033         }\r
1034 \r
1035         /* X.691, #12.2.2 */\r
1036         if(ct && ct->range_bits >= 0) {\r
1037                 unsigned long v;\r
1038 \r
1039                 /* #10.5.6 */\r
1040                 ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",\r
1041                           value, value - ct->lower_bound, ct->range_bits);\r
1042 \r
1043                 v = value - ct->lower_bound;\r
1044 \r
1045                 /* #12 <= 8 -> alignment ? */\r
1046                 if (ct->range_bits < 8) {\r
1047                         if(per_put_few_bits(po, 0x00 | v, ct->range_bits))\r
1048                                 ASN__ENCODE_FAILED;\r
1049                 } else if (ct->range_bits == 8) {\r
1050                         if(aper_put_align(po) < 0)\r
1051                                 ASN__ENCODE_FAILED;\r
1052                         if(per_put_few_bits(po, 0x00 | v, ct->range_bits))\r
1053                                 ASN__ENCODE_FAILED;\r
1054                 } else if (ct->range_bits <= 16) {\r
1055                         /* Consume the bytes to align on octet */\r
1056                         if(aper_put_align(po) < 0)\r
1057                                 ASN__ENCODE_FAILED;\r
1058                         if(per_put_few_bits(po, 0x0000 | v,\r
1059                                             16))\r
1060                                 ASN__ENCODE_FAILED;\r
1061                 } else {\r
1062                         /* TODO: extend to >64 bits */\r
1063                         int64_t v64 = v;\r
1064                         int i, j;\r
1065                         int max_range_bytes = (ct->range_bits >> 3) +\r
1066                                               (((ct->range_bits % 8) > 0) ? 1 : 0);\r
1067 \r
1068                         for (i = 1; ; i++) {\r
1069                                 int upper = 1 << i;\r
1070                                 if (upper >= max_range_bytes)\r
1071                                         break;\r
1072                         }\r
1073 \r
1074                         for (j = sizeof(int64_t) -1; j != 0; j--) {\r
1075                                 int64_t val;\r
1076                                 val = v64 >> (j * 8);\r
1077                                 if (val != 0)\r
1078                                         break;\r
1079                         }\r
1080 \r
1081                         /* Putting length in the minimum number of bits ex: 5 = 3bits */\r
1082                         if (per_put_few_bits(po, j, i))\r
1083                                 ASN__ENCODE_FAILED;\r
1084 \r
1085                         /* Consume the bits to align on octet */\r
1086                         if (aper_put_align(po) < 0)\r
1087                                 ASN__ENCODE_FAILED;\r
1088                         /* Put the value */\r
1089                         for (i = 0; i <= j; i++) {\r
1090                                 if(per_put_few_bits(po, (v64 >> (8 * (j - i))) & 0xff, 8))\r
1091                                         ASN__ENCODE_FAILED;\r
1092                         }\r
1093                 }\r
1094                 ASN__ENCODED_OK(er);\r
1095         }\r
1096 \r
1097         if(ct && ct->lower_bound) {\r
1098                 ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);\r
1099                 /* TODO: adjust lower bound */\r
1100                 ASN__ENCODE_FAILED;\r
1101         }\r
1102 \r
1103         for(buf = st->buf, end = st->buf + st->size; buf < end;) {\r
1104                 ssize_t mayEncode = aper_put_length(po, -1, end - buf);\r
1105                 if(mayEncode < 0)\r
1106                         ASN__ENCODE_FAILED;\r
1107                 if(per_put_many_bits(po, buf, 8 * mayEncode))\r
1108                         ASN__ENCODE_FAILED;\r
1109                 buf += mayEncode;\r
1110         }\r
1111 \r
1112         ASN__ENCODED_OK(er);\r
1113 }\r
1114 \r
1115 #endif  /* ASN_DISABLE_PER_SUPPORT */\r
1116 \r
1117 static intmax_t\r
1118 asn__integer_convert(const uint8_t *b, const uint8_t *end) {\r
1119     uintmax_t value;\r
1120 \r
1121     /* Perform the sign initialization */\r
1122     /* Actually value = -(*b >> 7); gains nothing, yet unreadable! */\r
1123     if((*b >> 7)) {\r
1124         value = (uintmax_t)(-1);\r
1125     } else {\r
1126         value = 0;\r
1127     }\r
1128 \r
1129     /* Conversion engine */\r
1130     for(; b < end; b++) {\r
1131         value = (value << 8) | *b;\r
1132     }\r
1133 \r
1134     return value;\r
1135 }\r
1136 \r
1137 int\r
1138 asn_INTEGER2imax(const INTEGER_t *iptr, intmax_t *lptr) {\r
1139         uint8_t *b, *end;\r
1140         size_t size;\r
1141 \r
1142         /* Sanity checking */\r
1143         if(!iptr || !iptr->buf || !lptr) {\r
1144                 errno = EINVAL;\r
1145                 return -1;\r
1146         }\r
1147 \r
1148         /* Cache the begin/end of the buffer */\r
1149         b = iptr->buf;  /* Start of the INTEGER buffer */\r
1150         size = iptr->size;\r
1151         end = b + size; /* Where to stop */\r
1152 \r
1153         if(size > sizeof(intmax_t)) {\r
1154                 uint8_t *end1 = end - 1;\r
1155                 /*\r
1156                  * Slightly more advanced processing,\r
1157                  * able to process INTEGERs with >sizeof(intmax_t) bytes\r
1158                  * when the actual value is small, e.g. for intmax_t == int32_t\r
1159                  * (0x0000000000abcdef INTEGER would yield a fine 0x00abcdef int32_t)\r
1160                  */\r
1161                 /* Skip out the insignificant leading bytes */\r
1162                 for(; b < end1; b++) {\r
1163                         switch(*b) {\r
1164                                 case 0x00: if((b[1] & 0x80) == 0) continue; break;\r
1165                                 case 0xff: if((b[1] & 0x80) != 0) continue; break;\r
1166                         }\r
1167                         break;\r
1168                 }\r
1169 \r
1170                 size = end - b;\r
1171                 if(size > sizeof(intmax_t)) {\r
1172                         /* Still cannot fit the sizeof(intmax_t) */\r
1173                         errno = ERANGE;\r
1174                         return -1;\r
1175                 }\r
1176         }\r
1177 \r
1178         /* Shortcut processing of a corner case */\r
1179         if(end == b) {\r
1180                 *lptr = 0;\r
1181                 return 0;\r
1182         }\r
1183 \r
1184         *lptr = asn__integer_convert(b, end);\r
1185         return 0;\r
1186 }\r
1187 \r
1188 /* FIXME: negative INTEGER values are silently interpreted as large unsigned ones. */\r
1189 int\r
1190 asn_INTEGER2umax(const INTEGER_t *iptr, uintmax_t *lptr) {\r
1191         uint8_t *b, *end;\r
1192         uintmax_t value;\r
1193         size_t size;\r
1194 \r
1195         if(!iptr || !iptr->buf || !lptr) {\r
1196                 errno = EINVAL;\r
1197                 return -1;\r
1198         }\r
1199 \r
1200         b = iptr->buf;\r
1201         size = iptr->size;\r
1202         end = b + size;\r
1203 \r
1204         /* If all extra leading bytes are zeroes, ignore them */\r
1205         for(; size > sizeof(value); b++, size--) {\r
1206                 if(*b) {\r
1207                         /* Value won't fit into uintmax_t */\r
1208                         errno = ERANGE;\r
1209                         return -1;\r
1210                 }\r
1211         }\r
1212 \r
1213         /* Conversion engine */\r
1214         for(value = 0; b < end; b++)\r
1215                 value = (value << 8) | *b;\r
1216 \r
1217         *lptr = value;\r
1218         return 0;\r
1219 }\r
1220 \r
1221 int\r
1222 asn_umax2INTEGER(INTEGER_t *st, uintmax_t value) {\r
1223     uint8_t *buf;\r
1224     uint8_t *end;\r
1225     uint8_t *b;\r
1226     int shr;\r
1227 \r
1228     if(value <= ((~(uintmax_t)0) >> 1)) {\r
1229         return asn_imax2INTEGER(st, value);\r
1230     }\r
1231 \r
1232     buf = (uint8_t *)MALLOC(1 + sizeof(value));\r
1233     if(!buf) return -1;\r
1234 \r
1235     end = buf + (sizeof(value) + 1);\r
1236     buf[0] = 0; /* INTEGERs are signed. 0-byte indicates positive. */\r
1237     for(b = buf + 1, shr = (sizeof(value) - 1) * 8; b < end; shr -= 8, b++)\r
1238         *b = (uint8_t)(value >> shr);\r
1239 \r
1240     if(st->buf) FREEMEM(st->buf);\r
1241     st->buf = buf;\r
1242     st->size = 1 + sizeof(value);\r
1243 \r
1244         return 0;\r
1245 }\r
1246 \r
1247 int\r
1248 asn_imax2INTEGER(INTEGER_t *st, intmax_t value) {\r
1249         uint8_t *buf, *bp;\r
1250         uint8_t *p;\r
1251         uint8_t *pstart;\r
1252         uint8_t *pend1;\r
1253         int littleEndian = 1;   /* Run-time detection */\r
1254         int add;\r
1255 \r
1256         if(!st) {\r
1257                 errno = EINVAL;\r
1258                 return -1;\r
1259         }\r
1260 \r
1261         buf = (uint8_t *)(long *)MALLOC(sizeof(value));\r
1262         if(!buf) return -1;\r
1263 \r
1264         if(*(char *)&littleEndian) {\r
1265                 pstart = (uint8_t *)&value + sizeof(value) - 1;\r
1266                 pend1 = (uint8_t *)&value;\r
1267                 add = -1;\r
1268         } else {\r
1269                 pstart = (uint8_t *)&value;\r
1270                 pend1 = pstart + sizeof(value) - 1;\r
1271                 add = 1;\r
1272         }\r
1273 \r
1274         /*\r
1275          * If the contents octet consists of more than one octet,\r
1276          * then bits of the first octet and bit 8 of the second octet:\r
1277          * a) shall not all be ones; and\r
1278          * b) shall not all be zero.\r
1279          */\r
1280         for(p = pstart; p != pend1; p += add) {\r
1281                 switch(*p) {\r
1282                 case 0x00: if((*(p+add) & 0x80) == 0)\r
1283                                 continue;\r
1284                         break;\r
1285                 case 0xff: if((*(p+add) & 0x80))\r
1286                                 continue;\r
1287                         break;\r
1288                 }\r
1289                 break;\r
1290         }\r
1291         /* Copy the integer body */\r
1292         for(bp = buf, pend1 += add; p != pend1; p += add)\r
1293                 *bp++ = *p;\r
1294 \r
1295         if(st->buf) FREEMEM(st->buf);\r
1296         st->buf = buf;\r
1297         st->size = bp - buf;\r
1298 \r
1299         return 0;\r
1300 }\r
1301 \r
1302 int\r
1303 asn_INTEGER2long(const INTEGER_t *iptr, long *l) {\r
1304     intmax_t v;\r
1305     if(asn_INTEGER2imax(iptr, &v) == 0) {\r
1306         if(v < LONG_MIN || v > LONG_MAX) {\r
1307             errno = ERANGE;\r
1308             return -1;\r
1309         }\r
1310         *l = v;\r
1311         return 0;\r
1312     } else {\r
1313         return -1;\r
1314     }\r
1315 }\r
1316 \r
1317 int\r
1318 asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *l) {\r
1319     uintmax_t v;\r
1320     if(asn_INTEGER2umax(iptr, &v) == 0) {\r
1321         if(v > ULONG_MAX) {\r
1322             errno = ERANGE;\r
1323             return -1;\r
1324         }\r
1325         *l = v;\r
1326         return 0;\r
1327     } else {\r
1328         return -1;\r
1329     }\r
1330 }\r
1331 \r
1332 int\r
1333 asn_long2INTEGER(INTEGER_t *st, long value) {\r
1334     return asn_imax2INTEGER(st, value);\r
1335 }\r
1336 \r
1337 int\r
1338 asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {\r
1339     return asn_imax2INTEGER(st, value);\r
1340 }\r
1341 \r
1342 \r
1343 int\r
1344 asn_uint642INTEGER(INTEGER_t *st, uint64_t value) {\r
1345         uint8_t *buf;\r
1346         uint8_t *end;\r
1347         uint8_t *b;\r
1348         int shr;\r
1349 \r
1350         if(value <= INT64_MAX)\r
1351                 return asn_int642INTEGER(st, value);\r
1352 \r
1353         buf = (uint8_t *)MALLOC(1 + sizeof(value));\r
1354         if(!buf) return -1;\r
1355 \r
1356         end = buf + (sizeof(value) + 1);\r
1357         buf[0] = 0;\r
1358         for(b = buf + 1, shr = (sizeof(value)-1)*8; b < end; shr -= 8, b++)\r
1359                 *b = (uint8_t)(value >> shr);\r
1360 \r
1361         if(st->buf) FREEMEM(st->buf);\r
1362         st->buf = buf;\r
1363         st->size = 1 + sizeof(value);\r
1364 \r
1365         return 0;\r
1366 }\r
1367 \r
1368 int\r
1369 asn_int642INTEGER(INTEGER_t *st, int64_t value) {\r
1370         uint8_t *buf, *bp;\r
1371         uint8_t *p;\r
1372         uint8_t *pstart;\r
1373         uint8_t *pend1;\r
1374         int littleEndian = 1;   /* Run-time detection */\r
1375         int add;\r
1376 \r
1377         if(!st) {\r
1378                 errno = EINVAL;\r
1379                 return -1;\r
1380         }\r
1381 \r
1382         buf = (uint8_t *)MALLOC(sizeof(value));\r
1383         if(!buf) return -1;\r
1384 \r
1385         if(*(char *)&littleEndian) {\r
1386                 pstart = (uint8_t *)&value + sizeof(value) - 1;\r
1387                 pend1 = (uint8_t *)&value;\r
1388                 add = -1;\r
1389         } else {\r
1390                 pstart = (uint8_t *)&value;\r
1391                 pend1 = pstart + sizeof(value) - 1;\r
1392                 add = 1;\r
1393         }\r
1394 \r
1395         /*\r
1396          * If the contents octet consists of more than one octet,\r
1397          * then bits of the first octet and bit 8 of the second octet:\r
1398          * a) shall not all be ones; and\r
1399          * b) shall not all be zero.\r
1400          */\r
1401         for(p = pstart; p != pend1; p += add) {\r
1402                 switch(*p) {\r
1403                 case 0x00: if((*(p+add) & 0x80) == 0)\r
1404                                 continue;\r
1405                         break;\r
1406                 case 0xff: if((*(p+add) & 0x80))\r
1407                                 continue;\r
1408                         break;\r
1409                 }\r
1410                 break;\r
1411         }\r
1412         /* Copy the integer body */\r
1413         for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)\r
1414                 *bp++ = *p;\r
1415 \r
1416         if(st->buf) FREEMEM(st->buf);\r
1417         st->buf = buf;\r
1418         st->size = bp - buf;\r
1419 \r
1420         return 0;\r
1421 }\r
1422 \r
1423 /*\r
1424  * Parse the number in the given string until the given *end position,\r
1425  * returning the position after the last parsed character back using the\r
1426  * same (*end) pointer.\r
1427  * WARNING: This behavior is different from the standard strtol/strtoimax(3).\r
1428  */\r
1429 enum asn_strtox_result_e\r
1430 asn_strtoimax_lim(const char *str, const char **end, intmax_t *intp) {\r
1431         int sign = 1;\r
1432         intmax_t value;\r
1433 \r
1434 #define ASN1_INTMAX_MAX ((~(uintmax_t)0) >> 1)\r
1435     const intmax_t upper_boundary = ASN1_INTMAX_MAX / 10;\r
1436         intmax_t last_digit_max = ASN1_INTMAX_MAX % 10;\r
1437 #undef  ASN1_INTMAX_MAX\r
1438 \r
1439         if(str >= *end) return ASN_STRTOX_ERROR_INVAL;\r
1440 \r
1441         switch(*str) {\r
1442         case '-':\r
1443                 last_digit_max++;\r
1444                 sign = -1;\r
1445                 /* FALL THROUGH */\r
1446         case '+':\r
1447                 str++;\r
1448                 if(str >= *end) {\r
1449                         *end = str;\r
1450                         return ASN_STRTOX_EXPECT_MORE;\r
1451                 }\r
1452         }\r
1453 \r
1454         for(value = 0; str < (*end); str++) {\r
1455                 switch(*str) {\r
1456                 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:\r
1457                 case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: {\r
1458                         int d = *str - '0';\r
1459                         if(value < upper_boundary) {\r
1460                                 value = value * 10 + d;\r
1461                         } else if(value == upper_boundary) {\r
1462                                 if(d <= last_digit_max) {\r
1463                                         if(sign > 0) {\r
1464                                                 value = value * 10 + d;\r
1465                                         } else {\r
1466                                                 sign = 1;\r
1467                                                 value = -value * 10 - d;\r
1468                                         }\r
1469                                 } else {\r
1470                                         *end = str;\r
1471                                         return ASN_STRTOX_ERROR_RANGE;\r
1472                                 }\r
1473                         } else {\r
1474                                 *end = str;\r
1475                                 return ASN_STRTOX_ERROR_RANGE;\r
1476                         }\r
1477                     }\r
1478                     continue;\r
1479                 default:\r
1480                     *end = str;\r
1481                     *intp = sign * value;\r
1482                     return ASN_STRTOX_EXTRA_DATA;\r
1483                 }\r
1484         }\r
1485 \r
1486         *end = str;\r
1487         *intp = sign * value;\r
1488         return ASN_STRTOX_OK;\r
1489 }\r
1490 \r
1491 /*\r
1492  * Parse the number in the given string until the given *end position,\r
1493  * returning the position after the last parsed character back using the\r
1494  * same (*end) pointer.\r
1495  * WARNING: This behavior is different from the standard strtoul/strtoumax(3).\r
1496  */\r
1497 enum asn_strtox_result_e\r
1498 asn_strtoumax_lim(const char *str, const char **end, uintmax_t *uintp) {\r
1499         uintmax_t value;\r
1500 \r
1501 #define ASN1_UINTMAX_MAX ((~(uintmax_t)0))\r
1502     const uintmax_t upper_boundary = ASN1_UINTMAX_MAX / 10;\r
1503     uintmax_t last_digit_max = ASN1_UINTMAX_MAX % 10;\r
1504 #undef ASN1_UINTMAX_MAX\r
1505 \r
1506     if(str >= *end) return ASN_STRTOX_ERROR_INVAL;\r
1507 \r
1508         switch(*str) {\r
1509         case '-':\r
1510         return ASN_STRTOX_ERROR_INVAL;\r
1511         case '+':\r
1512                 str++;\r
1513                 if(str >= *end) {\r
1514                         *end = str;\r
1515                         return ASN_STRTOX_EXPECT_MORE;\r
1516                 }\r
1517         }\r
1518 \r
1519         for(value = 0; str < (*end); str++) {\r
1520                 switch(*str) {\r
1521                 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:\r
1522                 case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: {\r
1523                         unsigned int d = *str - '0';\r
1524                         if(value < upper_boundary) {\r
1525                                 value = value * 10 + d;\r
1526                         } else if(value == upper_boundary) {\r
1527                                 if(d <= last_digit_max) {\r
1528                     value = value * 10 + d;\r
1529                 } else {\r
1530                                         *end = str;\r
1531                                         return ASN_STRTOX_ERROR_RANGE;\r
1532                                 }\r
1533                         } else {\r
1534                                 *end = str;\r
1535                                 return ASN_STRTOX_ERROR_RANGE;\r
1536                         }\r
1537                     }\r
1538                     continue;\r
1539                 default:\r
1540                     *end = str;\r
1541                     *uintp = value;\r
1542                     return ASN_STRTOX_EXTRA_DATA;\r
1543                 }\r
1544         }\r
1545 \r
1546         *end = str;\r
1547         *uintp = value;\r
1548         return ASN_STRTOX_OK;\r
1549 }\r
1550 \r
1551 enum asn_strtox_result_e\r
1552 asn_strtol_lim(const char *str, const char **end, long *lp) {\r
1553     intmax_t value;\r
1554     switch(asn_strtoimax_lim(str, end, &value)) {\r
1555     case ASN_STRTOX_ERROR_RANGE:\r
1556         return ASN_STRTOX_ERROR_RANGE;\r
1557     case ASN_STRTOX_ERROR_INVAL:\r
1558         return ASN_STRTOX_ERROR_INVAL;\r
1559     case ASN_STRTOX_EXPECT_MORE:\r
1560         return ASN_STRTOX_EXPECT_MORE;\r
1561     case ASN_STRTOX_OK:\r
1562         if(value >= LONG_MIN && value <= LONG_MAX) {\r
1563             *lp = value;\r
1564             return ASN_STRTOX_OK;\r
1565         } else {\r
1566             return ASN_STRTOX_ERROR_RANGE;\r
1567         }\r
1568     case ASN_STRTOX_EXTRA_DATA:\r
1569         if(value >= LONG_MIN && value <= LONG_MAX) {\r
1570             *lp = value;\r
1571             return ASN_STRTOX_EXTRA_DATA;\r
1572         } else {\r
1573             return ASN_STRTOX_ERROR_RANGE;\r
1574         }\r
1575     }\r
1576 \r
1577     assert(!"Unreachable");\r
1578     return ASN_STRTOX_ERROR_INVAL;\r
1579 }\r
1580 \r
1581 enum asn_strtox_result_e\r
1582 asn_strtoul_lim(const char *str, const char **end, unsigned long *ulp) {\r
1583     uintmax_t value;\r
1584     switch(asn_strtoumax_lim(str, end, &value)) {\r
1585     case ASN_STRTOX_ERROR_RANGE:\r
1586         return ASN_STRTOX_ERROR_RANGE;\r
1587     case ASN_STRTOX_ERROR_INVAL:\r
1588         return ASN_STRTOX_ERROR_INVAL;\r
1589     case ASN_STRTOX_EXPECT_MORE:\r
1590         return ASN_STRTOX_EXPECT_MORE;\r
1591     case ASN_STRTOX_OK:\r
1592         if(value <= ULONG_MAX) {\r
1593             *ulp = value;\r
1594             return ASN_STRTOX_OK;\r
1595         } else {\r
1596             return ASN_STRTOX_ERROR_RANGE;\r
1597         }\r
1598     case ASN_STRTOX_EXTRA_DATA:\r
1599         if(value <= ULONG_MAX) {\r
1600             *ulp = value;\r
1601             return ASN_STRTOX_EXTRA_DATA;\r
1602         } else {\r
1603             return ASN_STRTOX_ERROR_RANGE;\r
1604         }\r
1605     }\r
1606 \r
1607     assert(!"Unreachable");\r
1608     return ASN_STRTOX_ERROR_INVAL;\r
1609 }\r
1610 \r
1611 int\r
1612 INTEGER_compare(const asn_TYPE_descriptor_t *td, const void *aptr,\r
1613                      const void *bptr) {\r
1614     const INTEGER_t *a = aptr;\r
1615     const INTEGER_t *b = bptr;\r
1616 \r
1617     (void)td;\r
1618 \r
1619     if(a && b) {\r
1620         if(a->size && b->size) {\r
1621             int sign_a = (a->buf[0] & 0x80) ? -1 : 1;\r
1622             int sign_b = (b->buf[0] & 0x80) ? -1 : 1;\r
1623 \r
1624             if(sign_a < sign_b) return -1;\r
1625             if(sign_a > sign_b) return 1;\r
1626 \r
1627             /* The shortest integer wins, unless comparing negatives */\r
1628             if(a->size < b->size) {\r
1629                 return -1 * sign_a;\r
1630             } else if(a->size > b->size) {\r
1631                 return 1 * sign_b;\r
1632             }\r
1633 \r
1634             return sign_a * memcmp(a->buf, b->buf, a->size);\r
1635         } else if(a->size) {\r
1636             int sign = (a->buf[0] & 0x80) ? -1 : 1;\r
1637             return (1) * sign;\r
1638         } else if(b->size) {\r
1639             int sign = (a->buf[0] & 0x80) ? -1 : 1;\r
1640             return (-1) * sign;\r
1641         } else {\r
1642             return 0;\r
1643         }\r
1644     } else if(!a && !b) {\r
1645         return 0;\r
1646     } else if(!a) {\r
1647         return -1;\r
1648     } else {\r
1649         return 1;\r
1650     }\r
1651 \r
1652 }\r
1653 \r
1654 asn_random_fill_result_t\r
1655 INTEGER_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,\r
1656                     const asn_encoding_constraints_t *constraints,\r
1657                     size_t max_length) {\r
1658     const asn_INTEGER_specifics_t *specs =\r
1659         (const asn_INTEGER_specifics_t *)td->specifics;\r
1660     asn_random_fill_result_t result_ok = {ARFILL_OK, 1};\r
1661     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};\r
1662     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};\r
1663     INTEGER_t *st = *sptr;\r
1664     const asn_INTEGER_enum_map_t *emap;\r
1665     size_t emap_len;\r
1666     intmax_t value;\r
1667     int find_inside_map;\r
1668 \r
1669     if(max_length == 0) return result_skipped;\r
1670 \r
1671     if(st == NULL) {\r
1672         st = (INTEGER_t *)CALLOC(1, sizeof(*st));\r
1673         if(st == NULL) {\r
1674             return result_failed;\r
1675         }\r
1676     }\r
1677 \r
1678     if(specs) {\r
1679         emap = specs->value2enum;\r
1680         emap_len = specs->map_count;\r
1681         if(specs->strict_enumeration) {\r
1682             find_inside_map = emap_len > 0;\r
1683         } else {\r
1684             find_inside_map = emap_len ? asn_random_between(0, 1) : 0;\r
1685         }\r
1686     } else {\r
1687         emap = 0;\r
1688         emap_len = 0;\r
1689         find_inside_map = 0;\r
1690     }\r
1691 \r
1692     if(find_inside_map) {\r
1693         assert(emap_len > 0);\r
1694         value = emap[asn_random_between(0, emap_len - 1)].nat_value;\r
1695     } else {\r
1696         const asn_per_constraints_t *ct;\r
1697 \r
1698         static const long variants[] = {\r
1699             -65536, -65535, -65534, -32769, -32768, -32767, -16385, -16384,\r
1700             -16383, -257,   -256,   -255,   -254,   -129,   -128,   -127,\r
1701             -126,   -1,     0,      1,      126,    127,    128,    129,\r
1702             254,    255,    256,    257,    16383,  16384,  16385,  32767,\r
1703             32768,  32769,  65534,  65535,  65536,  65537};\r
1704         if(specs && specs->field_unsigned) {\r
1705             assert(variants[18] == 0);\r
1706             value = variants[asn_random_between(\r
1707                 18, sizeof(variants) / sizeof(variants[0]) - 1)];\r
1708         } else {\r
1709             value = variants[asn_random_between(\r
1710                 0, sizeof(variants) / sizeof(variants[0]) - 1)];\r
1711         }\r
1712 \r
1713         if(!constraints) constraints = &td->encoding_constraints;\r
1714         ct = constraints ? constraints->per_constraints : 0;\r
1715         if(ct && (ct->value.flags & APC_CONSTRAINED)) {\r
1716             if(value < ct->value.lower_bound || value > ct->value.upper_bound) {\r
1717                 value = asn_random_between(ct->value.lower_bound,\r
1718                                            ct->value.upper_bound);\r
1719             }\r
1720         }\r
1721     }\r
1722 \r
1723     if(asn_imax2INTEGER(st, value)) {\r
1724         if(st == *sptr) {\r
1725             ASN_STRUCT_RESET(*td, st);\r
1726         } else {\r
1727             ASN_STRUCT_FREE(*td, st);\r
1728         }\r
1729         return result_failed;\r
1730     } else {\r
1731         *sptr = st;\r
1732         result_ok.length = st->size;\r
1733         return result_ok;\r
1734     }\r
1735 }\r