55896bc5f11c5c1b39d19db819cd1fd4a36bd796
[ric-plt/resource-status-manager.git] / RSM / 3rdparty / asn1codec / e2ap_engine / per_encoder.c
1 /*
2  * Copyright 2019 AT&T Intellectual Property
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19  * platform project (RICP).
20  */
21
22
23 #include <asn_application.h>
24 #include <asn_internal.h>
25 #include <per_encoder.h>
26
27 static int _uper_encode_flush_outp(asn_per_outp_t *po);
28
29 static int
30 ignore_output(const void *data, size_t size, void *app_key) {
31     (void)data;
32     (void)size;
33     (void)app_key;
34     return 0;
35 }
36
37 asn_enc_rval_t
38 uper_encode(const asn_TYPE_descriptor_t *td,
39             const asn_per_constraints_t *constraints, const void *sptr,
40             asn_app_consume_bytes_f *cb, void *app_key) {
41     asn_per_outp_t po;
42     asn_enc_rval_t er = {0,0,0};
43
44     /*
45      * Invoke type-specific encoder.
46      */
47     if(!td || !td->op->uper_encoder)
48         ASN__ENCODE_FAILED;     /* PER is not compiled in */
49
50     po.buffer = po.tmpspace;
51     po.nboff = 0;
52     po.nbits = 8 * sizeof(po.tmpspace);
53     po.output = cb ? cb : ignore_output;
54     po.op_key = app_key;
55     po.flushed_bytes = 0;
56
57     er = td->op->uper_encoder(td, constraints, sptr, &po);
58     if(er.encoded != -1) {
59         size_t bits_to_flush;
60
61         bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;
62
63         /* Set number of bits encoded to a firm value */
64         er.encoded = (po.flushed_bytes << 3) + bits_to_flush;
65
66         if(_uper_encode_flush_outp(&po)) ASN__ENCODE_FAILED;
67     }
68
69     return er;
70 }
71
72 /*
73  * Argument type and callback necessary for uper_encode_to_buffer().
74  */
75 typedef struct enc_to_buf_arg {
76         void *buffer;
77         size_t left;
78 } enc_to_buf_arg;
79 static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
80         enc_to_buf_arg *arg = (enc_to_buf_arg *)key;
81
82         if(arg->left < size)
83                 return -1;      /* Data exceeds the available buffer size */
84
85         memcpy(arg->buffer, buffer, size);
86         arg->buffer = ((char *)arg->buffer) + size;
87         arg->left -= size;
88
89         return 0;
90 }
91
92 asn_enc_rval_t
93 uper_encode_to_buffer(const asn_TYPE_descriptor_t *td,
94                       const asn_per_constraints_t *constraints,
95                       const void *sptr, void *buffer, size_t buffer_size) {
96     enc_to_buf_arg key;
97
98     key.buffer = buffer;
99     key.left = buffer_size;
100
101     if(td) ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);
102
103     return uper_encode(td, constraints, sptr, encode_to_buffer_cb, &key);
104 }
105
106 typedef struct enc_dyn_arg {
107         void *buffer;
108         size_t length;
109         size_t allocated;
110 } enc_dyn_arg;
111 static int
112 encode_dyn_cb(const void *buffer, size_t size, void *key) {
113     enc_dyn_arg *arg = key;
114     if(arg->length + size >= arg->allocated) {
115         size_t new_size = arg->allocated ? arg->allocated : 8;
116         void *p;
117
118         do {
119             new_size <<= 2;
120         } while(arg->length + size >= new_size);
121
122         p = REALLOC(arg->buffer, new_size);
123         if(!p) {
124             FREEMEM(arg->buffer);
125             memset(arg, 0, sizeof(*arg));
126             return -1;
127         }
128         arg->buffer = p;
129         arg->allocated = new_size;
130     }
131     memcpy(((char *)arg->buffer) + arg->length, buffer, size);
132     arg->length += size;
133     return 0;
134 }
135 ssize_t
136 uper_encode_to_new_buffer(const asn_TYPE_descriptor_t *td,
137                           const asn_per_constraints_t *constraints,
138                           const void *sptr, void **buffer_r) {
139     asn_enc_rval_t er = {0,0,0};
140         enc_dyn_arg key;
141
142         memset(&key, 0, sizeof(key));
143
144         er = uper_encode(td, constraints, sptr, encode_dyn_cb, &key);
145         switch(er.encoded) {
146         case -1:
147                 FREEMEM(key.buffer);
148                 return -1;
149         case 0:
150                 FREEMEM(key.buffer);
151                 key.buffer = MALLOC(1);
152                 if(key.buffer) {
153                         *(char *)key.buffer = '\0';
154                         *buffer_r = key.buffer;
155                         return 1;
156                 } else {
157                         return -1;
158                 }
159         default:
160                 *buffer_r = key.buffer;
161                 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
162                 return ((er.encoded + 7) >> 3);
163         }
164 }
165
166 /*
167  * Internally useful functions.
168  */
169
170 /* Flush partially filled buffer */
171 static int
172 _uper_encode_flush_outp(asn_per_outp_t *po) {
173         uint8_t *buf;
174
175         if(po->nboff == 0 && po->buffer == po->tmpspace)
176                 return 0;
177
178         buf = po->buffer + (po->nboff >> 3);
179         /* Make sure we account for the last, partially filled */
180         if(po->nboff & 0x07) {
181                 buf[0] &= 0xff << (8 - (po->nboff & 0x07));
182                 buf++;
183         }
184
185         return po->output(po->tmpspace, buf - po->tmpspace, po->op_key);
186 }
187
188 asn_enc_rval_t
189 aper_encode_to_buffer(const asn_TYPE_descriptor_t *td,
190                       const asn_per_constraints_t *constraints,
191                       const void *sptr, void *buffer, size_t buffer_size) {
192     enc_to_buf_arg key;
193
194     key.buffer = buffer;
195     key.left = buffer_size;
196
197     if(td) ASN_DEBUG("Encoding \"%s\" using ALIGNED PER", td->name);
198
199     return aper_encode(td, constraints, sptr, encode_to_buffer_cb, &key);
200 }
201
202 ssize_t
203 aper_encode_to_new_buffer(const asn_TYPE_descriptor_t *td,
204                           const asn_per_constraints_t *constraints,
205                           const void *sptr, void **buffer_r) {
206     asn_enc_rval_t er = {0,0,0};
207         enc_dyn_arg key;
208
209         memset(&key, 0, sizeof(key));
210
211         er = aper_encode(td, constraints, sptr, encode_dyn_cb, &key);
212         switch(er.encoded) {
213         case -1:
214                 FREEMEM(key.buffer);
215                 return -1;
216         case 0:
217                 FREEMEM(key.buffer);
218                 key.buffer = MALLOC(1);
219                 if(key.buffer) {
220                         *(char *)key.buffer = '\0';
221                         *buffer_r = key.buffer;
222                         return 1;
223                 } else {
224                         return -1;
225                 }
226         default:
227                 *buffer_r = key.buffer;
228                 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
229                 return ((er.encoded + 7) >> 3);
230         }
231 }
232
233 static int
234 _aper_encode_flush_outp(asn_per_outp_t *po) {
235         uint8_t *buf;
236
237         if(po->nboff == 0 && po->buffer == po->tmpspace)
238                 return 0;
239
240         buf = po->buffer + (po->nboff >> 3);
241         /* Make sure we account for the last, partially filled */
242         if(po->nboff & 0x07) {
243                 buf[0] &= 0xff << (8 - (po->nboff & 0x07));
244                 buf++;
245         }
246
247         if (po->output) {
248                 return po->output(po->tmpspace, buf - po->tmpspace, po->op_key);
249         }
250         return 0;
251 }
252
253 asn_enc_rval_t
254 aper_encode(const asn_TYPE_descriptor_t *td,
255         const asn_per_constraints_t *constraints,
256         const void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
257         asn_per_outp_t po;
258         asn_enc_rval_t er = {0,0,0};
259
260         /*
261          * Invoke type-specific encoder.
262          */
263         if(!td || !td->op->aper_encoder)
264                 ASN__ENCODE_FAILED;      /* PER is not compiled in */
265
266         po.buffer = po.tmpspace;
267         po.nboff = 0;
268         po.nbits = 8 * sizeof(po.tmpspace);
269         po.output = cb;
270         po.op_key = app_key;
271         po.flushed_bytes = 0;
272
273         er = td->op->aper_encoder(td, constraints, sptr, &po);
274         if(er.encoded != -1) {
275                 size_t bits_to_flush;
276
277                 bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;
278
279                 /* Set number of bits encoded to a firm value */
280                 er.encoded = (po.flushed_bytes << 3) + bits_to_flush;
281
282                 if(_aper_encode_flush_outp(&po))
283                         ASN__ENCODE_FAILED;
284         }
285
286         return er;
287 }