X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?p=sim%2Fe2-interface.git;a=blobdiff_plain;f=e2sim%2Fasn1c%2FNativeReal_ber.c;fp=e2sim%2Fasn1c%2FNativeReal_ber.c;h=923c3df42d87e06c2cd053530ea6524b508a6ef0;hp=0000000000000000000000000000000000000000;hb=f5900596513e4359fc839ba361da085674e90b68;hpb=215d350dbe06a4c7ee370815f26128a7f7e160cb diff --git a/e2sim/asn1c/NativeReal_ber.c b/e2sim/asn1c/NativeReal_ber.c new file mode 100644 index 0000000..923c3df --- /dev/null +++ b/e2sim/asn1c/NativeReal_ber.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2017 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * Decode REAL type. + */ +asn_dec_rval_t +NativeReal_decode_ber(const asn_codec_ctx_t *opt_codec_ctx, + const asn_TYPE_descriptor_t *td, void **sptr, + const void *buf_ptr, size_t size, int tag_mode) { + asn_dec_rval_t rval; + ber_tlv_len_t length; + + ASN_DEBUG("Decoding %s as REAL (tm=%d)", td->name, tag_mode); + + /* + * Check tags. + */ + rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, tag_mode, 0, + &length, 0); + if(rval.code != RC_OK) return rval; + assert(length >= 0); /* Ensured by ber_check_tags */ + + ASN_DEBUG("%s length is %d bytes", td->name, (int)length); + + /* + * Make sure we have this length. + */ + buf_ptr = ((const char *)buf_ptr) + rval.consumed; + size -= rval.consumed; + if(length > (ber_tlv_len_t)size) { + rval.code = RC_WMORE; + rval.consumed = 0; + return rval; + } + + /* + * ASN.1 encoded REAL: buf_ptr, length + * Fill the Dbl, at the same time checking for overflow. + * If overflow occurred, return with RC_FAIL. + */ + { + uint8_t scratch[24]; /* Longer than %.16f in decimal */ + REAL_t tmp; + double d; + int ret; + + if((size_t)length < sizeof(scratch)) { + tmp.buf = scratch; + tmp.size = length; + } else { + /* This rarely happens: impractically long value */ + tmp.buf = CALLOC(1, length + 1); + tmp.size = length; + if(!tmp.buf) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + } + + memcpy(tmp.buf, buf_ptr, length); + tmp.buf[length] = '\0'; + + ret = asn_REAL2double(&tmp, &d); + if(tmp.buf != scratch) FREEMEM(tmp.buf); + if(ret) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + + if(NativeReal__set(td, sptr, d) < 0) + ASN__DECODE_FAILED; + } + + rval.code = RC_OK; + rval.consumed += length; + + ASN_DEBUG("Took %ld/%ld bytes to encode %s", (long)rval.consumed, + (long)length, td->name); + + return rval; +} + +/* + * Encode the NativeReal using the standard REAL type DER encoder. + */ +asn_enc_rval_t +NativeReal_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + double d = NativeReal__get_double(td, sptr); + asn_enc_rval_t erval = {0,0,0}; + REAL_t tmp; + + /* Prepare a temporary clean structure */ + memset(&tmp, 0, sizeof(tmp)); + + if(asn_double2REAL(&tmp, d)) + ASN__ENCODE_FAILED; + + /* Encode a fake REAL */ + erval = der_encode_primitive(td, &tmp, tag_mode, tag, cb, app_key); + if(erval.encoded == -1) { + assert(erval.structure_ptr == &tmp); + erval.structure_ptr = sptr; + } + + /* Free possibly allocated members of the temporary structure */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp); + + return erval; +}