Fix licensing issues
[ric-plt/resource-status-manager.git] / RSM / 3rdparty / asn1codec / e2ap_engine / NativeInteger.c
1
2 /*-
3  * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
4  * All rights reserved.
5  * Redistribution and modifications are permitted subject to BSD license.
6  */
7 /*
8  * Read the NativeInteger.h for the explanation wrt. differences between
9  * INTEGER and NativeInteger.
10  * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
11  * implementation deals with the standard (machine-specific) representation
12  * of them instead of using the platform-independent buffer.
13  */
14 #include <asn_internal.h>
15 #include <NativeInteger.h>
16
17 /*
18  * NativeInteger basic type description.
19  */
20 static const ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
21         (ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
22 };
23 asn_TYPE_operation_t asn_OP_NativeInteger = {
24         NativeInteger_free,
25         NativeInteger_print,
26         NativeInteger_compare,
27         NativeInteger_decode_ber,
28         NativeInteger_encode_der,
29         NativeInteger_decode_xer,
30         NativeInteger_encode_xer,
31 #ifdef  ASN_DISABLE_OER_SUPPORT
32         0,
33         0,
34 #else
35         NativeInteger_decode_oer,       /* OER decoder */
36         NativeInteger_encode_oer,       /* Canonical OER encoder */
37 #endif  /* ASN_DISABLE_OER_SUPPORT */
38 #ifdef  ASN_DISABLE_PER_SUPPORT
39         0,
40         0,
41         0,
42         0,
43 #else
44         NativeInteger_decode_uper,      /* Unaligned PER decoder */
45         NativeInteger_encode_uper,      /* Unaligned PER encoder */
46         NativeInteger_decode_aper,      /* Aligned PER decoder */
47         NativeInteger_encode_aper,      /* Aligned PER encoder */
48 #endif  /* ASN_DISABLE_PER_SUPPORT */
49         NativeInteger_random_fill,
50         0       /* Use generic outmost tag fetcher */
51 };
52 asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
53         "INTEGER",                      /* The ASN.1 type is still INTEGER */
54         "INTEGER",
55         &asn_OP_NativeInteger,
56         asn_DEF_NativeInteger_tags,
57         sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
58         asn_DEF_NativeInteger_tags,     /* Same as above */
59         sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
60         { 0, 0, asn_generic_no_constraint },
61         0, 0,   /* No members */
62         0       /* No specifics */
63 };
64
65 /*
66  * Decode INTEGER type.
67  */
68 asn_dec_rval_t
69 NativeInteger_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
70                          const asn_TYPE_descriptor_t *td, void **nint_ptr,
71                          const void *buf_ptr, size_t size, int tag_mode) {
72     const asn_INTEGER_specifics_t *specs =
73         (const asn_INTEGER_specifics_t *)td->specifics;
74     long *native = (long *)*nint_ptr;
75         asn_dec_rval_t rval;
76         ber_tlv_len_t length;
77
78         /*
79          * If the structure is not there, allocate it.
80          */
81         if(native == NULL) {
82                 native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
83                 if(native == NULL) {
84                         rval.code = RC_FAIL;
85                         rval.consumed = 0;
86                         return rval;
87                 }
88         }
89
90         ASN_DEBUG("Decoding %s as INTEGER (tm=%d)",
91                 td->name, tag_mode);
92
93         /*
94          * Check tags.
95          */
96         rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
97                         tag_mode, 0, &length, 0);
98         if(rval.code != RC_OK)
99                 return rval;
100
101         ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
102
103         /*
104          * Make sure we have this length.
105          */
106         buf_ptr = ((const char *)buf_ptr) + rval.consumed;
107         size -= rval.consumed;
108         if(length > (ber_tlv_len_t)size) {
109                 rval.code = RC_WMORE;
110                 rval.consumed = 0;
111                 return rval;
112         }
113
114         /*
115          * ASN.1 encoded INTEGER: buf_ptr, length
116          * Fill the native, at the same time checking for overflow.
117          * If overflow occured, return with RC_FAIL.
118          */
119         {
120                 INTEGER_t tmp;
121                 union {
122                         const void *constbuf;
123                         void *nonconstbuf;
124                 } unconst_buf;
125                 long l;
126
127                 unconst_buf.constbuf = buf_ptr;
128                 tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
129                 tmp.size = length;
130
131                 if((specs&&specs->field_unsigned)
132                         ? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */
133                         : asn_INTEGER2long(&tmp, &l)) {
134                         rval.code = RC_FAIL;
135                         rval.consumed = 0;
136                         return rval;
137                 }
138
139                 *native = l;
140         }
141
142         rval.code = RC_OK;
143         rval.consumed += length;
144
145         ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
146                 (long)rval.consumed, (long)length, td->name, (long)*native);
147
148         return rval;
149 }
150
151 /*
152  * Encode the NativeInteger using the standard INTEGER type DER encoder.
153  */
154 asn_enc_rval_t
155 NativeInteger_encode_der(const asn_TYPE_descriptor_t *sd, const void *ptr,
156                          int tag_mode, ber_tlv_tag_t tag,
157                          asn_app_consume_bytes_f *cb, void *app_key) {
158         unsigned long native = *(const unsigned long *)ptr; /* Disable sign ext. */
159         asn_enc_rval_t erval = {0,0,0};
160         INTEGER_t tmp;
161
162 #ifdef  WORDS_BIGENDIAN         /* Opportunistic optimization */
163
164         tmp.buf = (uint8_t *)&native;
165         tmp.size = sizeof(native);
166
167 #else   /* Works even if WORDS_BIGENDIAN is not set where should've been */
168         uint8_t buf[sizeof(native)];
169         uint8_t *p;
170
171         /* Prepare a fake INTEGER */
172         for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
173                 *p = (uint8_t)native;
174
175         tmp.buf = buf;
176         tmp.size = sizeof(buf);
177 #endif  /* WORDS_BIGENDIAN */
178         
179         /* Encode fake INTEGER */
180         erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key);
181     if(erval.structure_ptr == &tmp) {
182         erval.structure_ptr = ptr;
183     }
184         return erval;
185 }
186
187 /*
188  * Decode the chunk of XML text encoding INTEGER.
189  */
190 asn_dec_rval_t
191 NativeInteger_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
192                          const asn_TYPE_descriptor_t *td, void **sptr,
193                          const char *opt_mname, const void *buf_ptr,
194                          size_t size) {
195     const asn_INTEGER_specifics_t *specs =
196         (const asn_INTEGER_specifics_t *)td->specifics;
197     asn_dec_rval_t rval;
198         INTEGER_t st;
199         void *st_ptr = (void *)&st;
200         long *native = (long *)*sptr;
201
202         if(!native) {
203                 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
204                 if(!native) ASN__DECODE_FAILED;
205         }
206
207         memset(&st, 0, sizeof(st));
208         rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr, 
209                 opt_mname, buf_ptr, size);
210         if(rval.code == RC_OK) {
211                 long l;
212                 if((specs&&specs->field_unsigned)
213                         ? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
214                         : asn_INTEGER2long(&st, &l)) {
215                         rval.code = RC_FAIL;
216                         rval.consumed = 0;
217                 } else {
218                         *native = l;
219                 }
220         } else {
221                 /*
222                  * Cannot restart from the middle;
223                  * there is no place to save state in the native type.
224                  * Request a continuation from the very beginning.
225                  */
226                 rval.consumed = 0;
227         }
228         ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
229         return rval;
230 }
231
232
233 asn_enc_rval_t
234 NativeInteger_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
235                          int ilevel, enum xer_encoder_flags_e flags,
236                          asn_app_consume_bytes_f *cb, void *app_key) {
237     const asn_INTEGER_specifics_t *specs =
238         (const asn_INTEGER_specifics_t *)td->specifics;
239     char scratch[32];   /* Enough for 64-bit int */
240         asn_enc_rval_t er = {0,0,0};
241         const long *native = (const long *)sptr;
242
243         (void)ilevel;
244         (void)flags;
245
246         if(!native) ASN__ENCODE_FAILED;
247
248         er.encoded = snprintf(scratch, sizeof(scratch),
249                         (specs && specs->field_unsigned)
250                         ? "%lu" : "%ld", *native);
251         if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
252                 || cb(scratch, er.encoded, app_key) < 0)
253                 ASN__ENCODE_FAILED;
254
255         ASN__ENCODED_OK(er);
256 }
257
258 #ifndef  ASN_DISABLE_PER_SUPPORT
259
260 asn_dec_rval_t
261 NativeInteger_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
262                           const asn_TYPE_descriptor_t *td,
263                           const asn_per_constraints_t *constraints, void **sptr,
264                           asn_per_data_t *pd) {
265     const asn_INTEGER_specifics_t *specs =
266         (const asn_INTEGER_specifics_t *)td->specifics;
267     asn_dec_rval_t rval;
268         long *native = (long *)*sptr;
269         INTEGER_t tmpint;
270         void *tmpintptr = &tmpint;
271
272         (void)opt_codec_ctx;
273         ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name);
274
275         if(!native) {
276                 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
277                 if(!native) ASN__DECODE_FAILED;
278         }
279
280         memset(&tmpint, 0, sizeof tmpint);
281         rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints,
282                                    &tmpintptr, pd);
283         if(rval.code == RC_OK) {
284                 if((specs&&specs->field_unsigned)
285                         ? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
286                         : asn_INTEGER2long(&tmpint, native))
287                         rval.code = RC_FAIL;
288                 else
289                         ASN_DEBUG("NativeInteger %s got value %ld",
290                                 td->name, *native);
291         }
292         ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
293
294         return rval;
295 }
296
297 asn_enc_rval_t
298 NativeInteger_encode_uper(const asn_TYPE_descriptor_t *td,
299                           const asn_per_constraints_t *constraints,
300                           const void *sptr, asn_per_outp_t *po) {
301     const asn_INTEGER_specifics_t *specs =
302         (const asn_INTEGER_specifics_t *)td->specifics;
303     asn_enc_rval_t er = {0,0,0};
304         long native;
305         INTEGER_t tmpint;
306
307         if(!sptr) ASN__ENCODE_FAILED;
308
309     native = *(const long *)sptr;
310
311     ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native);
312
313         memset(&tmpint, 0, sizeof(tmpint));
314         if((specs&&specs->field_unsigned)
315                 ? asn_ulong2INTEGER(&tmpint, native)
316                 : asn_long2INTEGER(&tmpint, native))
317                 ASN__ENCODE_FAILED;
318         er = INTEGER_encode_uper(td, constraints, &tmpint, po);
319         ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
320         return er;
321 }
322
323 asn_dec_rval_t
324 NativeInteger_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
325                           const asn_TYPE_descriptor_t *td,
326                           const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
327
328         const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
329         asn_dec_rval_t rval;
330         long *native = (long *)*sptr;
331         INTEGER_t tmpint;
332         void *tmpintptr = &tmpint;
333
334         (void)opt_codec_ctx;
335         ASN_DEBUG("Decoding NativeInteger %s (APER)", td->name);
336
337         if(!native) {
338                 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
339                 if(!native) ASN__DECODE_FAILED;
340         }
341
342         memset(&tmpint, 0, sizeof tmpint);
343         rval = INTEGER_decode_aper(opt_codec_ctx, td, constraints,
344                                    &tmpintptr, pd);
345         if(rval.code == RC_OK) {
346                 if((specs&&specs->field_unsigned)
347                         ? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
348                         : asn_INTEGER2long(&tmpint, native))
349                         rval.code = RC_FAIL;
350                 else
351                         ASN_DEBUG("NativeInteger %s got value %ld",
352                                   td->name, *native);
353         }
354         ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
355
356         return rval;
357 }
358
359 asn_enc_rval_t
360 NativeInteger_encode_aper(const asn_TYPE_descriptor_t *td,
361                           const asn_per_constraints_t *constraints,
362                           const void *sptr, asn_per_outp_t *po) {
363
364         const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
365         asn_enc_rval_t er = {0,0,0};
366         long native;
367         INTEGER_t tmpint;
368
369         if(!sptr) ASN__ENCODE_FAILED;
370
371         native = *(const long *)sptr;
372
373         ASN_DEBUG("Encoding NativeInteger %s %ld (APER)", td->name, native);
374
375         memset(&tmpint, 0, sizeof(tmpint));
376         if((specs&&specs->field_unsigned)
377                 ? asn_ulong2INTEGER(&tmpint, (unsigned long)native)
378                 : asn_long2INTEGER(&tmpint, native))
379                 ASN__ENCODE_FAILED;
380         er = INTEGER_encode_aper(td, constraints, &tmpint, po);
381         ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
382         return er;
383 }
384
385 #endif  /* ASN_DISABLE_PER_SUPPORT */
386
387 /*
388  * INTEGER specific human-readable output.
389  */
390 int
391 NativeInteger_print(const asn_TYPE_descriptor_t *td, const void *sptr,
392                     int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
393     const asn_INTEGER_specifics_t *specs =
394         (const asn_INTEGER_specifics_t *)td->specifics;
395     const long *native = (const long *)sptr;
396     char scratch[32]; /* Enough for 64-bit int */
397     int ret;
398
399     (void)td;       /* Unused argument */
400     (void)ilevel;   /* Unused argument */
401
402     if(native) {
403         long value = *native;
404         ret = snprintf(scratch, sizeof(scratch),
405                        (specs && specs->field_unsigned) ? "%lu" : "%ld", value);
406         assert(ret > 0 && (size_t)ret < sizeof(scratch));
407         if(cb(scratch, ret, app_key) < 0) return -1;
408         if(specs && (value >= 0 || !specs->field_unsigned)) {
409             const asn_INTEGER_enum_map_t *el =
410                 INTEGER_map_value2enum(specs, value);
411             if(el) {
412                 if(cb(" (", 2, app_key) < 0) return -1;
413                 if(cb(el->enum_name, el->enum_len, app_key) < 0) return -1;
414                 if(cb(")", 1, app_key) < 0) return -1;
415             }
416         }
417         return 0;
418         } else {
419                 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
420         }
421 }
422
423 void
424 NativeInteger_free(const asn_TYPE_descriptor_t *td, void *ptr,
425                    enum asn_struct_free_method method) {
426     if(!td || !ptr)
427                 return;
428
429         ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)",
430                 td->name, method, ptr);
431
432     switch(method) {
433     case ASFM_FREE_EVERYTHING:
434         FREEMEM(ptr);
435         break;
436     case ASFM_FREE_UNDERLYING:
437         break;
438     case ASFM_FREE_UNDERLYING_AND_RESET:
439         memset(ptr, 0, sizeof(long));
440         break;
441     }
442 }
443
444 int
445 NativeInteger_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const void *bptr) {
446     (void)td;
447
448     if(aptr && bptr) {
449         const asn_INTEGER_specifics_t *specs =
450             (const asn_INTEGER_specifics_t *)td->specifics;
451         if(specs && specs->field_unsigned) {
452             const unsigned long *a = aptr;
453             const unsigned long *b = bptr;
454             if(*a < *b) {
455                 return -1;
456             } else if(*a > *b) {
457                 return 1;
458             } else {
459                 return 0;
460             }
461         } else {
462             const long *a = aptr;
463             const long *b = bptr;
464             if(*a < *b) {
465                 return -1;
466             } else if(*a > *b) {
467                 return 1;
468             } else {
469                 return 0;
470             }
471         }
472     } else if(!aptr) {
473         return -1;
474     } else {
475         return 1;
476     }
477 }
478
479 asn_random_fill_result_t
480 NativeInteger_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
481                           const asn_encoding_constraints_t *constraints,
482                           size_t max_length) {
483     const asn_INTEGER_specifics_t *specs =
484         (const asn_INTEGER_specifics_t *)td->specifics;
485     asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
486     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
487     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
488     long *st = *sptr;
489     const asn_INTEGER_enum_map_t *emap;
490     size_t emap_len;
491     intmax_t value;
492     int find_inside_map;
493
494     if(max_length == 0) return result_skipped;
495
496     if(st == NULL) {
497         st = (long *)CALLOC(1, sizeof(*st));
498         if(st == NULL) {
499             return result_failed;
500         }
501     }
502
503     if(specs) {
504         emap = specs->value2enum;
505         emap_len = specs->map_count;
506         if(specs->strict_enumeration) {
507             find_inside_map = emap_len > 0;
508         } else {
509             find_inside_map = emap_len ? asn_random_between(0, 1) : 0;
510         }
511     } else {
512         emap = 0;
513         emap_len = 0;
514         find_inside_map = 0;
515     }
516
517     if(find_inside_map) {
518         assert(emap_len > 0);
519         value = emap[asn_random_between(0, emap_len - 1)].nat_value;
520     } else {
521         const asn_per_constraints_t *ct;
522
523         static const long variants[] = {
524             -65536, -65535, -65534, -32769, -32768, -32767, -16385, -16384,
525             -16383, -257,   -256,   -255,   -254,   -129,   -128,   -127,
526             -126,   -1,     0,      1,      126,    127,    128,    129,
527             254,    255,    256,    257,    16383,  16384,  16385,  32767,
528             32768,  32769,  65534,  65535,  65536,  65537};
529         if(specs && specs->field_unsigned) {
530             assert(variants[18] == 0);
531             value = variants[asn_random_between(
532                 18, sizeof(variants) / sizeof(variants[0]) - 1)];
533         } else {
534             value = variants[asn_random_between(
535                 0, sizeof(variants) / sizeof(variants[0]) - 1)];
536         }
537
538         if(!constraints) constraints = &td->encoding_constraints;
539         ct = constraints ? constraints->per_constraints : 0;
540         if(ct && (ct->value.flags & APC_CONSTRAINED)) {
541             if(value < ct->value.lower_bound || value > ct->value.upper_bound) {
542                 value = asn_random_between(ct->value.lower_bound,
543                                            ct->value.upper_bound);
544             }
545         }
546     }
547
548     *sptr = st;
549     *st = value;
550     return result_ok;
551 }