SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / NativeReal_ber.c
1 /*
2  * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3  * All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <NativeReal.h>
8 #include <REAL.h>
9
10 /*
11  * Decode REAL type.
12  */
13 asn_dec_rval_t
14 NativeReal_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
15                       const asn_TYPE_descriptor_t *td, void **sptr,
16                       const void *buf_ptr, size_t size, int tag_mode) {
17     asn_dec_rval_t rval;
18     ber_tlv_len_t length;
19
20     ASN_DEBUG("Decoding %s as REAL (tm=%d)", td->name, tag_mode);
21
22     /*
23      * Check tags.
24      */
25     rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, tag_mode, 0,
26                           &length, 0);
27     if(rval.code != RC_OK) return rval;
28     assert(length >= 0);    /* Ensured by ber_check_tags */
29
30     ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
31
32     /*
33      * Make sure we have this length.
34      */
35     buf_ptr = ((const char *)buf_ptr) + rval.consumed;
36     size -= rval.consumed;
37     if(length > (ber_tlv_len_t)size) {
38         rval.code = RC_WMORE;
39         rval.consumed = 0;
40         return rval;
41     }
42
43     /*
44      * ASN.1 encoded REAL: buf_ptr, length
45      * Fill the Dbl, at the same time checking for overflow.
46      * If overflow occurred, return with RC_FAIL.
47      */
48     {
49         uint8_t scratch[24]; /* Longer than %.16f in decimal */
50         REAL_t tmp;
51         double d;
52         int ret;
53
54         if((size_t)length < sizeof(scratch)) {
55             tmp.buf = scratch;
56             tmp.size = length;
57         } else {
58             /* This rarely happens: impractically long value */
59             tmp.buf = CALLOC(1, length + 1);
60             tmp.size = length;
61             if(!tmp.buf) {
62                 rval.code = RC_FAIL;
63                 rval.consumed = 0;
64                 return rval;
65             }
66         }
67
68         memcpy(tmp.buf, buf_ptr, length);
69         tmp.buf[length] = '\0';
70
71         ret = asn_REAL2double(&tmp, &d);
72         if(tmp.buf != scratch) FREEMEM(tmp.buf);
73         if(ret) {
74             rval.code = RC_FAIL;
75             rval.consumed = 0;
76             return rval;
77         }
78
79         if(NativeReal__set(td, sptr, d) < 0)
80             ASN__DECODE_FAILED;
81     }
82
83     rval.code = RC_OK;
84     rval.consumed += length;
85
86     ASN_DEBUG("Took %ld/%ld bytes to encode %s", (long)rval.consumed,
87               (long)length, td->name);
88
89     return rval;
90 }
91
92 /*
93  * Encode the NativeReal using the standard REAL type DER encoder.
94  */
95 asn_enc_rval_t
96 NativeReal_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
97                       int tag_mode, ber_tlv_tag_t tag,
98                       asn_app_consume_bytes_f *cb, void *app_key) {
99     double d = NativeReal__get_double(td, sptr);
100     asn_enc_rval_t erval = {0,0,0};
101     REAL_t tmp;
102
103     /* Prepare a temporary clean structure */
104     memset(&tmp, 0, sizeof(tmp));
105
106     if(asn_double2REAL(&tmp, d))
107         ASN__ENCODE_FAILED;
108
109     /* Encode a fake REAL */
110     erval = der_encode_primitive(td, &tmp, tag_mode, tag, cb, app_key);
111     if(erval.encoded == -1) {
112         assert(erval.structure_ptr == &tmp);
113         erval.structure_ptr = sptr;
114     }
115
116     /* Free possibly allocated members of the temporary structure */
117     ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
118
119     return erval;
120 }