Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / per / whole_number.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 #include <boost/integer/static_log2.hpp>
24
25 // Local Includes: Application specific classes, functions, and libraries
26 #include "asn/per/common.hpp"
27 #include "asn/per/binary_integer.hpp"
28
29 namespace asn {
30 namespace per {
31
32 /***************************************************************************************
33 * Encoding of a constrained whole number (X.691 10.5)
34 ***************************************************************************************/
35
36 template<bound_t R, class E = void>
37 struct length_determinant;
38
39 template<bound_t R>
40 struct length_determinant<R, std::enable_if_t< R == 0 > > { static constexpr bound_t value = 0; };
41
42 template<bound_t R>
43 struct length_determinant<R, std::enable_if_t< R == 1 > > { static constexpr bound_t value = 1; };
44
45 template<bound_t R>
46 struct length_determinant<R, std::enable_if_t< (R  > 1) > > { static constexpr bound_t value = boost::static_log2<(R - 1)>::value + 1; };
47
48 /***************************************************************************************
49 ***************************************************************************************/
50
51 template <class Range, class V, class Enable = void>
52 struct ConstrainedWholeNumber;
53
54 //Bit-field case
55 template <class Range, class V>
56 struct ConstrainedWholeNumber<Range, V, std::enable_if_t<(Range::upper_bound < (Range::lower_bound + 255))> >
57 {
58         //non-negative-binary-integer X.691 10.5
59         static void inline run(EncoderCtx& ctx, const V& val)
60         {
61                 Tools::bit_accessor::put(static_cast<u8>(val - Range::lower_bound),
62                         length_determinant<(Range::upper_bound - Range::lower_bound + 1)>::value,
63                         ctx.refBuffer());
64         }
65         static V inline run(DecoderCtx& ctx)
66         {
67                 return Range::lower_bound + Tools::bit_accessor::get(
68                         length_determinant<(Range::upper_bound - Range::lower_bound + 1)>::value,
69                         ctx.refBuffer());
70         }
71 };
72
73 //One octet case
74 template <class Range, class V>
75 struct ConstrainedWholeNumber<Range, V, std::enable_if_t<(Range::upper_bound == (Range::lower_bound + 255))> >
76 {
77         //non-negative-binary-integer X.691 10.5
78         static void inline run(EncoderCtx& ctx, const V& val)
79         {
80                 Tools::bit_accessor::padByte(ctx.refBuffer());
81                 ctx.refBuffer().putByte(static_cast<u8>(val - Range::lower_bound));
82         }
83         static V inline run(DecoderCtx& ctx)
84         {
85                 V rval = 0;
86                 Tools::bit_accessor::padByte(ctx.refBuffer());
87                 u8 const* data = ctx.refBuffer().getBytes(1);
88                 if (data)
89                         rval = Range::lower_bound + data[0];
90                 return rval;
91         }
92 };
93
94 //Two octets case
95 template <class Range, class V>
96 struct ConstrainedWholeNumber<Range, V, std::enable_if_t<(Range::upper_bound > (Range::lower_bound + 255)) && (Range::upper_bound <= (Range::lower_bound + 65535))> >
97 {
98         //non-negative-binary-integer X.691 10.5
99         static void inline run(EncoderCtx& ctx, const V& v)
100         {
101                 u64 val = static_cast<u64>(v - Range::lower_bound);
102                 Tools::bit_accessor::padByte(ctx.refBuffer());
103                 ctx.refBuffer().putByte((u8)(val >> 8));
104                 ctx.refBuffer().putByte((u8)val);
105         }
106         static V inline run(DecoderCtx& ctx)
107         {
108                 V rval = 0;
109                 Tools::bit_accessor::padByte(ctx.refBuffer());
110                 u8 const* data = ctx.refBuffer().getBytes(2);
111                 if (data) {
112                         rval = data[0];
113                         rval = rval << 8;
114                         rval |= data[1];
115                         rval += Range::lower_bound;
116                 }
117                 return rval;
118         }
119 };
120
121 //Indefinite case
122 template <class Range, class V>
123 struct ConstrainedWholeNumber<Range, V, std::enable_if_t< (Range::upper_bound > Range::lower_bound + 65535) > >
124 {
125         struct NormalizedValueRange
126         {
127                 using boundary_type = typename Range::boundary_type;
128                 static constexpr bool extended = Range::extended;
129                 static constexpr boundary_type lower_bound = 0;
130                 static constexpr boundary_type upper_bound = Range::upper_bound - Range::lower_bound;
131         };
132         
133         //non-negative-binary-integer X.691 10.5
134         static void inline run(EncoderCtx& ctx, const V& val)
135         {
136                 NonnegativeBinaryInteger<NormalizedValueRange>::run(val - Range::lower_bound, ctx);
137         }
138         static V inline run(DecoderCtx& ctx)
139         {
140                 V rval = 0;
141                 NonnegativeBinaryInteger<NormalizedValueRange>::run(rval, ctx, false);
142                 return rval + Range::lower_bound;
143         }
144 };
145
146 } //namespace per
147 } //namespace asn