2 * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
5 #include <asn_internal.h>
6 #include <asn_codecs_prim.h>
10 * Decode an always-primitive type.
13 ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
14 asn_TYPE_descriptor_t *td,
15 void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
16 ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
21 * If the structure is not there, allocate it.
24 st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
25 if(st == NULL) _ASN_DECODE_FAILED;
29 ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
33 * Check tags and extract value length.
35 rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
36 tag_mode, 0, &length, 0);
37 if(rval.code != RC_OK)
40 ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
43 * Make sure we have this length.
45 buf_ptr = ((const char *)buf_ptr) + rval.consumed;
46 size -= rval.consumed;
47 if(length > (ber_tlv_len_t)size) {
53 st->size = (int)length;
54 /* The following better be optimized away. */
55 if(sizeof(st->size) != sizeof(length)
56 && (ber_tlv_len_t)st->size != length) {
61 st->buf = (uint8_t *)MALLOC(length + 1);
67 memcpy(st->buf, buf_ptr, length);
68 st->buf[length] = '\0'; /* Just in case */
71 rval.consumed += length;
73 ASN_DEBUG("Took %ld/%ld bytes to encode %s",
75 (long)length, td->name);
81 * Encode an always-primitive type using DER.
84 der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr,
85 int tag_mode, ber_tlv_tag_t tag,
86 asn_app_consume_bytes_f *cb, void *app_key) {
88 ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
90 ASN_DEBUG("%s %s as a primitive type (tm=%d)",
91 cb?"Encoding":"Estimating", td->name, tag_mode);
93 erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
95 ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
96 if(erval.encoded == -1) {
97 erval.failed_type = td;
98 erval.structure_ptr = sptr;
103 if(cb(st->buf, st->size, app_key) < 0) {
105 erval.failed_type = td;
106 erval.structure_ptr = sptr;
110 assert(st->buf || st->size == 0);
113 erval.encoded += st->size;
114 _ASN_ENCODED_OK(erval);
118 ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
120 ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
125 ASN_DEBUG("Freeing %s as a primitive type", td->name);
136 * Local internal type passed around as an argument.
139 asn_TYPE_descriptor_t *type_descriptor;
141 xer_primitive_body_decoder_f *prim_body_decoder;
142 int decoded_something;
148 xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
149 struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
150 enum xer_pbd_rval bret;
152 if(arg->decoded_something) {
153 if(xer_is_whitespace(chunk_buf, chunk_size))
154 return 0; /* Skip it. */
156 * Decoding was done once already. Prohibit doing it again.
161 bret = arg->prim_body_decoder(arg->type_descriptor,
162 arg->struct_key, chunk_buf, chunk_size);
164 case XPBD_SYSTEM_FAILURE:
165 case XPBD_DECODER_LIMIT:
166 case XPBD_BROKEN_ENCODING:
168 case XPBD_BODY_CONSUMED:
169 /* Tag decoded successfully */
170 arg->decoded_something = 1;
172 case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
180 xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
181 struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
182 enum xer_pbd_rval bret;
184 if(arg->decoded_something) {
185 if(xer_is_whitespace(chunk_buf, chunk_size))
188 * Decoding was done once already. Prohibit doing it again.
195 * If we've received something like "1", we can't really
196 * tell whether it is really `1` or `123`, until we know
197 * that there is no more data coming.
198 * The have_more argument will be set to 1 once something
199 * like this is available to the caller of this callback:
206 bret = arg->prim_body_decoder(arg->type_descriptor,
207 arg->struct_key, chunk_buf, chunk_size);
209 case XPBD_SYSTEM_FAILURE:
210 case XPBD_DECODER_LIMIT:
211 case XPBD_BROKEN_ENCODING:
213 case XPBD_BODY_CONSUMED:
214 /* Tag decoded successfully */
215 arg->decoded_something = 1;
217 case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
226 xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
227 asn_TYPE_descriptor_t *td,
230 const char *opt_mname,
231 const void *buf_ptr, size_t size,
232 xer_primitive_body_decoder_f *prim_body_decoder
234 const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
235 asn_struct_ctx_t s_ctx;
236 struct xdp_arg_s s_arg;
240 * Create the structure if does not exist.
243 *sptr = CALLOC(1, struct_size);
244 if(!*sptr) _ASN_DECODE_FAILED;
247 memset(&s_ctx, 0, sizeof(s_ctx));
248 s_arg.type_descriptor = td;
249 s_arg.struct_key = *sptr;
250 s_arg.prim_body_decoder = prim_body_decoder;
251 s_arg.decoded_something = 0;
254 rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
255 xml_tag, buf_ptr, size,
256 xer_decode__unexpected_tag, xer_decode__body);
259 if(!s_arg.decoded_something) {
261 ASN_DEBUG("Primitive body is not recognized, "
262 "supplying empty one");
264 * Decoding opportunity has come and gone.
265 * Where's the result?
266 * Try to feed with empty body, see if it eats it.
268 if(prim_body_decoder(s_arg.type_descriptor,
269 s_arg.struct_key, &ch, 0)
270 != XPBD_BODY_CONSUMED) {
272 * This decoder does not like empty stuff.
280 * Redo the whole thing later.
281 * We don't have a context to save intermediate parsing state.