new E2AP and E2SMKPM files
[o-du/l2.git] / src / codec_utils / E2SMKPM / NativeEnumerated_oer.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 #ifndef ASN_DISABLE_OER_SUPPORT
7
8 #include <asn_internal.h>
9 #include <NativeEnumerated.h>
10 #include <errno.h>
11
12 static long
13 asn__nativeenumerated_convert(const uint8_t *b, const uint8_t *end) {
14     unsigned long value;
15
16     /* Perform the sign initialization */
17     /* Actually value = -(*b >> 7); gains nothing, yet unreadable! */
18     if((*b >> 7)) {
19         value = (unsigned long)(-1);
20     } else {
21         value = 0;
22     }
23
24     /* Conversion engine */
25     for(; b < end; b++) {
26         value = (value << 8) | *b;
27     }
28
29     return value;
30 }
31
32 asn_dec_rval_t
33 NativeEnumerated_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
34                             const asn_TYPE_descriptor_t *td,
35                             const asn_oer_constraints_t *constraints,
36                             void **nint_ptr, const void *ptr, size_t size) {
37     asn_dec_rval_t rval = {RC_OK, 0};
38     long *native = (long *)*nint_ptr;
39     const uint8_t *b = ptr;
40
41     (void)opt_codec_ctx;
42     (void)constraints;
43
44     if(size < 1) {
45         ASN__DECODE_STARVED;
46     }
47
48     if((*b & 0x80) == 0) {
49         /*
50          * X.696 (08/2015) #11.2 Short form for Enumerated.
51          */
52         if(!native) {
53             native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
54             if(!native) ASN__DECODE_FAILED;
55         }
56
57         *native = *b;
58         rval.consumed = 1;
59     } else {
60         /*
61          * X.696 (08/2015) #11.4 Long form for Enumerated.
62          */
63         size_t length = *b & 0x7f;
64         const uint8_t *bend;
65         long value;
66
67         if(length < 1 || length > sizeof(*native)) {
68             ASN__DECODE_FAILED;
69         }
70         if((1 + length) > size) {
71             ASN__DECODE_STARVED;
72         }
73         b++;
74         bend = b + length;
75
76         value = asn__nativeenumerated_convert(b, bend);
77         if(value < 0) {
78             const asn_INTEGER_specifics_t *specs =
79                 (const asn_INTEGER_specifics_t *)td->specifics;
80             if(specs && specs->field_unsigned) {
81                 ASN__DECODE_FAILED;
82             }
83         }
84
85         if(!native) {
86             native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
87             if(!native) ASN__DECODE_FAILED;
88         }
89
90         *native = value;
91
92         rval.consumed = (1 + length);
93     }
94
95     return rval;
96 }
97
98 /*
99  * Encode as Canonical OER.
100  */
101 asn_enc_rval_t
102 NativeEnumerated_encode_oer(const asn_TYPE_descriptor_t *td,
103                             const asn_oer_constraints_t *constraints,
104                             const void *sptr, asn_app_consume_bytes_f *cb,
105                             void *app_key) {
106     asn_enc_rval_t er = {0,0,0};
107     long native;
108
109     (void)constraints;
110
111     if(!sptr) ASN__ENCODE_FAILED;
112
113     native = *(const long *)sptr;
114
115     if(native >= 0 && native <= 127) {
116         /* #11.2 Short form */
117         uint8_t b = native;
118         er.encoded = 1;
119         if(cb(&b, er.encoded, app_key) < 0) {
120             ASN__ENCODE_FAILED;
121         }
122         ASN__ENCODED_OK(er);
123     } else {
124         /* #11.2 Long form */
125         uint8_t buf[1 + sizeof(native)];
126         uint8_t *b = &buf[sizeof(native)];  /* Last addressable */
127         long final_pattern = -1 * (native < 0);
128
129         for(;;) {
130             *b-- = native;
131             native >>= 8;
132             if(native == final_pattern) {
133                 if(final_pattern) {
134                     if((b[1] & 0x80)) break;
135                 } else {
136                     if(!(b[1] & 0x80)) break;
137                 }
138             }
139         }
140         *b = 0x80 | (&buf[sizeof(native)] - b);
141         er.encoded = 1 + (&buf[sizeof(native)] - b);
142         if(cb(b, er.encoded, app_key) < 0) {
143             ASN__ENCODE_FAILED;
144         }
145         ASN__ENCODED_OK(er);
146     }
147 }
148
149 #endif  /* ASN_DISABLE_OER_SUPPORT */