Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / per / bstring.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
23 // Local Includes: Application specific classes, functions, and libraries
24 #include "asn/per/common.hpp"
25
26 namespace asn {
27 namespace per {
28
29 //15.11 Default
30 template <class IE, class Enabler = void>
31 struct BitstringNoExt
32 {
33         static void inline run(IE const& ie, EncoderCtx& ctx)
34         {
35                 LengthDeterminant<typename IE::constraint_t>::run(ctx, ie.get_bitqty());
36                 Tools::bit_accessor::padByte(ctx.refBuffer());
37
38                 const u8 tail = ie.get_bitqty() % 8;
39                 if (tail)
40                 {
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);
43
44                         last_byte <<= 8 - tail;
45                         ctx.refBuffer().putBytes(&last_byte, 1);
46                         ctx.refBuffer().set_begin(ctx.refBuffer().begin() - 1, tail);
47                 }
48                 else
49                 {
50                         ctx.refBuffer().putBytes(ie.get_buffer().data(), ie.get_buffer().size());
51                 }
52         }
53         static void inline run(IE& ie, DecoderCtx& ctx)
54         {
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);
59                 if (data_in)
60                 {
61                         u8* data_out = ctx.refAllocator().alloc_bytes(len_bytes);
62                         if (data_out)
63                         {
64                                 memcpy(data_out, data_in, len_bytes);
65                                 const u8 shift = len % 8;
66                                 if (shift)
67                                 {
68                                         ctx.refBuffer().set_begin(ctx.refBuffer().begin() - 1, shift);
69                                         data_out[len_bytes - 1] >>= 8 - shift;
70                                 }
71                                 ie.set_buffer(len, data_out);
72                         }
73                         else
74                                 ctx.refErrorCtx().allocatorNoMem(0, len_bytes);
75                 }
76         }
77 };
78
79 //15.8 Zero length
80 template <class IE>
81 struct BitstringNoExt<IE, std::enable_if_t<     (IE::constraint_t::upper_bound == 0)> >
82 {
83         static void inline run(IE const& ie, EncoderCtx& ctx) {/* do nothing */ }
84         static void inline run(IE& ie, DecoderCtx& ctx) { ie.setpresent(true); }
85 };
86
87 //15.9 Up to 6 bits, fixed length
88 template <class IE>
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))
91 >>
92 {
93         static void inline run(IE const& ie, EncoderCtx& ctx)
94         {
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());
97         }
98         static void inline run(IE& ie, DecoderCtx& ctx)
99         {
100                 u8 * data = ctx.refAllocator().alloc_bytes(1);
101                 if (data)
102                 {
103                         data[0] = Tools::bit_accessor::get(IE::constraint_t::upper_bound, ctx.refBuffer());
104                         ie.set_buffer(IE::constraint_t::upper_bound, data);
105                 }
106                 else
107                         ctx.refErrorCtx().allocatorNoMem(0, 1);
108         }
109 };
110 template <class IE>
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))
113 >>
114 {
115         static void inline run(IE const& ie, EncoderCtx& ctx)
116         {
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());
120         }
121         static void inline run(IE& ie, DecoderCtx& ctx)
122         {
123                 u8 * data = ctx.refAllocator().alloc_bytes(2);
124                 if (data)
125                 {
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);
129                 }
130                 else
131                         ctx.refErrorCtx().allocatorNoMem(0, 2);
132         }
133 };
134
135 //15.10 More than 6 bits, up to 64K bits, fixed length
136 template <class IE>
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))
139 >>
140 {
141         constexpr static size_t len_bytes = (IE::constraint_t::upper_bound + 7) >> 3;
142
143         static void inline run(IE const& ie, EncoderCtx& ctx)
144         {
145                 Tools::bit_accessor::padByte(ctx.refBuffer());
146                 if (ie.get_buffer().size() != len_bytes)
147                 {
148                         ctx.refErrorCtx().sizeRangeError(ie.get_buffer().size(), len_bytes, len_bytes);
149                 }
150                 else
151                 {
152                         const u8 tail = ie.get_bitqty() % 8;
153                         if (tail)
154                         {
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);
160                         }
161                         else
162                         {
163                                 ctx.refBuffer().putBytes(ie.get_buffer().data(), ie.get_buffer().size());
164                         }
165                 }
166         }
167         static void inline run(IE& ie, DecoderCtx& ctx)
168         {
169                 Tools::bit_accessor::padByte(ctx.refBuffer());
170                 u8 const* data_in = ctx.refBuffer().getBytes(len_bytes);
171                 if (data_in)
172                 {
173                         u8* data_out = ctx.refAllocator().alloc_bytes(len_bytes);
174                         if (data_out)
175                         {
176                                 memcpy(data_out, data_in, len_bytes);
177                                 const u8 shift = IE::constraint_t::upper_bound % 8;
178                                 if (shift)
179                                 {
180                                         ctx.refBuffer().set_begin(ctx.refBuffer().begin() - 1, shift);
181                                         data_out[len_bytes - 1] >>= 8 - shift;
182                                 }
183                                 ie.set_buffer(IE::constraint_t::upper_bound, data_out);
184                         }
185                         else
186                                 ctx.refErrorCtx().allocatorNoMem(0, len_bytes);
187                 }
188         }
189 };
190
191 /**************************************************/
192
193 template <class IE, class Enabler = void>
194 struct Bitstring;
195
196 //15.6 : Extension present
197 template <class IE>
198 struct Bitstring<IE, std::enable_if_t< (IE::constraint_t::extended == true)> >
199 {
200         static void inline run(IE const& ie, EncoderCtx& ctx)
201         {
202
203                 if (ie.get_bitqty() <= IE::constraint_t::upper_bound && ie.get_bitqty() >= IE::constraint_t::lower_bound)
204                 {
205                         Tools::bit_accessor::put(0, 1, ctx.refBuffer());
206                         BitstringNoExt<IE>::run(ie, ctx);
207                 }
208                 else
209                 {
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;
215                         if (tail)
216                         {
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);
219
220                                 last_byte <<= 8 - tail;
221
222                                 ctx.refBuffer().putBytes(&last_byte, 1);
223                                 ctx.refBuffer().set_begin(ctx.refBuffer().begin() - 1, tail);
224                         }
225                         else
226                         {
227                                 ctx.refBuffer().putBytes(ie.get_buffer().data(), ie.get_buffer().size());
228                         }
229                 }
230         }
231         static void inline run(IE& ie, DecoderCtx& ctx)
232         {
233                 u8 ext = Tools::bit_accessor::get(1, ctx.refBuffer());
234                 if (ext)
235                 {
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);
241                         if (data_in)
242                         {
243                                 u8* data_out = ctx.refAllocator().alloc_bytes(len_bytes);
244                                 if (data_out)
245                                 {
246                                         memcpy(data_out, data_in, len_bytes);
247                                         const u8 shift = len % 8;
248                                         if (shift)
249                                         {
250                                                 ctx.refBuffer().set_begin(ctx.refBuffer().begin() - 1, shift);
251                                                 data_out[len_bytes - 1] >>= 8 - shift;
252                                         }
253                                         ie.set_buffer(len, data_out);
254                                 }
255                                 else
256                                         ctx.refErrorCtx().allocatorNoMem(0, len_bytes);
257                         }
258                 }
259                 else
260                         BitstringNoExt<IE>::run(ie, ctx);
261         }
262 };
263
264 //15.7 : No extension
265 template <class IE>
266 struct Bitstring<IE, std::enable_if_t< (IE::constraint_t::extended == false)> >
267 {
268         static void inline run(IE const& ie, EncoderCtx& ctx)
269         {
270                 BitstringNoExt<IE>::run(ie, ctx);
271         }
272         static void inline run(IE& ie, DecoderCtx& ctx)
273         {
274                 BitstringNoExt<IE>::run(ie, ctx);
275         }
276 };
277
278 } //namespace per
279 } //namespace asn