SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / constr_SEQUENCE_xer.c
1 /*
2  * Copyright (c) 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 <constr_SEQUENCE.h>
8 #include <OPEN_TYPE.h>
9
10 /*
11  * Return a standardized complex structure.
12  */
13 #undef RETURN
14 #define RETURN(_code)                     \
15     do {                                  \
16         rval.code = _code;                \
17         rval.consumed = consumed_myself;  \
18         return rval;                      \
19     } while(0)
20
21 /*
22  * Check whether we are inside the extensions group.
23  */
24 #define IN_EXTENSION_GROUP(specs, memb_idx)                \
25     ((specs)->first_extension >= 0                         \
26      && (unsigned)(specs)->first_extension <= (memb_idx))
27
28 #undef XER_ADVANCE
29 #define XER_ADVANCE(num_bytes)            \
30     do {                                  \
31         size_t num = (num_bytes);         \
32         ptr = ((const char *)ptr) + num;  \
33         size -= num;                      \
34         consumed_myself += num;           \
35     } while(0)
36
37 /*
38  * Decode the XER (XML) data.
39  */
40 asn_dec_rval_t
41 SEQUENCE_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
42                     const asn_TYPE_descriptor_t *td, void **struct_ptr,
43                     const char *opt_mname, const void *ptr, size_t size) {
44     /*
45      * Bring closer parts of structure description.
46      */
47     const asn_SEQUENCE_specifics_t *specs
48         = (const asn_SEQUENCE_specifics_t *)td->specifics;
49     asn_TYPE_member_t *elements = td->elements;
50     const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
51
52     /*
53      * ... and parts of the structure being constructed.
54      */
55     void *st = *struct_ptr;  /* Target structure. */
56     asn_struct_ctx_t *ctx;   /* Decoder context */
57
58     asn_dec_rval_t rval;          /* Return value from a decoder */
59     ssize_t consumed_myself = 0;  /* Consumed bytes from ptr */
60     size_t edx;                   /* Element index */
61
62     /*
63      * Create the target structure if it is not present already.
64      */
65     if(st == 0) {
66         st = *struct_ptr = CALLOC(1, specs->struct_size);
67         if(st == 0) RETURN(RC_FAIL);
68     }
69
70     /*
71      * Restore parsing context.
72      */
73     ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
74
75
76     /*
77      * Phases of XER/XML processing:
78      * Phase 0: Check that the opening tag matches our expectations.
79      * Phase 1: Processing body and reacting on closing tag.
80      * Phase 2: Processing inner type.
81      * Phase 3: Skipping unknown extensions.
82      * Phase 4: PHASED OUT
83      */
84     for(edx = ctx->step; ctx->phase <= 3;) {
85         pxer_chunk_type_e ch_type;  /* XER chunk type */
86         ssize_t ch_size;            /* Chunk size */
87         xer_check_tag_e tcv;        /* Tag check value */
88         asn_TYPE_member_t *elm;
89
90         /*
91          * Go inside the inner member of a sequence.
92          */
93         if(ctx->phase == 2) {
94             asn_dec_rval_t tmprval;
95             void *memb_ptr_dontuse;  /* Pointer to the member */
96             void **memb_ptr2;        /* Pointer to that pointer */
97
98             elm = &td->elements[edx];
99
100             if(elm->flags & ATF_POINTER) {
101                 /* Member is a pointer to another structure */
102                 memb_ptr2 = (void **)((char *)st + elm->memb_offset);
103             } else {
104                 memb_ptr_dontuse = (char *)st + elm->memb_offset;
105                 memb_ptr2 = &memb_ptr_dontuse;  /* Only use of memb_ptr_dontuse */
106             }
107
108             if(elm->flags & ATF_OPEN_TYPE) {
109                 tmprval = OPEN_TYPE_xer_get(opt_codec_ctx, td, st, elm, ptr, size);
110             } else {
111                 /* Invoke the inner type decoder, m.b. multiple times */
112                 tmprval = elm->type->op->xer_decoder(opt_codec_ctx,
113                                                      elm->type, memb_ptr2, elm->name,
114                                                      ptr, size);
115             }
116             XER_ADVANCE(tmprval.consumed);
117             if(tmprval.code != RC_OK)
118                 RETURN(tmprval.code);
119             ctx->phase = 1;  /* Back to body processing */
120             ctx->step = ++edx;
121             ASN_DEBUG("XER/SEQUENCE phase => %d, step => %d",
122                 ctx->phase, ctx->step);
123             /* Fall through */
124         }
125
126         /*
127          * Get the next part of the XML stream.
128          */
129         ch_size = xer_next_token(&ctx->context, ptr, size,
130             &ch_type);
131         if(ch_size == -1) {
132             RETURN(RC_FAIL);
133         } else {
134             switch(ch_type) {
135             case PXER_WMORE:
136                 RETURN(RC_WMORE);
137             case PXER_COMMENT:  /* Got XML comment */
138             case PXER_TEXT:  /* Ignore free-standing text */
139                 XER_ADVANCE(ch_size);  /* Skip silently */
140                 continue;
141             case PXER_TAG:
142                 break;  /* Check the rest down there */
143             }
144         }
145
146         tcv = xer_check_tag(ptr, ch_size, xml_tag);
147         ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d [%s]",
148                   tcv, ctx->phase, xml_tag);
149
150         /* Skip the extensions section */
151         if(ctx->phase == 3) {
152             switch(xer_skip_unknown(tcv, &ctx->left)) {
153             case -1:
154                 ctx->phase = 4;
155                 RETURN(RC_FAIL);
156             case 0:
157                 XER_ADVANCE(ch_size);
158                 continue;
159             case 1:
160                 XER_ADVANCE(ch_size);
161                 ctx->phase = 1;
162                 continue;
163             case 2:
164                 ctx->phase = 1;
165                 break;
166             }
167         }
168
169         switch(tcv) {
170         case XCT_CLOSING:
171             if(ctx->phase == 0) break;
172             ctx->phase = 0;
173             /* Fall through */
174         case XCT_BOTH:
175             if(ctx->phase == 0) {
176                 if(edx >= td->elements_count ||
177                    /* Explicit OPTIONAL specs reaches the end */
178                    (edx + elements[edx].optional == td->elements_count) ||
179                    /* All extensions are optional */
180                    IN_EXTENSION_GROUP(specs, edx)) {
181                     XER_ADVANCE(ch_size);
182                     ctx->phase = 4;  /* Phase out */
183                     RETURN(RC_OK);
184                 } else {
185                     ASN_DEBUG("Premature end of XER SEQUENCE");
186                     RETURN(RC_FAIL);
187                 }
188             }
189             /* Fall through */
190         case XCT_OPENING:
191             if(ctx->phase == 0) {
192                 XER_ADVANCE(ch_size);
193                 ctx->phase = 1;  /* Processing body phase */
194                 continue;
195             }
196             /* Fall through */
197         case XCT_UNKNOWN_OP:
198         case XCT_UNKNOWN_BO:
199
200             ASN_DEBUG("XER/SEQUENCE: tcv=%d, ph=%d, edx=%" ASN_PRI_SIZE "",
201                       tcv, ctx->phase, edx);
202             if(ctx->phase != 1) {
203                 break;  /* Really unexpected */
204             }
205
206             if(edx < td->elements_count) {
207                 /*
208                  * Search which member corresponds to this tag.
209                  */
210                 size_t n;
211                 size_t edx_end = edx + elements[edx].optional + 1;
212                 if(edx_end > td->elements_count)
213                     edx_end = td->elements_count;
214                 for(n = edx; n < edx_end; n++) {
215                     elm = &td->elements[n];
216                     tcv = xer_check_tag(ptr, ch_size, elm->name);
217                     switch(tcv) {
218                     case XCT_BOTH:
219                     case XCT_OPENING:
220                         /*
221                          * Process this member.
222                          */
223                         ctx->step = edx = n;
224                         ctx->phase = 2;
225                         break;
226                     case XCT_UNKNOWN_OP:
227                     case XCT_UNKNOWN_BO:
228                         continue;
229                     default:
230                         n = edx_end;
231                         break;  /* Phase out */
232                     }
233                     break;
234                 }
235                 if(n != edx_end)
236                     continue;
237             } else {
238                 ASN_DEBUG("Out of defined members: %" ASN_PRI_SIZE "/%u",
239                           edx, td->elements_count);
240             }
241
242             /* It is expected extension */
243             if(IN_EXTENSION_GROUP(specs,
244                 edx + (edx < td->elements_count
245                     ? elements[edx].optional : 0))) {
246                 ASN_DEBUG("Got anticipated extension at %" ASN_PRI_SIZE "",
247                           edx);
248                 /*
249                  * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
250                  * By using a mask. Only record a pure
251                  * <opening> tags.
252                  */
253                 if(tcv & XCT_CLOSING) {
254                     /* Found </extension> without body */
255                 } else {
256                     ctx->left = 1;
257                     ctx->phase = 3;  /* Skip ...'s */
258                 }
259                 XER_ADVANCE(ch_size);
260                 continue;
261             }
262
263             /* Fall through */
264         default:
265             break;
266         }
267
268         ASN_DEBUG("Unexpected XML tag in SEQUENCE [%c%c%c%c%c%c]",
269                   size>0?((const char *)ptr)[0]:'.',
270                   size>1?((const char *)ptr)[1]:'.',
271                   size>2?((const char *)ptr)[2]:'.',
272                   size>3?((const char *)ptr)[3]:'.',
273                   size>4?((const char *)ptr)[4]:'.',
274                   size>5?((const char *)ptr)[5]:'.');
275         break;
276     }
277
278     ctx->phase = 4;  /* "Phase out" on hard failure */
279     RETURN(RC_FAIL);
280 }
281
282 asn_enc_rval_t
283 SEQUENCE_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
284                     int ilevel, enum xer_encoder_flags_e flags,
285                     asn_app_consume_bytes_f *cb, void *app_key) {
286     asn_enc_rval_t er = {0,0,0};
287     int xcan = (flags & XER_F_CANONICAL);
288     asn_TYPE_descriptor_t *tmp_def_val_td = 0;
289     void *tmp_def_val = 0;
290     size_t edx;
291
292     if(!sptr) ASN__ENCODE_FAILED;
293
294     er.encoded = 0;
295
296     for(edx = 0; edx < td->elements_count; edx++) {
297         asn_enc_rval_t tmper = {0,0,0};
298         asn_TYPE_member_t *elm = &td->elements[edx];
299         const void *memb_ptr;
300         const char *mname = elm->name;
301         unsigned int mlen = strlen(mname);
302
303         if(elm->flags & ATF_POINTER) {
304             memb_ptr =
305                 *(const void *const *)((const char *)sptr + elm->memb_offset);
306             if(!memb_ptr) {
307                 assert(tmp_def_val == 0);
308                 if(elm->default_value_set) {
309                     if(elm->default_value_set(&tmp_def_val)) {
310                         ASN__ENCODE_FAILED;
311                     } else {
312                         memb_ptr = tmp_def_val;
313                         tmp_def_val_td = elm->type;
314                     }
315                 } else if(elm->optional) {
316                     continue;
317                 } else {
318                     /* Mandatory element is missing */
319                     ASN__ENCODE_FAILED;
320                 }
321             }
322         } else {
323             memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
324         }
325
326         if(!xcan) ASN__TEXT_INDENT(1, ilevel);
327         ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
328
329         /* Print the member itself */
330         tmper = elm->type->op->xer_encoder(elm->type, memb_ptr, ilevel + 1,
331                                            flags, cb, app_key);
332         if(tmp_def_val) {
333             ASN_STRUCT_FREE(*tmp_def_val_td, tmp_def_val);
334             tmp_def_val = 0;
335         }
336         if(tmper.encoded == -1) return tmper;
337         er.encoded += tmper.encoded;
338
339         ASN__CALLBACK3("</", 2, mname, mlen, ">", 1);
340     }
341
342     if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
343
344     ASN__ENCODED_OK(er);
345 cb_failed:
346     if(tmp_def_val) ASN_STRUCT_FREE(*tmp_def_val_td, tmp_def_val);
347     ASN__ENCODE_FAILED;
348 }