Adding initial code jy.oak@samsung.com
[ric-app/kpimon.git] / asn1c_defs / all-defs / per_encoder.c
1 #include <asn_application.h>\r
2 #include <asn_internal.h>\r
3 #include <per_encoder.h>\r
4 \r
5 static int _uper_encode_flush_outp(asn_per_outp_t *po);\r
6 \r
7 static int\r
8 ignore_output(const void *data, size_t size, void *app_key) {\r
9     (void)data;\r
10     (void)size;\r
11     (void)app_key;\r
12     return 0;\r
13 }\r
14 \r
15 asn_enc_rval_t\r
16 uper_encode(const asn_TYPE_descriptor_t *td,\r
17             const asn_per_constraints_t *constraints, const void *sptr,\r
18             asn_app_consume_bytes_f *cb, void *app_key) {\r
19     asn_per_outp_t po;\r
20     asn_enc_rval_t er = {0,0,0};\r
21 \r
22     /*\r
23      * Invoke type-specific encoder.\r
24      */\r
25     if(!td || !td->op->uper_encoder)\r
26         ASN__ENCODE_FAILED;     /* PER is not compiled in */\r
27 \r
28     po.buffer = po.tmpspace;\r
29     po.nboff = 0;\r
30     po.nbits = 8 * sizeof(po.tmpspace);\r
31     po.output = cb ? cb : ignore_output;\r
32     po.op_key = app_key;\r
33     po.flushed_bytes = 0;\r
34 \r
35     er = td->op->uper_encoder(td, constraints, sptr, &po);\r
36     if(er.encoded != -1) {\r
37         size_t bits_to_flush;\r
38 \r
39         bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;\r
40 \r
41         /* Set number of bits encoded to a firm value */\r
42         er.encoded = (po.flushed_bytes << 3) + bits_to_flush;\r
43 \r
44         if(_uper_encode_flush_outp(&po)) ASN__ENCODE_FAILED;\r
45     }\r
46 \r
47     return er;\r
48 }\r
49 \r
50 /*\r
51  * Argument type and callback necessary for uper_encode_to_buffer().\r
52  */\r
53 typedef struct enc_to_buf_arg {\r
54         void *buffer;\r
55         size_t left;\r
56 } enc_to_buf_arg;\r
57 static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {\r
58         enc_to_buf_arg *arg = (enc_to_buf_arg *)key;\r
59 \r
60         if(arg->left < size)\r
61                 return -1;      /* Data exceeds the available buffer size */\r
62 \r
63         memcpy(arg->buffer, buffer, size);\r
64         arg->buffer = ((char *)arg->buffer) + size;\r
65         arg->left -= size;\r
66 \r
67         return 0;\r
68 }\r
69 \r
70 asn_enc_rval_t\r
71 uper_encode_to_buffer(const asn_TYPE_descriptor_t *td,\r
72                       const asn_per_constraints_t *constraints,\r
73                       const void *sptr, void *buffer, size_t buffer_size) {\r
74     enc_to_buf_arg key;\r
75 \r
76     key.buffer = buffer;\r
77     key.left = buffer_size;\r
78 \r
79     if(td) ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);\r
80 \r
81     return uper_encode(td, constraints, sptr, encode_to_buffer_cb, &key);\r
82 }\r
83 \r
84 typedef struct enc_dyn_arg {\r
85         void *buffer;\r
86         size_t length;\r
87         size_t allocated;\r
88 } enc_dyn_arg;\r
89 static int\r
90 encode_dyn_cb(const void *buffer, size_t size, void *key) {\r
91     enc_dyn_arg *arg = key;\r
92     if(arg->length + size >= arg->allocated) {\r
93         size_t new_size = arg->allocated ? arg->allocated : 8;\r
94         void *p;\r
95 \r
96         do {\r
97             new_size <<= 2;\r
98         } while(arg->length + size >= new_size);\r
99 \r
100         p = REALLOC(arg->buffer, new_size);\r
101         if(!p) {\r
102             FREEMEM(arg->buffer);\r
103             memset(arg, 0, sizeof(*arg));\r
104             return -1;\r
105         }\r
106         arg->buffer = p;\r
107         arg->allocated = new_size;\r
108     }\r
109     memcpy(((char *)arg->buffer) + arg->length, buffer, size);\r
110     arg->length += size;\r
111     return 0;\r
112 }\r
113 ssize_t\r
114 uper_encode_to_new_buffer(const asn_TYPE_descriptor_t *td,\r
115                           const asn_per_constraints_t *constraints,\r
116                           const void *sptr, void **buffer_r) {\r
117     asn_enc_rval_t er = {0,0,0};\r
118         enc_dyn_arg key;\r
119 \r
120         memset(&key, 0, sizeof(key));\r
121 \r
122         er = uper_encode(td, constraints, sptr, encode_dyn_cb, &key);\r
123         switch(er.encoded) {\r
124         case -1:\r
125                 FREEMEM(key.buffer);\r
126                 return -1;\r
127         case 0:\r
128                 FREEMEM(key.buffer);\r
129                 key.buffer = MALLOC(1);\r
130                 if(key.buffer) {\r
131                         *(char *)key.buffer = '\0';\r
132                         *buffer_r = key.buffer;\r
133                         return 1;\r
134                 } else {\r
135                         return -1;\r
136                 }\r
137         default:\r
138                 *buffer_r = key.buffer;\r
139                 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);\r
140                 return ((er.encoded + 7) >> 3);\r
141         }\r
142 }\r
143 \r
144 /*\r
145  * Internally useful functions.\r
146  */\r
147 \r
148 /* Flush partially filled buffer */\r
149 static int\r
150 _uper_encode_flush_outp(asn_per_outp_t *po) {\r
151         uint8_t *buf;\r
152 \r
153         if(po->nboff == 0 && po->buffer == po->tmpspace)\r
154                 return 0;\r
155 \r
156         buf = po->buffer + (po->nboff >> 3);\r
157         /* Make sure we account for the last, partially filled */\r
158         if(po->nboff & 0x07) {\r
159                 buf[0] &= 0xff << (8 - (po->nboff & 0x07));\r
160                 buf++;\r
161         }\r
162 \r
163         return po->output(po->tmpspace, buf - po->tmpspace, po->op_key);\r
164 }\r
165 \r
166 asn_enc_rval_t\r
167 aper_encode_to_buffer(const asn_TYPE_descriptor_t *td,\r
168                       const asn_per_constraints_t *constraints,\r
169                       const void *sptr, void *buffer, size_t buffer_size) {\r
170     enc_to_buf_arg key;\r
171 \r
172     key.buffer = buffer;\r
173     key.left = buffer_size;\r
174 \r
175     if(td) ASN_DEBUG("Encoding \"%s\" using ALIGNED PER", td->name);\r
176 \r
177     return aper_encode(td, constraints, sptr, encode_to_buffer_cb, &key);\r
178 }\r
179 \r
180 ssize_t\r
181 aper_encode_to_new_buffer(const asn_TYPE_descriptor_t *td,\r
182                           const asn_per_constraints_t *constraints,\r
183                           const void *sptr, void **buffer_r) {\r
184     asn_enc_rval_t er = {0,0,0};\r
185         enc_dyn_arg key;\r
186 \r
187         memset(&key, 0, sizeof(key));\r
188 \r
189         er = aper_encode(td, constraints, sptr, encode_dyn_cb, &key);\r
190         switch(er.encoded) {\r
191         case -1:\r
192                 FREEMEM(key.buffer);\r
193                 return -1;\r
194         case 0:\r
195                 FREEMEM(key.buffer);\r
196                 key.buffer = MALLOC(1);\r
197                 if(key.buffer) {\r
198                         *(char *)key.buffer = '\0';\r
199                         *buffer_r = key.buffer;\r
200                         return 1;\r
201                 } else {\r
202                         return -1;\r
203                 }\r
204         default:\r
205                 *buffer_r = key.buffer;\r
206                 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);\r
207                 return ((er.encoded + 7) >> 3);\r
208         }\r
209 }\r
210 \r
211 static int\r
212 _aper_encode_flush_outp(asn_per_outp_t *po) {\r
213         uint8_t *buf;\r
214 \r
215         if(po->nboff == 0 && po->buffer == po->tmpspace)\r
216                 return 0;\r
217 \r
218         buf = po->buffer + (po->nboff >> 3);\r
219         /* Make sure we account for the last, partially filled */\r
220         if(po->nboff & 0x07) {\r
221                 buf[0] &= 0xff << (8 - (po->nboff & 0x07));\r
222                 buf++;\r
223         }\r
224 \r
225         if (po->output) {\r
226                 return po->output(po->tmpspace, buf - po->tmpspace, po->op_key);\r
227         }\r
228         return 0;\r
229 }\r
230 \r
231 asn_enc_rval_t\r
232 aper_encode(const asn_TYPE_descriptor_t *td,\r
233         const asn_per_constraints_t *constraints,\r
234         const void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {\r
235         asn_per_outp_t po;\r
236         asn_enc_rval_t er = {0,0,0};\r
237 \r
238         /*\r
239          * Invoke type-specific encoder.\r
240          */\r
241         if(!td || !td->op->aper_encoder)\r
242                 ASN__ENCODE_FAILED;      /* PER is not compiled in */\r
243 \r
244         po.buffer = po.tmpspace;\r
245         po.nboff = 0;\r
246         po.nbits = 8 * sizeof(po.tmpspace);\r
247         po.output = cb;\r
248         po.op_key = app_key;\r
249         po.flushed_bytes = 0;\r
250 \r
251         er = td->op->aper_encoder(td, constraints, sptr, &po);\r
252         if(er.encoded != -1) {\r
253                 size_t bits_to_flush;\r
254 \r
255                 bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;\r
256 \r
257                 /* Set number of bits encoded to a firm value */\r
258                 er.encoded = (po.flushed_bytes << 3) + bits_to_flush;\r
259 \r
260                 if(_aper_encode_flush_outp(&po))\r
261                         ASN__ENCODE_FAILED;\r
262         }\r
263 \r
264         return er;\r
265 }\r