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 // Local Includes: Application specific classes, functions, and libraries
24 #include "asn/per/common.hpp"
30 template <class IE, class Enabler = void>
33 static void inline run(IE const& ie, EncoderCtx& ctx)
35 LengthDeterminant<typename IE::constraint_t>::run(ctx, ie.get_bitqty());
36 Tools::bit_accessor::padByte(ctx.refBuffer());
38 const u8 tail = ie.get_bitqty() % 8;
41 ctx.refBuffer().putBytes(ie.get_buffer().data(), ie.get_buffer().size() - 1);
42 u8 last_byte = *(ie.get_buffer().data() + ie.get_buffer().size() - 1);
44 last_byte <<= 8 - tail;
45 ctx.refBuffer().putBytes(&last_byte, 1);
46 ctx.refBuffer().set_begin(ctx.refBuffer().begin() - 1, tail);
50 ctx.refBuffer().putBytes(ie.get_buffer().data(), ie.get_buffer().size());
53 static void inline run(IE& ie, DecoderCtx& ctx)
55 size_t len = LengthDeterminant<typename IE::constraint_t>::run(ctx, false);
56 size_t len_bytes = (len + 7) >> 3;
57 Tools::bit_accessor::padByte(ctx.refBuffer());
58 u8 const* data_in = ctx.refBuffer().getBytes(len_bytes);
61 u8* data_out = ctx.refAllocator().alloc_bytes(len_bytes);
64 memcpy(data_out, data_in, len_bytes);
65 const u8 shift = len % 8;
68 ctx.refBuffer().set_begin(ctx.refBuffer().begin() - 1, shift);
69 data_out[len_bytes - 1] >>= 8 - shift;
71 ie.set_buffer(len, data_out);
74 ctx.refErrorCtx().allocatorNoMem(0, len_bytes);
81 struct BitstringNoExt<IE, std::enable_if_t< (IE::constraint_t::upper_bound == 0)> >
83 static void inline run(IE const& ie, EncoderCtx& ctx) {/* do nothing */ }
84 static void inline run(IE& ie, DecoderCtx& ctx) { ie.setpresent(true); }
87 //15.9 Up to 6 bits, fixed length
89 struct BitstringNoExt<IE, std::enable_if_t<
90 ((IE::constraint_t::upper_bound == IE::constraint_t::lower_bound) && (IE::constraint_t::upper_bound <= 8) && (IE::constraint_t::upper_bound > 0))
93 static void inline run(IE const& ie, EncoderCtx& ctx)
95 Tools::bit_accessor::put((static_cast<u8>(ie.get_buffer().data()[0])) & (0xFF >> (8 - IE::constraint_t::upper_bound)),
96 IE::constraint_t::upper_bound, ctx.refBuffer());
98 static void inline run(IE& ie, DecoderCtx& ctx)
100 u8 * data = ctx.refAllocator().alloc_bytes(1);
103 data[0] = Tools::bit_accessor::get(IE::constraint_t::upper_bound, ctx.refBuffer());
104 ie.set_buffer(IE::constraint_t::upper_bound, data);
107 ctx.refErrorCtx().allocatorNoMem(0, 1);
111 struct BitstringNoExt<IE, std::enable_if_t<
112 ((IE::constraint_t::upper_bound == IE::constraint_t::lower_bound) && (IE::constraint_t::upper_bound <= 16) && (IE::constraint_t::upper_bound > 8))
115 static void inline run(IE const& ie, EncoderCtx& ctx)
117 Tools::bit_accessor::put(ie.get_buffer().data()[0], 8, ctx.refBuffer());
118 Tools::bit_accessor::put((static_cast<u8>(ie.get_buffer().data()[1])) & (0xFF >> (16 - IE::constraint_t::upper_bound)),
119 IE::constraint_t::upper_bound - 8, ctx.refBuffer());
121 static void inline run(IE& ie, DecoderCtx& ctx)
123 u8 * data = ctx.refAllocator().alloc_bytes(2);
126 data[0] = Tools::bit_accessor::get(8, ctx.refBuffer());
127 data[1] = Tools::bit_accessor::get(IE::constraint_t::upper_bound - 8, ctx.refBuffer());
128 ie.set_buffer(IE::constraint_t::upper_bound, data);
131 ctx.refErrorCtx().allocatorNoMem(0, 2);
135 //15.10 More than 6 bits, up to 64K bits, fixed length
137 struct BitstringNoExt<IE, std::enable_if_t<
138 ((IE::constraint_t::upper_bound == IE::constraint_t::lower_bound) && (IE::constraint_t::upper_bound < 65536) && (IE::constraint_t::upper_bound > 16))
141 constexpr static size_t len_bytes = (IE::constraint_t::upper_bound + 7) >> 3;
143 static void inline run(IE const& ie, EncoderCtx& ctx)
145 Tools::bit_accessor::padByte(ctx.refBuffer());
146 if (ie.get_buffer().size() != len_bytes)
148 ctx.refErrorCtx().sizeRangeError(ie.get_buffer().size(), len_bytes, len_bytes);
152 const u8 tail = ie.get_bitqty() % 8;
155 ctx.refBuffer().putBytes(ie.get_buffer().data(), ie.get_buffer().size() - 1);
156 u8 last_byte = *(ie.get_buffer().data() + ie.get_buffer().size() - 1);
157 last_byte <<= 8 - tail;
158 ctx.refBuffer().putBytes(&last_byte, 1);
159 ctx.refBuffer().set_begin(ctx.refBuffer().begin() - 1, tail);
163 ctx.refBuffer().putBytes(ie.get_buffer().data(), ie.get_buffer().size());
167 static void inline run(IE& ie, DecoderCtx& ctx)
169 Tools::bit_accessor::padByte(ctx.refBuffer());
170 u8 const* data_in = ctx.refBuffer().getBytes(len_bytes);
173 u8* data_out = ctx.refAllocator().alloc_bytes(len_bytes);
176 memcpy(data_out, data_in, len_bytes);
177 const u8 shift = IE::constraint_t::upper_bound % 8;
180 ctx.refBuffer().set_begin(ctx.refBuffer().begin() - 1, shift);
181 data_out[len_bytes - 1] >>= 8 - shift;
183 ie.set_buffer(IE::constraint_t::upper_bound, data_out);
186 ctx.refErrorCtx().allocatorNoMem(0, len_bytes);
191 /**************************************************/
193 template <class IE, class Enabler = void>
196 //15.6 : Extension present
198 struct Bitstring<IE, std::enable_if_t< (IE::constraint_t::extended == true)> >
200 static void inline run(IE const& ie, EncoderCtx& ctx)
203 if (ie.get_bitqty() <= IE::constraint_t::upper_bound && ie.get_bitqty() >= IE::constraint_t::lower_bound)
205 Tools::bit_accessor::put(0, 1, ctx.refBuffer());
206 BitstringNoExt<IE>::run(ie, ctx);
210 Tools::bit_accessor::put(1, 1, ctx.refBuffer());
211 Tools::bit_accessor::padByte(ctx.refBuffer());
212 LengthDeterminant<typename IE::constraint_t>::run(ctx, ie.get_bitqty());
213 Tools::bit_accessor::padByte(ctx.refBuffer());
214 const u8 tail = ie.get_bitqty() % 8;
217 ctx.refBuffer().putBytes(ie.get_buffer().data(), ie.get_buffer().size() - 1);
218 u8 last_byte = *(ie.get_buffer().data() + ie.get_buffer().size() - 1);
220 last_byte <<= 8 - tail;
222 ctx.refBuffer().putBytes(&last_byte, 1);
223 ctx.refBuffer().set_begin(ctx.refBuffer().begin() - 1, tail);
227 ctx.refBuffer().putBytes(ie.get_buffer().data(), ie.get_buffer().size());
231 static void inline run(IE& ie, DecoderCtx& ctx)
233 u8 ext = Tools::bit_accessor::get(1, ctx.refBuffer());
236 Tools::bit_accessor::padByte(ctx.refBuffer());
237 const size_t len = LengthDeterminant<typename IE::constraint_t>::run(ctx, true);
238 const size_t len_bytes = (len + 7) >> 3;
239 Tools::bit_accessor::padByte(ctx.refBuffer());
240 u8 const* data_in = ctx.refBuffer().getBytes(len_bytes);
243 u8* data_out = ctx.refAllocator().alloc_bytes(len_bytes);
246 memcpy(data_out, data_in, len_bytes);
247 const u8 shift = len % 8;
250 ctx.refBuffer().set_begin(ctx.refBuffer().begin() - 1, shift);
251 data_out[len_bytes - 1] >>= 8 - shift;
253 ie.set_buffer(len, data_out);
256 ctx.refErrorCtx().allocatorNoMem(0, len_bytes);
260 BitstringNoExt<IE>::run(ie, ctx);
264 //15.7 : No extension
266 struct Bitstring<IE, std::enable_if_t< (IE::constraint_t::extended == false)> >
268 static void inline run(IE const& ie, EncoderCtx& ctx)
270 BitstringNoExt<IE>::run(ie, ctx);
272 static void inline run(IE& ie, DecoderCtx& ctx)
274 BitstringNoExt<IE>::run(ie, ctx);