2 * Copyright (c) 2017 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_application.h>
9 static asn_enc_rval_t asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
10 enum asn_transfer_syntax syntax,
11 const asn_TYPE_descriptor_t *td,
13 asn_app_consume_bytes_f *callback,
17 struct callback_count_bytes_key {
18 asn_app_consume_bytes_f *callback;
24 * Encoder which just counts bytes that come through it.
27 callback_count_bytes_cb(const void *data, size_t size, void *keyp) {
28 struct callback_count_bytes_key *key = keyp;
31 ret = key->callback(data, size, key->callback_key);
33 key->computed_size += size;
39 struct overrun_encoder_key {
45 struct dynamic_encoder_key {
51 struct callback_failure_catch_key {
52 asn_app_consume_bytes_f *callback;
58 * Encoder which doesn't stop counting bytes
59 * even if it reaches the end of the buffer.
62 overrun_encoder_cb(const void *data, size_t size, void *keyp) {
63 struct overrun_encoder_key *key = keyp;
65 if(key->computed_size + size > key->buffer_size) {
67 * Avoid accident on the next call:
68 * stop adding bytes to the buffer.
72 memcpy((char *)key->buffer + key->computed_size, data, size);
74 key->computed_size += size;
80 * Encoder which dynamically allocates output, and continues
81 * to count even if allocation failed.
84 dynamic_encoder_cb(const void *data, size_t size, void *keyp) {
85 struct dynamic_encoder_key *key = keyp;
88 if(key->computed_size + size >= key->buffer_size) {
90 size_t new_size = key->buffer_size;
94 } while(new_size <= key->computed_size + size);
96 p = REALLOC(key->buffer, new_size);
99 key->buffer_size = new_size;
101 FREEMEM(key->buffer);
103 key->buffer_size = 0;
104 key->computed_size += size;
108 memcpy((char *)key->buffer + key->computed_size, data, size);
111 key->computed_size += size;
117 * Encoder which help convert the application level encoder failure into EIO.
120 callback_failure_catch_cb(const void *data, size_t size, void *keyp) {
121 struct callback_failure_catch_key *key = keyp;
124 ret = key->callback(data, size, key->callback_key);
126 key->callback_failed = 1;
133 asn_encode(const asn_codec_ctx_t *opt_codec_ctx,
134 enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,
135 const void *sptr, asn_app_consume_bytes_f *callback, void *callback_key) {
136 struct callback_failure_catch_key cb_key;
137 asn_enc_rval_t er = {0,0,0};
144 cb_key.callback = callback;
145 cb_key.callback_key = callback_key;
146 cb_key.callback_failed = 0;
148 er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
149 callback_failure_catch_cb, &cb_key);
150 if(cb_key.callback_failed) {
151 assert(er.encoded == -1);
152 assert(errno == EBADF);
160 asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_ctx,
161 enum asn_transfer_syntax syntax,
162 const asn_TYPE_descriptor_t *td, const void *sptr,
163 void *buffer, size_t buffer_size) {
164 struct overrun_encoder_key buf_key;
165 asn_enc_rval_t er = {0,0,0};
167 if(buffer_size > 0 && !buffer) {
172 buf_key.buffer = buffer;
173 buf_key.buffer_size = buffer_size;
174 buf_key.computed_size = 0;
176 er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
177 overrun_encoder_cb, &buf_key);
179 if(er.encoded >= 0 && (size_t)er.encoded != buf_key.computed_size) {
180 ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
181 " yet produced %" ASN_PRI_SIZE " bytes",
182 er.encoded, buf_key.computed_size);
183 assert(er.encoded < 0 || (size_t)er.encoded == buf_key.computed_size);
189 asn_encode_to_new_buffer_result_t
190 asn_encode_to_new_buffer(const asn_codec_ctx_t *opt_codec_ctx,
191 enum asn_transfer_syntax syntax,
192 const asn_TYPE_descriptor_t *td, const void *sptr) {
193 struct dynamic_encoder_key buf_key;
194 asn_encode_to_new_buffer_result_t res;
196 buf_key.buffer_size = 16;
197 buf_key.buffer = MALLOC(buf_key.buffer_size);
198 buf_key.computed_size = 0;
200 res.result = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
201 dynamic_encoder_cb, &buf_key);
203 if(res.result.encoded >= 0
204 && (size_t)res.result.encoded != buf_key.computed_size) {
205 ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
206 " yet produced %" ASN_PRI_SIZE " bytes",
207 res.result.encoded, buf_key.computed_size);
208 assert(res.result.encoded < 0
209 || (size_t)res.result.encoded == buf_key.computed_size);
212 res.buffer = buf_key.buffer;
214 /* 0-terminate just in case. */
216 assert(buf_key.computed_size < buf_key.buffer_size);
217 ((char *)res.buffer)[buf_key.computed_size] = '\0';
223 static asn_enc_rval_t
224 asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
225 enum asn_transfer_syntax syntax,
226 const asn_TYPE_descriptor_t *td, const void *sptr,
227 asn_app_consume_bytes_f *callback, void *callback_key) {
228 asn_enc_rval_t er = {0,0,0};
229 #if !defined(ASN_DISABLE_XER_SUPPORT)
230 enum xer_encoder_flags_e xer_flags = XER_F_CANONICAL;
231 #endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
233 (void)opt_codec_ctx; /* Parameters are not checked on encode yet. */
241 case ATS_NONSTANDARD_PLAINTEXT:
242 if(td->op->print_struct) {
243 struct callback_count_bytes_key cb_key;
244 cb_key.callback = callback;
245 cb_key.callback_key = callback_key;
246 cb_key.computed_size = 0;
247 if(td->op->print_struct(td, sptr, 1, callback_count_bytes_cb,
250 || callback_count_bytes_cb("\n", 1, &cb_key) < 0) {
251 errno = EBADF; /* Structure has incorrect form. */
254 er.structure_ptr = sptr;
256 er.encoded = cb_key.computed_size;
258 er.structure_ptr = 0;
261 errno = ENOENT; /* Transfer syntax is not defined for this type. */
267 errno = ENOENT; /* Randomization doesn't make sense on output. */
270 #if !defined(ASN_DISABLE_BER_SUPPORT)
272 /* BER is a superset of DER. */
275 if(td->op->der_encoder) {
276 er = der_encode(td, sptr, callback, callback_key);
277 if(er.encoded == -1) {
278 if(er.failed_type && er.failed_type->op->der_encoder) {
279 errno = EBADF; /* Structure has incorrect form. */
281 errno = ENOENT; /* DER is not defined for this type. */
285 errno = ENOENT; /* Transfer syntax is not defined for this type. */
290 errno = ENOENT; /* Transfer syntax is not defined for any type. */
296 errno = ENOENT; /* BER is not defined. */
299 #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
301 #if !defined(ASN_DISABLE_OER_SUPPORT)
303 /* CANONICAL-OER is a superset of BASIC-OER. */
305 case ATS_CANONICAL_OER:
306 if(td->op->oer_encoder) {
307 er = oer_encode(td, sptr, callback, callback_key);
308 if(er.encoded == -1) {
309 if(er.failed_type && er.failed_type->op->oer_encoder) {
310 errno = EBADF; /* Structure has incorrect form. */
312 errno = ENOENT; /* OER is not defined for this type. */
316 errno = ENOENT; /* Transfer syntax is not defined for this type. */
322 case ATS_CANONICAL_OER:
323 errno = ENOENT; /* OER is not defined. */
326 #endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
328 #if !defined(ASN_DISABLE_UPER_SUPPORT)
329 case ATS_UNALIGNED_BASIC_PER:
330 /* CANONICAL-UPER is a superset of BASIC-UPER. */
332 case ATS_UNALIGNED_CANONICAL_PER:
333 if(td->op->uper_encoder) {
334 er = uper_encode(td, 0, sptr, callback, callback_key);
335 if(er.encoded == -1) {
336 if(er.failed_type && er.failed_type->op->uper_encoder) {
337 errno = EBADF; /* Structure has incorrect form. */
339 errno = ENOENT; /* UPER is not defined for this type. */
342 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
343 if(er.encoded == 0) {
344 /* Enforce "Complete Encoding" of X.691 #11.1 */
345 if(callback("\0", 1, callback_key) < 0) {
349 er.encoded = 8; /* Exactly 8 zero bits is added. */
351 /* Convert bits into bytes */
352 er.encoded = (er.encoded + 7) >> 3;
355 errno = ENOENT; /* Transfer syntax is not defined for this type. */
360 case ATS_UNALIGNED_BASIC_PER:
361 case ATS_UNALIGNED_CANONICAL_PER:
362 errno = ENOENT; /* UPER is not defined. */
365 #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
366 #if !defined(ASN_DISABLE_APER_SUPPORT)
367 case ATS_ALIGNED_BASIC_PER:
368 /* CANONICAL-APER is a superset of BASIC-APER. */
370 case ATS_ALIGNED_CANONICAL_PER:
371 if(td->op->aper_encoder) {
372 er = aper_encode(td, 0, sptr, callback, callback_key);
373 if(er.encoded == -1) {
374 if(er.failed_type && er.failed_type->op->aper_encoder) {
375 errno = EBADF; /* Structure has incorrect form. */
377 errno = ENOENT; /* APER is not defined for this type. */
380 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
381 if(er.encoded == 0) {
382 /* Enforce "Complete Encoding" of X.691 #11.1 */
383 if(callback("\0", 1, callback_key) < 0) {
387 er.encoded = 8; /* Exactly 8 zero bits is added. */
389 /* Convert bits into bytes */
390 er.encoded = (er.encoded + 7) >> 3;
393 errno = ENOENT; /* Transfer syntax is not defined for this type. */
398 case ATS_ALIGNED_BASIC_PER:
399 case ATS_ALIGNED_CANONICAL_PER:
400 errno = ENOENT; /* APER is not defined. */
403 #endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
405 #if !defined(ASN_DISABLE_XER_SUPPORT)
407 /* CANONICAL-XER is a superset of BASIC-XER. */
408 xer_flags &= ~XER_F_CANONICAL;
409 xer_flags |= XER_F_BASIC;
411 case ATS_CANONICAL_XER:
412 if(td->op->xer_encoder) {
413 er = xer_encode(td, sptr, xer_flags, callback, callback_key);
414 if(er.encoded == -1) {
415 if(er.failed_type && er.failed_type->op->xer_encoder) {
416 errno = EBADF; /* Structure has incorrect form. */
418 errno = ENOENT; /* XER is not defined for this type. */
422 errno = ENOENT; /* Transfer syntax is not defined for this type. */
428 case ATS_CANONICAL_XER:
429 errno = ENOENT; /* XER is not defined. */
432 #endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
434 #if !defined(ASN_DISABLE_JER_SUPPORT)
436 if(td->op->jer_encoder) {
437 er = jer_encode(td, sptr, callback, callback_key);
438 if(er.encoded == -1) {
439 if(er.failed_type && er.failed_type->op->jer_encoder) {
440 errno = EBADF; /* Structure has incorrect form. */
442 errno = ENOENT; /* JER is not defined for this type. */
446 errno = ENOENT; /* Transfer syntax is not defined for this type. */
450 #endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
460 asn_decode(const asn_codec_ctx_t *opt_codec_ctx,
461 enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,
462 void **sptr, const void *buffer, size_t size) {
463 if(!td || !td->op || !sptr || (size && !buffer)) {
469 case ATS_NONSTANDARD_PLAINTEXT:
475 #if !defined(ASN_DISABLE_RFILL_SUPPORT)
476 if(!td->op->random_fill) {
479 if(asn_random_fill(td, sptr, 16000) == 0) {
480 asn_dec_rval_t ret = {RC_OK, 0};
490 #endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
494 #if !defined(ASN_DISABLE_BER_SUPPORT)
495 return ber_decode(opt_codec_ctx, td, sptr, buffer, size);
499 #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
502 case ATS_CANONICAL_OER:
503 #if !defined(ASN_DISABLE_OER_SUPPORT)
504 return oer_decode(opt_codec_ctx, td, sptr, buffer, size);
508 #endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
510 case ATS_UNALIGNED_BASIC_PER:
511 case ATS_UNALIGNED_CANONICAL_PER:
512 #if !defined(ASN_DISABLE_UPER_SUPPORT)
513 return uper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
517 #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
519 case ATS_ALIGNED_BASIC_PER:
520 case ATS_ALIGNED_CANONICAL_PER:
521 #if !defined(ASN_DISABLE_APER_SUPPORT)
522 return aper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
526 #endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
529 case ATS_CANONICAL_XER:
530 #if !defined(ASN_DISABLE_XER_SUPPORT)
531 return xer_decode(opt_codec_ctx, td, sptr, buffer, size);
535 #endif /* !defined(ASN_DISABLE_XER_SUPPORT) */