SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / aper_support.c
1 /*
2  * Copyright (c) 2005-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
3  * Redistribution and modifications are permitted subject to BSD license.
4  */
5 #include <asn_system.h>
6 #include <asn_internal.h>
7 #include <aper_support.h>
8
9 int32_t
10 aper_get_align(asn_per_data_t *pd) {
11
12         if(pd->nboff & 0x7) {
13                 ASN_DEBUG("Aligning %ld bits", 8 - ((unsigned long)pd->nboff & 0x7));
14                 return per_get_few_bits(pd, 8 - (pd->nboff & 0x7));
15         }
16         return 0;
17 }
18
19 ssize_t
20 aper_get_length(asn_per_data_t *pd, ssize_t lb, ssize_t ub,
21                 int ebits, int *repeat) {
22         int constrained = (lb >= 0) && (ub >= 0);
23         ssize_t value;
24
25         *repeat = 0;
26
27         if (constrained && ub < 65536) {
28                 int range = ub - lb + 1;
29                 return aper_get_nsnnwn(pd, range);
30         }
31
32         if (aper_get_align(pd) < 0)
33                 return -1;
34
35         if(ebits >= 0) return per_get_few_bits(pd, ebits);
36
37         value = per_get_few_bits(pd, 8);
38         if(value < 0) return -1;
39         if((value & 128) == 0)  /* #11.9.3.6 */
40                 return (value & 0x7F);
41         if((value & 64) == 0) { /* #11.9.3.7 */
42                 value = ((value & 63) << 8) | per_get_few_bits(pd, 8);
43                 if(value < 0) return -1;
44                 return value;
45         }
46         value &= 63;    /* this is "m" from X.691, #11.9.3.8 */
47         if(value < 1 || value > 4)
48                 return -1;
49         *repeat = 1;
50         return (16384 * value);
51 }
52
53 ssize_t
54 aper_get_nslength(asn_per_data_t *pd) {
55         ssize_t length;
56
57         ASN_DEBUG("Getting normally small length");
58
59         if(per_get_few_bits(pd, 1) == 0) {
60                 length = per_get_few_bits(pd, 6) + 1;
61                 if(length <= 0) return -1;
62                 ASN_DEBUG("l=%zd", length);
63                 return length;
64         } else {
65                 int repeat;
66                 length = aper_get_length(pd, -1, -1, -1, &repeat);
67                 if(length >= 0 && !repeat) return length;
68                 return -1; /* Error, or do not support >16K extensions */
69         }
70 }
71
72 ssize_t
73 aper_get_nsnnwn(asn_per_data_t *pd, int range) {
74         ssize_t value;
75         int bytes = 0;
76
77         ASN_DEBUG("getting nsnnwn with range %d", range);
78
79         if(range <= 255) {
80                 int i;
81
82                 if (range < 0) return -1;
83                 /* 1 -> 8 bits */
84                 for (i = 1; i <= 8; i++) {
85                         int upper = 1 << i;
86                         if (upper >= range)
87                                 break;
88                 }
89                 value = per_get_few_bits(pd, i);
90                 return value;
91         } else if (range == 256){
92                 /* 1 byte */
93                 bytes = 1;
94         } else if (range <= 65536) {
95                 /* 2 bytes */
96                 bytes = 2;
97         } else {
98                 //return -1;
99                 int length;
100
101                 /* handle indefinite range */
102                 length = per_get_few_bits(pd, 1);
103                 if (length == 0)
104                         return per_get_few_bits(pd, 6);
105
106                 if (aper_get_align(pd) < 0)
107                         return -1;
108
109                 length = per_get_few_bits(pd, 8);
110                 /* the length is not likely to be that big */
111                 if (length > 4)
112                         return -1;
113                 value = 0;
114                 if (per_get_many_bits(pd, (uint8_t *)&value, 0, length * 8) < 0)
115                         return -1;
116                 return value;
117         }
118         if (aper_get_align(pd) < 0)
119                 return -1;
120         value = per_get_few_bits(pd, 8 * bytes);
121         return value;
122 }
123
124 int aper_put_align(asn_per_outp_t *po) {
125
126         if(po->nboff & 0x7) {
127                 ASN_DEBUG("Aligning %ld bits", 8 - ((unsigned long)po->nboff & 0x7));
128                 if(per_put_few_bits(po, 0x00, (8 - (po->nboff & 0x7))))
129                         return -1;
130         }
131         return 0;
132 }
133
134 ssize_t
135 aper_put_length(asn_per_outp_t *po, ssize_t lb, ssize_t ub, size_t n, int *need_eom) {
136         int constrained = (lb >= 0) && (ub >= 0);
137         int dummy = 0;
138         if(!need_eom) need_eom = &dummy;
139
140         *need_eom = 0;
141
142
143         ASN_DEBUG("APER put length %zu with range (%zd..%zd)", n, lb, ub);
144
145         /* 11.9 X.691 Note 2 */
146         if (constrained && ub < 65536) {
147                 int range = ub - lb + 1;
148                 return aper_put_nsnnwn(po, range, n) ? -1 : (ssize_t)n;
149         }
150
151         if (aper_put_align(po) < 0)
152                 return -1;
153
154         if(n <= 127) { /* #11.9.3.6 */
155                 return per_put_few_bits(po, n, 8)
156                 ? -1 : (ssize_t)n;
157         }
158         else if(n < 16384) /* #11.9.3.7 */
159                 return per_put_few_bits(po, n|0x8000, 16)
160                 ? -1 : (ssize_t)n;
161
162         *need_eom = 0 == (n & 16383);
163         n >>= 14;
164         if(n > 4) {
165                 *need_eom = 0;
166                 n = 4;
167         }
168
169         return per_put_few_bits(po, 0xC0 | n, 8)
170         ? -1 : (ssize_t)(n << 14);
171 }
172
173
174 int
175 aper_put_nslength(asn_per_outp_t *po, size_t length) {
176
177         if(length <= 64) {
178                 /* #11.9.3.4 */
179                 if(length == 0) return -1;
180                 return per_put_few_bits(po, length-1, 7) ? -1 : 0;
181         } else {
182                 if(aper_put_length(po, -1, -1, length, NULL) != (ssize_t)length) {
183                         /* This might happen in case of >16K extensions */
184                         return -1;
185                 }
186         }
187
188         return 0;
189 }
190
191 int
192 aper_put_nsnnwn(asn_per_outp_t *po, int range, int number) {
193         int bytes;
194
195         ASN_DEBUG("aper put nsnnwn %d with range %d", number, range);
196         /* 10.5.7.1 X.691 */
197         if(range < 0) {
198                 int i;
199                 for (i = 1; ; i++) {
200                         int bits = 1 << (8 * i);
201                         if (number <= bits)
202                                 break;
203                 }
204                 bytes = i;
205                 assert(i <= 4);
206         }
207         if(range <= 255) {
208                 int i;
209                 for (i = 1; i <= 8; i++) {
210                         int bits = 1 << i;
211                         if (range <= bits)
212                                 break;
213                 }
214                 return per_put_few_bits(po, number, i);
215         } else if(range == 256) {
216                 if (number >= range)
217                         return -1;
218                 bytes = 1;
219         } else if(range <= 65536) {
220                 if (number >= range)
221                         return -1;
222                 bytes = 2;
223         } else { /* Ranges > 64K */
224                 int i;
225                 for (i = 1; ; i++) {
226                         int bits = 1 << (8 * i);
227                         if (range <= bits)
228                                 break;
229                 }
230                 assert(i <= 4);
231                 bytes = i;
232         }
233         if(aper_put_align(po) < 0) /* Aligning on octet */
234                 return -1;
235 /*      if(per_put_few_bits(po, bytes, 8))
236                 return -1;
237 */
238         return per_put_few_bits(po, number, 8 * bytes);
239 }