SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / OCTET_STRING.c
1 /*-
2  * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
3  * All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <OCTET_STRING.h>
8 #include <errno.h>
9
10 /*
11  * OCTET STRING basic type description.
12  */
13 static const ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = {
14     (ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
15 };
16 asn_OCTET_STRING_specifics_t asn_SPC_OCTET_STRING_specs = {
17     sizeof(OCTET_STRING_t),
18     offsetof(OCTET_STRING_t, _asn_ctx),
19     ASN_OSUBV_STR
20 };
21 asn_TYPE_operation_t asn_OP_OCTET_STRING = {
22     OCTET_STRING_free,
23 #if !defined(ASN_DISABLE_PRINT_SUPPORT)
24     OCTET_STRING_print,  /* OCTET STRING generally means a non-ascii sequence */
25 #else
26     0,
27 #endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
28     OCTET_STRING_compare,
29 #if !defined(ASN_DISABLE_BER_SUPPORT)
30     OCTET_STRING_decode_ber,
31     OCTET_STRING_encode_der,
32 #else
33     0,
34     0,
35 #endif  /* !defined(ASN_DISABLE_BER_SUPPORT) */
36 #if !defined(ASN_DISABLE_XER_SUPPORT)
37     OCTET_STRING_decode_xer_hex,
38     OCTET_STRING_encode_xer,
39 #else
40     0,
41     0,
42 #endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
43 #if !defined(ASN_DISABLE_JER_SUPPORT)
44     OCTET_STRING_encode_jer,
45 #else
46     0,
47 #endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
48 #if !defined(ASN_DISABLE_OER_SUPPORT)
49     OCTET_STRING_decode_oer,
50     OCTET_STRING_encode_oer,
51 #else
52     0,
53     0,
54 #endif  /* !defined(ASN_DISABLE_OER_SUPPORT) */
55 #if !defined(ASN_DISABLE_UPER_SUPPORT)
56     OCTET_STRING_decode_uper,  /* Unaligned PER decoder */
57     OCTET_STRING_encode_uper,  /* Unaligned PER encoder */
58 #else
59     0,
60     0,
61 #endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) */
62 #if !defined(ASN_DISABLE_APER_SUPPORT)
63     OCTET_STRING_decode_aper,  /* Aligned PER decoder */
64     OCTET_STRING_encode_aper,  /* Aligned PER encoder */
65 #else
66     0,
67     0,
68 #endif  /* !defined(ASN_DISABLE_APER_SUPPORT) */
69 #if !defined(ASN_DISABLE_RFILL_SUPPORT)
70     OCTET_STRING_random_fill,
71 #else
72     0,
73 #endif  /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
74     0  /* Use generic outmost tag fetcher */
75 };
76 asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
77     "OCTET STRING",  /* Canonical name */
78     "OCTET_STRING",  /* XML tag name */
79     &asn_OP_OCTET_STRING,
80     asn_DEF_OCTET_STRING_tags,
81     sizeof(asn_DEF_OCTET_STRING_tags)
82         / sizeof(asn_DEF_OCTET_STRING_tags[0]),
83     asn_DEF_OCTET_STRING_tags,  /* Same as above */
84     sizeof(asn_DEF_OCTET_STRING_tags)
85         / sizeof(asn_DEF_OCTET_STRING_tags[0]),
86     {
87 #if !defined(ASN_DISABLE_OER_SUPPORT)
88         0,
89 #endif  /* !defined(ASN_DISABLE_OER_SUPPORT) */
90 #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
91         0,
92 #endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
93         asn_generic_no_constraint
94     },
95     0, 0,  /* No members */
96     &asn_SPC_OCTET_STRING_specs
97 };
98
99 void
100 OCTET_STRING_free(const asn_TYPE_descriptor_t *td, void *sptr,
101                   enum asn_struct_free_method method) {
102         OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
103
104         if(!td || !st)
105                 return;
106
107         ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
108
109         if(st->buf) {
110                 FREEMEM(st->buf);
111                 st->buf = 0;
112         }
113
114 #if !defined(ASN_DISABLE_BER_SUPPORT)
115     const asn_OCTET_STRING_specifics_t *specs;
116     asn_struct_ctx_t *ctx;
117
118     specs = td->specifics
119             ? (const asn_OCTET_STRING_specifics_t *)td->specifics
120             : &asn_SPC_OCTET_STRING_specs;
121     ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
122
123     /*
124      * Remove decode-time stack.
125      */
126     struct _stack *stck;
127     stck = (struct _stack *)ctx->ptr;
128     if(stck) {
129         while(stck->tail) {
130             struct _stack_el *sel = stck->tail;
131             stck->tail = sel->prev;
132             FREEMEM(sel);
133         }
134         FREEMEM(stck);
135     }
136 #endif  /* !defined(ASN_DISABLE_BER_SUPPORT) */
137
138     switch(method) {
139     case ASFM_FREE_EVERYTHING:
140         FREEMEM(sptr);
141         break;
142     case ASFM_FREE_UNDERLYING:
143         break;
144     case ASFM_FREE_UNDERLYING_AND_RESET:
145         memset(sptr, 0,
146                td->specifics
147                    ? ((const asn_OCTET_STRING_specifics_t *)(td->specifics))
148                          ->struct_size
149                    : sizeof(OCTET_STRING_t));
150         break;
151     }
152 }
153
154 /*
155  * Conversion routines.
156  */
157 int
158 OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) {
159         void *buf;
160
161         if(st == 0 || (str == 0 && len)) {
162                 errno = EINVAL;
163                 return -1;
164         }
165
166         /*
167          * Clear the OCTET STRING.
168          */
169         if(str == NULL) {
170                 FREEMEM(st->buf);
171                 st->buf = 0;
172                 st->size = 0;
173                 return 0;
174         }
175
176         /* Determine the original string size, if not explicitly given */
177         if(len < 0)
178                 len = strlen(str);
179
180         /* Allocate and fill the memory */
181         buf = MALLOC(len + 1);
182         if(buf == NULL)
183                 return -1;
184
185         memcpy(buf, str, len);
186         ((uint8_t *)buf)[len] = '\0';   /* Couldn't use memcpy(len+1)! */
187         FREEMEM(st->buf);
188         st->buf = (uint8_t *)buf;
189         st->size = len;
190
191         return 0;
192 }
193
194 OCTET_STRING_t *
195 OCTET_STRING_new_fromBuf(const asn_TYPE_descriptor_t *td, const char *str,
196                          int len) {
197     const asn_OCTET_STRING_specifics_t *specs =
198         td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
199                       : &asn_SPC_OCTET_STRING_specs;
200     OCTET_STRING_t *st;
201
202         st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
203         if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
204                 FREEMEM(st);
205                 st = NULL;
206         }
207
208         return st;
209 }
210
211 /*
212  * Lexicographically compare the common prefix of both strings,
213  * and if it is the same return -1 for the smallest string.
214  */
215 int
216 OCTET_STRING_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
217                      const void *bptr) {
218     const asn_OCTET_STRING_specifics_t *specs = td->specifics;
219     const OCTET_STRING_t *a = aptr;
220     const OCTET_STRING_t *b = bptr;
221
222     (void)specs;
223     assert(!specs || specs->subvariant != ASN_OSUBV_BIT);
224
225     if(a && b) {
226         size_t common_prefix_size = a->size <= b->size ? a->size : b->size;
227         int ret = memcmp(a->buf, b->buf, common_prefix_size);
228         if(ret == 0) {
229             /* Figure out which string with equal prefixes is longer. */
230             if(a->size < b->size) {
231                 return -1;
232             } else if(a->size > b->size) {
233                 return 1;
234             } else {
235                 return 0;
236             }
237         } else {
238             return ret < 0 ? -1 : 1;
239         }
240     } else if(!a && !b) {
241         return 0;
242     } else if(!a) {
243         return -1;
244     } else {
245         return 1;
246     }
247
248 }
249
250 #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
251 int
252 OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
253                                 size_t units, unsigned int bpc, unsigned int unit_bits,
254                                 long lb, long ub, const asn_per_constraints_t *pc) {
255     uint8_t *end = buf + units * bpc;
256
257     ASN_DEBUG("Expanding %d characters into (%ld..%ld):%d",
258               (int)units, lb, ub, unit_bits);
259
260     /* X.691: 27.5.4 */
261     if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
262         /* Decode without translation */
263         lb = 0;
264     } else if(pc && pc->code2value) {
265         if(unit_bits > 16)
266             return 1;  /* FATAL: can't have constrained
267                         * UniversalString with more than
268                         * 16 million code points */
269         for(; buf < end; buf += bpc) {
270             int value;
271             int code = per_get_few_bits(po, unit_bits);
272             if(code < 0) return -1;  /* WMORE */
273             value = pc->code2value(code);
274             if(value < 0) {
275                 ASN_DEBUG("Code %d (0x%02x) is"
276                           " not in map (%ld..%ld)",
277                           code, code, lb, ub);
278                 return 1;  /* FATAL */
279             }
280             switch(bpc) {
281             case 1: *buf = value; break;
282             case 2: buf[0] = value >> 8; buf[1] = value; break;
283             case 4: buf[0] = value >> 24; buf[1] = value >> 16;
284                 buf[2] = value >> 8; buf[3] = value; break;
285             }
286         }
287         return 0;
288     }
289
290     /* Shortcut the no-op copying to the aligned structure */
291     if(lb == 0 && (unit_bits == 8 * bpc)) {
292         return per_get_many_bits(po, buf, 0, unit_bits * units);
293     }
294
295     for(; buf < end; buf += bpc) {
296         int32_t code = per_get_few_bits(po, unit_bits);
297         int32_t ch = code + lb;
298         if(code < 0) return -1;  /* WMORE */
299         if(ch > ub) {
300             ASN_DEBUG("Code %d is out of range (%ld..%ld)",
301                       ch, lb, ub);
302             return 1;  /* FATAL */
303         }
304         switch(bpc) {
305         case 1: *buf = ch; break;
306         case 2: buf[0] = ch >> 8; buf[1] = ch; break;
307         case 4: buf[0] = ch >> 24; buf[1] = ch >> 16;
308             buf[2] = ch >> 8; buf[3] = ch; break;
309         }
310     }
311
312     return 0;
313 }
314
315 int
316 OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
317                                 size_t units, unsigned int bpc, unsigned int unit_bits,
318                                 long lb, long ub, const asn_per_constraints_t *pc) {
319     const uint8_t *end = buf + units * bpc;
320
321     ASN_DEBUG("Squeezing %d characters into (%ld..%ld):%d (%d bpc)",
322               (int)units, lb, ub, unit_bits, bpc);
323
324     /* X.691: 27.5.4 */
325     if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
326         /* Encode as is */
327         lb = 0;
328     } else if(pc && pc->value2code) {
329         for(; buf < end; buf += bpc) {
330             int code;
331             uint32_t value;
332             switch(bpc) {
333             case 1: value = *(const uint8_t *)buf; break;
334             case 2: value = (buf[0] << 8) | buf[1]; break;
335             case 4: value = (buf[0] << 24) | (buf[1] << 16)
336                 | (buf[2] << 8) | buf[3]; break;
337             default: return -1;
338             }
339             code = pc->value2code(value);
340             if(code < 0) {
341                 ASN_DEBUG("Character %d (0x%02x) is"
342                           " not in map (%ld..%ld)",
343                           *buf, *buf, lb, ub);
344                 return -1;
345             }
346             if(per_put_few_bits(po, code, unit_bits))
347     return -1;
348         }
349     }
350
351     /* Shortcut the no-op copying to the aligned structure */
352     if(lb == 0 && (unit_bits == 8 * bpc)) {
353         return per_put_many_bits(po, buf, unit_bits * units);
354     }
355
356     for(ub -= lb; buf < end; buf += bpc) {
357         int ch;
358         uint32_t value;
359         switch(bpc) {
360         case 1:
361             value = *(const uint8_t *)buf;
362             break;
363         case 2:
364             value = (buf[0] << 8) | buf[1];
365             break;
366         case 4:
367             value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
368             break;
369         default:
370             return -1;
371         }
372         ch = value - lb;
373         if(ch < 0 || ch > ub) {
374             ASN_DEBUG("Character %d (0x%02x) is out of range (%ld..%ld)", *buf,
375                       value, lb, ub + lb);
376             return -1;
377         }
378         if(per_put_few_bits(po, ch, unit_bits)) return -1;
379     }
380
381     return 0;
382 }
383 #endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */