X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/8e80bb9cec2c90dd61f810fb1525932a434288eb..16e9905f82947dd471c09382122d8150ba6fda1a:/libs/smux/per_encoder.c diff --git a/libs/smux/per_encoder.c b/libs/smux/per_encoder.c index 47f3c916..86aec4ea 100644 --- a/libs/smux/per_encoder.c +++ b/libs/smux/per_encoder.c @@ -2,11 +2,49 @@ #include #include -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 int _uper_encode_flush_outp(asn_per_outp_t *po); + +static int +ignore_output(const void *data, size_t size, void *app_key) { + (void)data; + (void)size; + (void)app_key; + return 0; +} 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); +uper_encode(const asn_TYPE_descriptor_t *td, + const asn_per_constraints_t *constraints, const 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->op->uper_encoder) + ASN__ENCODE_FAILED; /* PER is not compiled in */ + + po.buffer = po.tmpspace; + po.nboff = 0; + po.nbits = 8 * sizeof(po.tmpspace); + po.output = cb ? cb : ignore_output; + po.op_key = app_key; + po.flushed_bytes = 0; + + er = td->op->uper_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(_uper_encode_flush_outp(&po)) ASN__ENCODE_FAILED; + } + + return er; } /* @@ -30,15 +68,17 @@ static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) { } asn_enc_rval_t -uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) { - enc_to_buf_arg key; +uper_encode_to_buffer(const asn_TYPE_descriptor_t *td, + const asn_per_constraints_t *constraints, + const void *sptr, void *buffer, size_t buffer_size) { + enc_to_buf_arg key; - key.buffer = buffer; - key.left = buffer_size; + key.buffer = buffer; + key.left = buffer_size; - if(td) ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name); + if(td) ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name); - return uper_encode_internal(td, 0, sptr, encode_to_buffer_cb, &key); + return uper_encode(td, constraints, sptr, encode_to_buffer_cb, &key); } typedef struct enc_dyn_arg { @@ -48,30 +88,38 @@ typedef struct enc_dyn_arg { } enc_dyn_arg; static int encode_dyn_cb(const void *buffer, size_t size, void *key) { - enc_dyn_arg *arg = key; - if(arg->length + size >= arg->allocated) { - void *p; - arg->allocated = arg->allocated ? (arg->allocated << 2) : size; - p = REALLOC(arg->buffer, arg->allocated); - if(!p) { - FREEMEM(arg->buffer); - memset(arg, 0, sizeof(*arg)); - return -1; - } - arg->buffer = p; - } - memcpy(((char *)arg->buffer) + arg->length, buffer, size); - arg->length += size; - return 0; + enc_dyn_arg *arg = key; + if(arg->length + size >= arg->allocated) { + size_t new_size = arg->allocated ? arg->allocated : 8; + void *p; + + do { + new_size <<= 2; + } while(arg->length + size >= new_size); + + p = REALLOC(arg->buffer, new_size); + if(!p) { + FREEMEM(arg->buffer); + memset(arg, 0, sizeof(*arg)); + return -1; + } + arg->buffer = p; + arg->allocated = new_size; + } + memcpy(((char *)arg->buffer) + arg->length, buffer, size); + arg->length += size; + return 0; } ssize_t -uper_encode_to_new_buffer(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, void **buffer_r) { - asn_enc_rval_t er; +uper_encode_to_new_buffer(const asn_TYPE_descriptor_t *td, + const asn_per_constraints_t *constraints, + const void *sptr, void **buffer_r) { + asn_enc_rval_t er; enc_dyn_arg key; memset(&key, 0, sizeof(key)); - er = uper_encode_internal(td, constraints, sptr, encode_dyn_cb, &key); + er = uper_encode(td, constraints, sptr, encode_dyn_cb, &key); switch(er.encoded) { case -1: FREEMEM(key.buffer); @@ -112,40 +160,6 @@ _uper_encode_flush_outp(asn_per_outp_t *po) { 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; - asn_enc_rval_t er; - - /* - * Invoke type-specific encoder. - */ - if(!td || !td->uper_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->uper_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(_uper_encode_flush_outp(&po)) - ASN__ENCODE_FAILED; - } - - return er; + return po->output(po->tmpspace, buf - po->tmpspace, po->op_key); }