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.