SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / asn_codecs_prim_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 <asn_codecs_prim.h>
8
9 /*
10  * Local internal type passed around as an argument.
11  */
12 struct xdp_arg_s {
13     const asn_TYPE_descriptor_t *type_descriptor;
14     void *struct_key;
15     xer_primitive_body_decoder_f *prim_body_decoder;
16     int decoded_something;
17     int want_more;
18 };
19
20 /*
21  * Since some kinds of primitive values can be encoded using value-specific
22  * tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive decoder must
23  * be supplied with such tags to parse them as needed.
24  */
25 static int
26 xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
27     struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
28     enum xer_pbd_rval bret;
29
30     /*
31      * The chunk_buf is guaranteed to start at '<'.
32      */
33     assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
34
35     /*
36      * Decoding was performed once already. Prohibit doing it again.
37     */
38     if(arg->decoded_something)
39         return -1;
40
41     bret = arg->prim_body_decoder(arg->type_descriptor,
42                                   arg->struct_key, chunk_buf,
43                                   chunk_size);
44     switch(bret) {
45     case XPBD_SYSTEM_FAILURE:
46     case XPBD_DECODER_LIMIT:
47     case XPBD_BROKEN_ENCODING:
48         break;
49     case XPBD_BODY_CONSUMED:
50         /* Tag decoded successfully */
51         arg->decoded_something = 1;
52         /* Fall through */
53     case XPBD_NOT_BODY_IGNORE:  /* Safe to proceed further */
54         return 0;
55     }
56
57     return -1;
58 }
59
60 static ssize_t
61 xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
62     struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
63     enum xer_pbd_rval bret;
64     size_t lead_wsp_size;
65
66     if(arg->decoded_something) {
67         if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
68             /*
69              * Example:
70              * "<INTEGER>123<!--/--> </INTEGER>"
71              *                      ^- chunk_buf position.
72              */
73             return chunk_size;
74         }
75         /*
76          * Decoding was done once already. Prohibit doing it again.
77          */
78         return -1;
79     }
80
81     if(!have_more) {
82         /*
83          * If we've received something like "1", we can't really
84          * tell whether it is really `1` or `123`, until we know
85          * that there is no more data coming.
86          * The have_more argument will be set to 1 once something
87          * like this is available to the caller of this callback:
88          * "1<tag_start..."
89          */
90         arg->want_more = 1;
91         return -1;
92     }
93
94     lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size);
95     chunk_buf   = (chunk_buf == NULL)? NULL : ((const char *)chunk_buf + lead_wsp_size);
96     chunk_size -= lead_wsp_size;
97
98     bret = arg->prim_body_decoder(arg->type_descriptor,
99                                   arg->struct_key, chunk_buf,
100                                   chunk_size);
101     switch(bret) {
102     case XPBD_SYSTEM_FAILURE:
103     case XPBD_DECODER_LIMIT:
104     case XPBD_BROKEN_ENCODING:
105         break;
106     case XPBD_BODY_CONSUMED:
107         /* Tag decoded successfully */
108         arg->decoded_something = 1;
109         /* Fall through */
110     case XPBD_NOT_BODY_IGNORE:  /* Safe to proceed further */
111         return lead_wsp_size + chunk_size;
112     }
113
114     return -1;
115 }
116
117 asn_dec_rval_t
118 xer_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
119                      const asn_TYPE_descriptor_t *td, void **sptr,
120                      size_t struct_size, const char *opt_mname,
121                      const void *buf_ptr, size_t size,
122                      xer_primitive_body_decoder_f *prim_body_decoder) {
123     const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
124     asn_struct_ctx_t s_ctx;
125     struct xdp_arg_s s_arg;
126     asn_dec_rval_t rc;
127
128     /*
129      * Create the structure if does not exist.
130      */
131     if(!*sptr) {
132         *sptr = CALLOC(1, struct_size);
133         if(!*sptr) ASN__DECODE_FAILED;
134     }
135
136     memset(&s_ctx, 0, sizeof(s_ctx));
137     s_arg.type_descriptor = td;
138     s_arg.struct_key = *sptr;
139     s_arg.prim_body_decoder = prim_body_decoder;
140     s_arg.decoded_something = 0;
141     s_arg.want_more = 0;
142
143     rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
144                             xml_tag, buf_ptr, size,
145                             xer_decode__unexpected_tag,
146                             xer_decode__primitive_body);
147     switch(rc.code) {
148     case RC_OK:
149         if(!s_arg.decoded_something) {
150             char ch;
151             ASN_DEBUG("Primitive body is not recognized, "
152                       "supplying empty one");
153             /*
154              * Decoding opportunity has come and gone.
155              * Where's the result?
156              * Try to feed with empty body, see if it eats it.
157              */
158             if(prim_body_decoder(s_arg.type_descriptor,
159                 s_arg.struct_key, &ch, 0)
160                     != XPBD_BODY_CONSUMED) {
161                 /*
162                  * This decoder does not like empty stuff.
163                  */
164                 ASN__DECODE_FAILED;
165             }
166         }
167         break;
168     case RC_WMORE:
169         /*
170          * Redo the whole thing later.
171          * We don't have a context to save intermediate parsing state.
172          */
173         rc.consumed = 0;
174         break;
175     case RC_FAIL:
176         rc.consumed = 0;
177         if(s_arg.want_more)
178             rc.code = RC_WMORE;
179         else
180             ASN__DECODE_FAILED;
181         break;
182     }
183     return rc;
184 }