Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / per / binary_integer.hpp
1 #pragma once
2 /******************************************************************************
3 *
4 *   Copyright (c) 2019 AT&T Intellectual Property.
5 *   Copyright (c) 2018-2019 Nokia.
6 *
7 *   Licensed under the Apache License, Version 2.0 (the "License");
8 *   you may not use this file except in compliance with the License.
9 *   You may obtain a copy of the License at
10 *
11 *       http://www.apache.org/licenses/LICENSE-2.0
12 *
13 *   Unless required by applicable law or agreed to in writing, software
14 *   distributed under the License is distributed on an "AS IS" BASIS,
15 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 *   See the License for the specific language governing permissions and
17 *   limitations under the License.
18 *
19 ******************************************************************************/
20
21 // Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
22
23 // Local Includes: Application specific classes, functions, and libraries
24 #include "asn/per/common.hpp"
25 #include "asn/per/length.hpp"
26
27 namespace asn {
28 namespace per {
29
30 template <class Range, class Enable = void>
31 struct BinaryIntegerLength;
32
33 /***************************************************************************************
34 * Encoding of a non-negative-binary-integer (X.691 10.3)
35 ***************************************************************************************/
36 template <class Range>
37 struct NonnegativeBinaryInteger
38 {
39         static void inline run(u64 val, EncoderCtx& ctx)
40         {
41                 if(val)
42                 {
43                         size_t const len = sizeof(val) - (__builtin_clzll(val) >> 3);
44                         
45                         BinaryIntegerLength< Range >::run(ctx, len);
46                         Tools::bit_accessor::padByte(ctx.refBuffer());
47                                         
48                         u8 buff[len];
49                         size_t shift = (len - 1) << 3;
50                         for(size_t i = 0; i < len; ++i)
51                         {
52                                 buff[i] = static_cast<uint8_t>(val >> shift);
53                                 shift -= 8;
54                         }
55                         
56                         ctx.refBuffer().putBytes(buff, len);
57                 }
58                 else
59                 {
60                         BinaryIntegerLength< Range >::run(ctx, 1);
61                         Tools::bit_accessor::padByte(ctx.refBuffer());
62                         ctx.refBuffer().putByte(0);
63                 }
64         }
65         template<typename T>
66         static void inline run(T& retval, DecoderCtx& ctx, bool extended_val)
67         {
68                 retval = 0;
69                 size_t len = (size_t)BinaryIntegerLength< Range >::run(ctx, extended_val);
70                 Tools::bit_accessor::padByte(ctx.refBuffer());
71                 u8 const* data = ctx.refBuffer().getBytes(len);
72
73                 if (data)
74                 {
75                         for (size_t i = 0; i < len; ++i)
76                         {
77                                 retval = retval << 8;
78                                 retval |= data[i];
79                         }
80                 }
81         }
82 };
83
84 /***************************************************************************************
85 * Encoding of a 2's-complement-binary-integer (X.691 10.4)
86 ***************************************************************************************/
87
88 template <class IE>
89 struct TwosComplementBinaryInteger
90 {
91         static void inline run(IE const& ie, EncoderCtx& ctx)
92         {
93                 Tools::bit_accessor::padByte(ctx.refBuffer());
94
95                 u64 val = ie.get();
96                 u64 tval = val;
97                 u64 mask = static_cast<u64>(-128);
98                 u8 len = 1;
99                 u8 i = 7;
100
101                 u8 buf[8];
102
103                 while (len < 8)
104                 {
105                         buf[i] = static_cast<u8>(tval);
106                         if (!(val & mask) || (val & mask) == mask)
107                                 break;
108                         mask = mask << 8;
109                         tval = tval >> 8;
110                         len++;
111                         i--;
112                 }
113
114                 ctx.refBuffer().putByte(len) && ctx.refBuffer().putBytes(&buf[i], len);
115         }
116         static void inline run(IE& ie, DecoderCtx& ctx)
117         {
118                 Tools::bit_accessor::padByte(ctx.refBuffer());
119
120                 u8 const* data = nullptr;
121                 typename IE::value_type val = 0;
122
123                 u8 const* len = ctx.refBuffer().getBytes(1);
124
125                 if (len && (*len) <= 8 && (data = ctx.refBuffer().getBytes(*len)))
126                 {
127                         for (u8 i = 0; i < *len; ++i)
128                         {
129                                 val = val << 8;
130                                 val |= data[i];
131                         }
132                 }
133                 ie.set(val);
134         }
135 };
136
137 /***************************************************************************************
138 * Encoding of a normally small non-negativebinary integer (X.691 10.6)
139 ***************************************************************************************/
140 template <class IE, typename TValue = typename IE::value_type>
141 struct NormallySmallNonnegativeBinaryInteger
142 {
143         static void inline run(IE const& ie, EncoderCtx& ctx, typename IE::constraint_t::boundary_type val)
144         {
145                 if (val <= 63)
146                 {
147                         Tools::bit_accessor::put(static_cast<u8>(val), 7, ctx.refBuffer()); //7 bits ('0' indicator + value)
148                 }
149                 else
150                 {
151                         Tools::bit_accessor::put(1, 1, ctx.refBuffer()); //1 bit ('1' indicator)
152                         NonnegativeBinaryInteger<typename IE::constraint_t>::run(val, ctx);
153                 }
154         }
155         static TValue inline run(DecoderCtx& ctx)
156         {
157                 u8 ext = Tools::bit_accessor::get(1, ctx.refBuffer());
158                 if (ext) {
159                         TValue rval = 0;
160                         NonnegativeBinaryInteger<typename IE::constraint_t>::run(rval, ctx, true);
161                         return rval;
162                 }
163                 return Tools::bit_accessor::get(6, ctx.refBuffer());
164         }
165 };
166
167 } //namespace per
168 } //namespace asn