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
24 // Local Includes: Application specific classes, functions, and libraries
25 #include "asn/per/common.hpp"
26 #include "asn/per/whole_number.hpp"
31 /********************************************************************************
32 * Encoding of a length determinant (X.691 10.9)
33 *********************************************************************************/
35 template <class Range, class Enable = void>
36 struct LengthDeterminant;
38 struct LengthDeterminantDefault //Unconstrained length
40 static u8 bytes_needed(size_t len)
47 static void run(EncoderCtx& ctx, size_t len)
51 Tools::bit_accessor::padByte(ctx.refBuffer());
52 ctx.refBuffer().putByte(static_cast<u8>(len));
56 Tools::bit_accessor::padByte(ctx.refBuffer());
58 ctx.refBuffer().putByte(static_cast<u8>(len >> 8));
59 ctx.refBuffer().putByte(static_cast<u8>(len));
63 //todo: 10.9.3.8.1 for len >= 16K
66 static size_t run(DecoderCtx& ctx)
69 Tools::bit_accessor::padByte(ctx.refBuffer());
71 u8 const* data = ctx.refBuffer().getBytes(1);
76 rval = (*data & 0x7F) << 8;
77 data = ctx.refBuffer().getBytes(1);
89 template <class Range>
90 struct LengthDeterminant<Range, std::enable_if_t<
91 ((Range::upper_bound < 65536) && (Range::extended == false))
94 static void run(EncoderCtx& ctx, size_t len)
96 ConstrainedWholeNumber<Range, size_t>::run(ctx, len);
98 static size_t inline run(DecoderCtx& ctx, bool extended_len)
100 return ConstrainedWholeNumber<Range, size_t>::run(ctx);
103 template <class Range>
104 struct LengthDeterminant<Range, std::enable_if_t<
105 ((Range::upper_bound < 65536) && (Range::extended == true))
108 static void run(EncoderCtx& ctx, size_t len)
110 if (len > Range::upper_bound || len < Range::lower_bound)
111 LengthDeterminantDefault::run(ctx, len);
113 ConstrainedWholeNumber<Range, size_t>::run(ctx, len);
115 static size_t inline run(DecoderCtx& ctx, bool extended_len)
118 return LengthDeterminantDefault::run(ctx);
120 return ConstrainedWholeNumber<Range, size_t>::run(ctx);
124 template <class Range>
125 struct LengthDeterminant<Range, std::enable_if_t< (Range::upper_bound >= 65536) > >
127 static void run(EncoderCtx& ctx, size_t len)
129 LengthDeterminantDefault::run(ctx, len);
131 static size_t inline run(DecoderCtx& ctx, bool extended_len)
133 return LengthDeterminantDefault::run(ctx);
137 //10.9.3.4 : for "normally small length". bitmaps, sequence types
138 template <bound_t Length, class Enable = void>
139 struct NormallySmallLength;
141 template <bound_t Length>
142 struct NormallySmallLength<Length, std::enable_if_t<(Length <= 64)> >
144 static_assert(Length > 0, "NormallySmallLength must be > 0");
146 static void run(EncoderCtx& ctx)
148 Tools::bit_accessor::put((u8)(Length - 1), 7, ctx.refBuffer());
150 static size_t run(DecoderCtx& ctx)
152 u8 ext = Tools::bit_accessor::get(1, ctx.refBuffer());
154 return LengthDeterminantDefault::run(ctx);
155 return Tools::bit_accessor::get(6, ctx.refBuffer()) + 1;
159 template <bound_t Length>
160 struct NormallySmallLength<Length, std::enable_if_t<(Length > 64)> >
162 static void run(EncoderCtx& ctx)
164 Tools::bit_accessor::put(1, 1, ctx.refBuffer());
165 LengthDeterminantDefault::run(ctx, Length);
170 * BinaryIntegerLength
173 template<bound_t N, class Enable = void>
176 static constexpr bound_t value = std::log2( N ) / 8 + 1;
180 struct NBytes<N, std::enable_if_t< (N == 0) > >
182 static constexpr bound_t value = 1;
185 template<bound_t B1, bound_t B2, class Enable = void>
188 static constexpr bound_t lower_bound = B1;
189 static constexpr bound_t upper_bound = B2;
192 template<bound_t B1, bound_t B2>
193 struct NRange<B1, B2, std::enable_if_t<(B2 < B1)> >
195 static constexpr bound_t lower_bound = B2;
196 static constexpr bound_t upper_bound = B1;
199 template <class Range, class Enable>
200 struct BinaryIntegerLength
203 NBytes<Range::lower_bound>::value,
204 NBytes<Range::upper_bound>::value
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;
212 static void run(EncoderCtx& ctx, size_t len)
214 LengthDeterminant<BinaryIntegerLength>::run(ctx, len);
216 static size_t inline run(DecoderCtx& ctx, bool extended_len)
218 return LengthDeterminant<BinaryIntegerLength>::run(ctx, extended_len);
222 template <class Range>
223 struct BinaryIntegerLength<Range, std::enable_if_t<
224 (Range::type == constraint_type::SEMICONSTRAINED) || (Range::type == constraint_type::SEMICONSTRAINED_EXTENDED)
227 static void run(EncoderCtx& ctx, size_t len)
229 LengthDeterminantDefault::run(ctx, len);
231 static size_t inline run(DecoderCtx& ctx, bool extended_len)
233 return LengthDeterminantDefault::run(ctx);