diff options
Diffstat (limited to 'src/per_encoder.c')
-rw-r--r-- | src/per_encoder.c | 95 |
1 files changed, 94 insertions, 1 deletions
diff --git a/src/per_encoder.c b/src/per_encoder.c index f4bace0..02dc3a2 100644 --- a/src/per_encoder.c +++ b/src/per_encoder.c @@ -4,6 +4,7 @@ static asn_enc_rval_t uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *, void *sptr, asn_app_consume_bytes_f *cb, void *app_key); +static asn_enc_rval_t aper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *, void *sptr, asn_app_consume_bytes_f *cb, void *app_key); asn_enc_rval_t uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) { return uper_encode_internal(td, 0, sptr, cb, app_key); @@ -41,6 +42,18 @@ uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_ return uper_encode_internal(td, 0, sptr, encode_to_buffer_cb, &key); } +asn_enc_rval_t +aper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) { + enc_to_buf_arg key; + + key.buffer = buffer; + key.left = buffer_size; + + if(td) ASN_DEBUG("Encoding \"%s\" using ALIGNED PER", td->name); + + return aper_encode_internal(td, 0, sptr, encode_to_buffer_cb, &key); +} + typedef struct enc_dyn_arg { void *buffer; size_t length; @@ -88,11 +101,40 @@ uper_encode_to_new_buffer(asn_TYPE_descriptor_t *td, asn_per_constraints_t *cons } default: *buffer_r = key.buffer; - ASN_DEBUG("Complete encoded in %d bits", er.encoded); + ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded); return ((er.encoded + 7) >> 3); } } +ssize_t +aper_encode_to_new_buffer(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, void **buffer_r) { + asn_enc_rval_t er; + enc_dyn_arg key; + + memset(&key, 0, sizeof(key)); + + er = aper_encode_internal(td, constraints, sptr, encode_dyn_cb, &key); + switch(er.encoded) { + case -1: + FREEMEM(key.buffer); + return -1; + case 0: + FREEMEM(key.buffer); + key.buffer = MALLOC(1); + if(key.buffer) { + *(char *)key.buffer = '\0'; + *buffer_r = key.buffer; + return 1; + } else { + return -1; + } + default: + *buffer_r = key.buffer; + ASN_DEBUG("Complete encoded in %d bits", er.encoded); + return ((er.encoded + 7) >> 3); + } +} + /* * Internally useful functions. */ @@ -115,6 +157,23 @@ _uper_encode_flush_outp(asn_per_outp_t *po) { return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key); } +static int +_aper_encode_flush_outp(asn_per_outp_t *po) { + uint8_t *buf; + + if(po->nboff == 0 && po->buffer == po->tmpspace) + return 0; + + buf = po->buffer + (po->nboff >> 3); + /* Make sure we account for the last, partially filled */ + if(po->nboff & 0x07) { + buf[0] &= 0xff << (8 - (po->nboff & 0x07)); + buf++; + } + + return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key); +} + static asn_enc_rval_t uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) { asn_per_outp_t po; @@ -149,3 +208,37 @@ uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constrain return er; } +static asn_enc_rval_t +aper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) { + asn_per_outp_t po; + asn_enc_rval_t er; + + /* + * Invoke type-specific encoder. + */ + if(!td || !td->aper_encoder) + _ASN_ENCODE_FAILED; /* PER is not compiled in */ + + po.buffer = po.tmpspace; + po.nboff = 0; + po.nbits = 8 * sizeof(po.tmpspace); + po.outper = cb; + po.op_key = app_key; + po.flushed_bytes = 0; + + er = td->aper_encoder(td, constraints, sptr, &po); + if(er.encoded != -1) { + size_t bits_to_flush; + + bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff; + + /* Set number of bits encoded to a firm value */ + er.encoded = (po.flushed_bytes << 3) + bits_to_flush; + + if(_aper_encode_flush_outp(&po)) + _ASN_ENCODE_FAILED; + } + + return er; +} + |