2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
4 * Redistribution and modifications are permitted subject to BSD license.
6 #include <asn_internal.h>
7 #include <asn_codecs_prim.h>
10 * Local internal type passed around as an argument.
13 const asn_TYPE_descriptor_t *type_descriptor;
15 xer_primitive_body_decoder_f *prim_body_decoder;
16 int decoded_something;
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.
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;
31 * The chunk_buf is guaranteed to start at '<'.
33 assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
36 * Decoding was performed once already. Prohibit doing it again.
38 if(arg->decoded_something)
41 bret = arg->prim_body_decoder(arg->type_descriptor,
42 arg->struct_key, chunk_buf,
45 case XPBD_SYSTEM_FAILURE:
46 case XPBD_DECODER_LIMIT:
47 case XPBD_BROKEN_ENCODING:
49 case XPBD_BODY_CONSUMED:
50 /* Tag decoded successfully */
51 arg->decoded_something = 1;
53 case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
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;
66 if(arg->decoded_something) {
67 if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
70 * "<INTEGER>123<!--/--> </INTEGER>"
71 * ^- chunk_buf position.
76 * Decoding was done once already. Prohibit doing it again.
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:
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;
98 bret = arg->prim_body_decoder(arg->type_descriptor,
99 arg->struct_key, chunk_buf,
102 case XPBD_SYSTEM_FAILURE:
103 case XPBD_DECODER_LIMIT:
104 case XPBD_BROKEN_ENCODING:
106 case XPBD_BODY_CONSUMED:
107 /* Tag decoded successfully */
108 arg->decoded_something = 1;
110 case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
111 return lead_wsp_size + chunk_size;
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;
129 * Create the structure if does not exist.
132 *sptr = CALLOC(1, struct_size);
133 if(!*sptr) ASN__DECODE_FAILED;
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;
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);
149 if(!s_arg.decoded_something) {
151 ASN_DEBUG("Primitive body is not recognized, "
152 "supplying empty one");
154 * Decoding opportunity has come and gone.
155 * Where's the result?
156 * Try to feed with empty body, see if it eats it.
158 if(prim_body_decoder(s_arg.type_descriptor,
159 s_arg.struct_key, &ch, 0)
160 != XPBD_BODY_CONSUMED) {
162 * This decoder does not like empty stuff.
170 * Redo the whole thing later.
171 * We don't have a context to save intermediate parsing state.