2 /******************************************************************************
4 * Copyright (c) 2019 AT&T Intellectual Property.
5 * Copyright (c) 2018-2019 Nokia.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************************/
21 // Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
23 #include <boost/integer/static_log2.hpp>
25 // Local Includes: Application specific classes, functions, and libraries
26 #include "asn/per/common.hpp"
27 #include "asn/per/binary_integer.hpp"
32 /***************************************************************************************
33 * Encoding of a constrained whole number (X.691 10.5)
34 ***************************************************************************************/
36 template<bound_t R, class E = void>
37 struct length_determinant;
40 struct length_determinant<R, std::enable_if_t< R == 0 > > { static constexpr bound_t value = 0; };
43 struct length_determinant<R, std::enable_if_t< R == 1 > > { static constexpr bound_t value = 1; };
46 struct length_determinant<R, std::enable_if_t< (R > 1) > > { static constexpr bound_t value = boost::static_log2<(R - 1)>::value + 1; };
48 /***************************************************************************************
49 ***************************************************************************************/
51 template <class Range, class V, class Enable = void>
52 struct ConstrainedWholeNumber;
55 template <class Range, class V>
56 struct ConstrainedWholeNumber<Range, V, std::enable_if_t<(Range::upper_bound < (Range::lower_bound + 255))> >
58 //non-negative-binary-integer X.691 10.5
59 static void inline run(EncoderCtx& ctx, const V& val)
61 Tools::bit_accessor::put(static_cast<u8>(val - Range::lower_bound),
62 length_determinant<(Range::upper_bound - Range::lower_bound + 1)>::value,
65 static V inline run(DecoderCtx& ctx)
67 return Range::lower_bound + Tools::bit_accessor::get(
68 length_determinant<(Range::upper_bound - Range::lower_bound + 1)>::value,
74 template <class Range, class V>
75 struct ConstrainedWholeNumber<Range, V, std::enable_if_t<(Range::upper_bound == (Range::lower_bound + 255))> >
77 //non-negative-binary-integer X.691 10.5
78 static void inline run(EncoderCtx& ctx, const V& val)
80 Tools::bit_accessor::padByte(ctx.refBuffer());
81 ctx.refBuffer().putByte(static_cast<u8>(val - Range::lower_bound));
83 static V inline run(DecoderCtx& ctx)
86 Tools::bit_accessor::padByte(ctx.refBuffer());
87 u8 const* data = ctx.refBuffer().getBytes(1);
89 rval = Range::lower_bound + data[0];
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))> >
98 //non-negative-binary-integer X.691 10.5
99 static void inline run(EncoderCtx& ctx, const V& v)
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);
106 static V inline run(DecoderCtx& ctx)
109 Tools::bit_accessor::padByte(ctx.refBuffer());
110 u8 const* data = ctx.refBuffer().getBytes(2);
115 rval += Range::lower_bound;
122 template <class Range, class V>
123 struct ConstrainedWholeNumber<Range, V, std::enable_if_t< (Range::upper_bound > Range::lower_bound + 65535) > >
125 struct NormalizedValueRange
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;
133 //non-negative-binary-integer X.691 10.5
134 static void inline run(EncoderCtx& ctx, const V& val)
136 NonnegativeBinaryInteger<NormalizedValueRange>::run(val - Range::lower_bound, ctx);
138 static V inline run(DecoderCtx& ctx)
141 NonnegativeBinaryInteger<NormalizedValueRange>::run(rval, ctx, false);
142 return rval + Range::lower_bound;