488a83041a6365178321dd84cd50dd752ec65935
[sim/e2-interface.git] / e2sim / previous / e2apv1sim / e2sim / src / ASN1 / asn / per / length.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 #include <cmath>
23
24 // Local Includes: Application specific classes, functions, and libraries
25 #include "asn/per/common.hpp"
26 #include "asn/per/whole_number.hpp"
27
28 namespace asn {
29 namespace per {
30
31 /********************************************************************************
32 * Encoding of a length determinant (X.691 10.9)
33 *********************************************************************************/
34
35 template <class Range, class Enable = void>
36 struct LengthDeterminant;
37
38 struct LengthDeterminantDefault //Unconstrained length
39 {
40         static u8 bytes_needed(size_t len)
41         {
42                 if (len <= 127)
43                         return 1;
44                 return 2;
45         }
46
47         static void run(EncoderCtx& ctx, size_t len)
48         {
49                 if (len <= 127)
50                 {
51                         Tools::bit_accessor::padByte(ctx.refBuffer());
52                         ctx.refBuffer().putByte(static_cast<u8>(len));
53                 }
54                 else if (len < 16384)
55                 {
56                         Tools::bit_accessor::padByte(ctx.refBuffer());
57                         len += 0x8000;
58                         ctx.refBuffer().putByte(static_cast<u8>(len >> 8));
59                         ctx.refBuffer().putByte(static_cast<u8>(len));
60                 }
61                 else
62                 {
63                         //todo: 10.9.3.8.1 for len >= 16K
64                 }
65         }
66         static size_t run(DecoderCtx& ctx)
67         {
68                 size_t rval = 0;
69                 Tools::bit_accessor::padByte(ctx.refBuffer());
70
71                 u8 const* data = ctx.refBuffer().getBytes(1);
72                 if (data)
73                 {
74                         if (*data & 0x80)
75                         {
76                                 rval = (*data & 0x7F) << 8;
77                                 data = ctx.refBuffer().getBytes(1);
78                                 if (data)
79                                         rval |= *data;
80                         }
81                         else
82                                 rval = *data;
83                 }
84                 return rval;
85         }
86 };
87
88 //10.9.3.3
89 template <class Range>
90 struct LengthDeterminant<Range, std::enable_if_t<
91         ((Range::upper_bound < 65536) && (Range::extended == false))
92 >>
93 {
94         static void run(EncoderCtx& ctx, size_t len)
95         {
96                 ConstrainedWholeNumber<Range, size_t>::run(ctx, len);
97         }
98         static size_t inline run(DecoderCtx& ctx, bool extended_len)
99         {
100                 return ConstrainedWholeNumber<Range, size_t>::run(ctx);
101         }
102 };
103 template <class Range>
104 struct LengthDeterminant<Range, std::enable_if_t<
105         ((Range::upper_bound < 65536) && (Range::extended == true))
106 >>
107 {
108         static void run(EncoderCtx& ctx, size_t len)
109         {
110                 if (len > Range::upper_bound || len < Range::lower_bound)
111                         LengthDeterminantDefault::run(ctx, len);
112                 else
113                         ConstrainedWholeNumber<Range, size_t>::run(ctx, len);
114         }
115         static size_t inline run(DecoderCtx& ctx, bool extended_len)
116         {
117                 if (extended_len)
118                         return LengthDeterminantDefault::run(ctx);
119
120                 return ConstrainedWholeNumber<Range, size_t>::run(ctx);
121         }
122 };
123
124 template <class Range>
125 struct LengthDeterminant<Range, std::enable_if_t< (Range::upper_bound >= 65536) > >
126 {
127         static void run(EncoderCtx& ctx, size_t len)
128         {
129                 LengthDeterminantDefault::run(ctx, len);
130         }
131         static size_t inline run(DecoderCtx& ctx, bool extended_len)
132         {
133                 return LengthDeterminantDefault::run(ctx);
134         }
135 };
136
137 //10.9.3.4 : for "normally small length". bitmaps, sequence types
138 template <bound_t Length, class Enable = void>
139 struct NormallySmallLength;
140
141 template <bound_t Length>
142 struct NormallySmallLength<Length, std::enable_if_t<(Length <= 64)> >
143 {
144         static_assert(Length > 0, "NormallySmallLength must be > 0");
145
146         static void run(EncoderCtx& ctx)
147         {
148                 Tools::bit_accessor::put((u8)(Length - 1), 7, ctx.refBuffer());
149         }
150         static size_t run(DecoderCtx& ctx)
151         {
152                 u8 ext = Tools::bit_accessor::get(1, ctx.refBuffer());
153                 if (ext)
154                         return LengthDeterminantDefault::run(ctx);
155                 return Tools::bit_accessor::get(6, ctx.refBuffer()) + 1;
156         }
157 };
158
159 template <bound_t Length>
160 struct NormallySmallLength<Length, std::enable_if_t<(Length > 64)> >
161 {
162         static void run(EncoderCtx& ctx)
163         {
164                 Tools::bit_accessor::put(1, 1, ctx.refBuffer());
165                 LengthDeterminantDefault::run(ctx, Length);
166         }
167 };
168
169 /*
170 * BinaryIntegerLength
171 */
172
173 template<bound_t N, class Enable = void>
174 struct NBytes
175 {
176         static constexpr bound_t value = std::log2( N ) / 8 + 1;
177 };
178
179 template<bound_t N>
180 struct NBytes<N, std::enable_if_t< (N ==  0) > >
181 {
182         static constexpr bound_t value = 1;
183 };
184
185 template<bound_t B1, bound_t B2, class Enable = void>
186 struct NRange
187 {
188         static constexpr bound_t lower_bound = B1;
189         static constexpr bound_t upper_bound = B2;
190 };
191
192 template<bound_t B1, bound_t B2>
193 struct NRange<B1, B2, std::enable_if_t<(B2 < B1)> >
194 {
195         static constexpr bound_t lower_bound = B2;
196         static constexpr bound_t upper_bound = B1;
197 };
198
199 template <class Range, class Enable>
200 struct BinaryIntegerLength
201 {
202         typedef NRange<
203                 NBytes<Range::lower_bound>::value,
204                 NBytes<Range::upper_bound>::value
205         > nrange;
206         
207         using boundary_type = typename Range::boundary_type;
208         static constexpr bool extended = Range::extended;
209         static constexpr bound_t lower_bound = nrange::lower_bound;
210         static constexpr bound_t upper_bound = nrange::upper_bound;
211         
212         static void run(EncoderCtx& ctx, size_t len)
213         {
214                 LengthDeterminant<BinaryIntegerLength>::run(ctx, len);
215         }
216         static size_t inline run(DecoderCtx& ctx, bool extended_len)
217         {
218                 return LengthDeterminant<BinaryIntegerLength>::run(ctx, extended_len);
219         }
220 };
221
222 template <class Range>
223 struct BinaryIntegerLength<Range, std::enable_if_t<
224         (Range::type == constraint_type::SEMICONSTRAINED) || (Range::type == constraint_type::SEMICONSTRAINED_EXTENDED)
225 >>
226 {
227         static void run(EncoderCtx& ctx, size_t len)
228         {
229                 LengthDeterminantDefault::run(ctx, len);
230         }
231         static size_t inline run(DecoderCtx& ctx, bool extended_len)
232         {
233                 return LengthDeterminantDefault::run(ctx);
234         }
235 };
236
237 } //namespace per
238 } //namespace asn