Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / per / sequence.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 #include "asn/per/visitor.hpp"
26
27 namespace asn {
28 namespace per {
29
30 /******************************************************************
31  * Adapter
32  *****************************************************************/
33 template <class Container, typename IE, class Enabler = void>
34 struct Adapter
35 {
36         static void inline run(IE const& ie, EncoderCtx& ctx, Container const& cont)
37         {
38                 Element<IE, IE::ie_type>::run(ie, ctx);
39         }
40         
41         static void inline run(IE& ie, DecoderCtx& ctx, Container const& cont)
42         {
43                 Element<IE, IE::ie_type>::run(ie, ctx);
44         }
45 };
46 template <class Container, typename IE>
47 struct Adapter<Container, IE, std::enable_if_t< (IE::ie_type == element_type::T_OBJFIELD_FTV) >>
48 {
49         static void inline run(IE const& ie, EncoderCtx& ctx, Container const& cont)
50         {
51                 VisitorEncoder v(ctx);
52                 bool rv = ie.encode(v, cont);
53                 if(!rv && static_cast<bool>(ctx))
54                 {
55                         ctx.refErrorCtx().errorNoObject(Container::name());
56                 }
57         }
58         
59         static void inline run(IE& ie, DecoderCtx& ctx, Container const& cont)
60         {
61                 VisitorDecoder v(ctx);
62                 bool rv = ie.decode(v, cont);
63                 if(!rv && static_cast<bool>(ctx))
64                 {
65                         ctx.refErrorCtx().errorNoObject(Container::name());
66                 }
67         }
68 };
69 template <class Container, typename IE>
70 struct Adapter<Container, IE, std::enable_if_t< (IE::ie_type == element_type::T_OBJFIELD_TF)> >
71 {
72         static void inline run(IE const& ie, EncoderCtx& ctx, Container const& cont)
73         {
74                 OpenTypeVisitorEncoder v(ctx);
75                 bool rv = ie.encode(v, cont);
76                 if(!rv && static_cast<bool>(ctx))
77                 {
78                         ctx.refErrorCtx().errorNoObject(Container::name());
79                 }
80         }
81         
82         static void inline run(IE& ie, DecoderCtx& ctx, Container const& cont)
83         {
84                 OpenTypeVisitorDecoder v(ctx);
85                 bool rv = ie.decode(v, cont);
86                 if(!rv && static_cast<bool>(ctx))
87                 {
88                         ctx.refErrorCtx().errorNoObject(Container::name());
89                 }
90                 if(ie.is_unknown()) //skip the unknown Open Type
91                 {
92                         size_t size = LengthDeterminantDefault::run(ctx);
93                         DecoderCtx::buf_type& buffer = ctx.refBuffer();
94                         if (buffer.getBytesLeft() < size)
95                                 ctx.refErrorCtx().lengthErrorBytes(buffer.getBytesLeft(), size);
96                         else
97                                 buffer.advance(size);
98                 }
99         }
100 };
101
102 /******************************************************************
103  * RootEncoder
104  *****************************************************************/
105 template <class Container>
106 struct RootEncoder
107 {
108         RootEncoder(EncoderCtx& ctx, Container const& cont) : m_ctx(ctx), m_cont(cont) {}
109         
110         template <typename IE>
111         bool operator() (IE const& ie) const
112         {
113                 if(!IE::extension)
114                 {
115                         if(IE::optional && !ie.is_valid())
116                                 return static_cast<bool>(m_ctx);
117                         Adapter<Container, IE>::run(ie, m_ctx, m_cont);
118                 }
119                 return static_cast<bool>(m_ctx);
120         }
121         EncoderCtx& m_ctx;
122         Container const& m_cont;
123 };
124
125 /******************************************************************
126  * RootDecoder
127  *****************************************************************/
128 template <class Container>
129 struct RootDecoder
130 {
131         RootDecoder(DecoderCtx& ctx, Container const& cont) : m_ctx(ctx), m_cont(cont) {}
132         
133         template <typename IE>
134         bool operator() (IE& ie) const
135         {
136                 if(!IE::extension)
137                 {
138                         if(IE::optional)
139                         {
140                                 if(m_ctx.map_elm())
141                                 {
142                                         ie.setpresent(true);
143                                         Adapter<Container, IE>::run(ie, m_ctx, m_cont);
144                                 }
145                                 else
146                                         ie.setpresent(false);
147                         }
148                         else
149                         {
150                                 Adapter<Container, IE>::run(ie, m_ctx, m_cont);
151                         }
152                 }
153                 return static_cast<bool>(m_ctx);
154         }
155         DecoderCtx& m_ctx;
156         Container const& m_cont;
157 };
158
159 /******************************************************************
160  * ExtEncoder
161  *****************************************************************/
162 template <class Container>
163 struct ExtEncoder
164 {
165         explicit ExtEncoder(EncoderCtx& ctx, Container const& cont) : m_ctx(ctx), m_cont(cont) {}
166
167         template <typename IE>
168         bool operator() (IE const& ie) const
169         {
170                 if(!IE::extension)
171                         return static_cast<bool>(m_ctx);
172                 
173                 if(IE::optional && !ie.is_valid())
174                         return static_cast<bool>(m_ctx);
175                 
176                 size_t reserved_size = 1; //1 byte length is most likely
177                 Tools::bit_accessor::padByte(m_ctx.refBuffer());
178
179                 if (m_ctx.refBuffer().getBytesLeft())
180                 {
181                         EncoderCtx::buf_type::pointer p = m_ctx.refBuffer().advance(reserved_size);
182                         EncoderCtx::buf_type::pointer start = p + reserved_size;
183
184                         Adapter<Container, IE>::run(ie, m_ctx, m_cont);
185
186                         if (m_ctx)
187                         {
188                                 Tools::bit_accessor::padByte(m_ctx.refBuffer());
189                                 EncoderCtx::buf_type::pointer p_new = m_ctx.refBuffer().begin();
190                                 size_t size = p_new - start;
191                                 size_t needed = LengthDeterminantDefault::bytes_needed(size) - reserved_size;
192                                 if (needed) //1 byte is not enough for the length determinant. it is hardly possible
193                                 {
194                                         if (m_ctx.refBuffer().getBytesLeft() < needed) {
195                                                 m_ctx.refErrorCtx().lengthErrorBytes(m_ctx.refBuffer().getBytesLeft(), needed);
196                                                 return false;
197                                         }
198                                         memmove(start + needed, start, size);
199                                         p_new += needed;
200                                 }
201                                 m_ctx.refBuffer().set_begin(p, 0);
202                                 LengthDeterminantDefault::run(m_ctx, size);
203                                 if (m_ctx) {
204                                         m_ctx.refBuffer().set_begin(p_new, 0);
205                                         Tools::bit_accessor::padByte(m_ctx.refBuffer());
206                                 }
207                         }
208                 }
209                 else
210                 {
211                         m_ctx.refErrorCtx().lengthErrorBytes(m_ctx.refBuffer().getBytesLeft(), reserved_size);
212                         return false;
213                 }
214                 return static_cast<bool>(m_ctx);
215         }
216         EncoderCtx& m_ctx;
217         Container const& m_cont;
218 };
219
220 /******************************************************************
221  * ExtDecoder
222  *****************************************************************/
223 template <class Container>
224 struct ExtDecoder
225 {
226         explicit ExtDecoder(DecoderCtx& ctx, Container const& cont) : m_ctx(ctx), m_cont(cont) {}
227
228         template <typename IE>
229         bool operator() (IE& ie) const
230         {
231                 if(!IE::extension)
232                         return static_cast<bool>(m_ctx);
233
234                 if (m_ctx.map_elm())
235                 {
236                         ie.setpresent(true);
237                         size_t size = LengthDeterminantDefault::run(m_ctx);
238                         DecoderCtx::buf_type& buffer = m_ctx.refBuffer();
239                         if (buffer.getBytesLeft() < size)
240                         {
241                                 m_ctx.refErrorCtx().lengthErrorBytes(buffer.getBytesLeft(), size);
242                                 return false;
243                         }
244                         DecoderCtx::buf_type::pointer end = buffer.end();
245                         buffer.set_end(buffer.begin() + size);
246                         Adapter<Container, IE>::run(ie, m_ctx, m_cont);
247                         Tools::bit_accessor::padByte(m_ctx.refBuffer());
248                         buffer.set_end(end);
249                 }
250                 else
251                 {
252                         ie.setpresent(false);
253                 }
254
255                 return static_cast<bool>(m_ctx);
256         }
257         DecoderCtx& m_ctx;
258         Container const& m_cont;
259 };
260
261 /******************************************************************
262  * SeqMap
263  *****************************************************************/
264 template<class IE, class Enabler = void>
265 struct SeqMap;
266
267 /*
268 template <class IE>
269 struct SeqMap<IE, std::enable_if_t< (IE::num_opt_entries > 8) > >
270 {
271         static void inline run(EncoderCtx& ctx, size_t val)
272         {
273                 u8 k       = IE::num_opt_entries / 8; // num of full bytes in a seq map mask
274                 u8 fb_bits = IE::num_opt_entries % 8; // num of first byte bits (without padding)
275
276                 if (fb_bits) {
277                         // Put a part of a first byte (without padding, only seq map own bits)
278                         Tools::bit_accessor::put((u8)(val >> 8*k), fb_bits, ctx.refBuffer());
279                 }
280
281                 // Put other bytes (full bytes)
282                 for (int i = (k-1); i >= 0; i--) {
283                         Tools::bit_accessor::put((u8)(val >> 8*i), 8, ctx.refBuffer());
284                 }
285         }
286
287         static DecoderCtx::map_type inline run(DecoderCtx& ctx)
288         {
289                 uint num_opts = IE::num_opt_entries;
290                 u64 res = 0;
291                 u8  k   = 1;
292                 u8  lb_bits  = IE::num_opt_entries % 8; // num of last byte bits (without padding)
293
294                 while (num_opts >= 8) {
295                         size_t shift = sizeof(DecoderCtx::map_type) * CHAR_BIT - 8*k;
296
297                         DecoderCtx::map_type rval = Tools::bit_accessor::get(8, ctx.refBuffer());
298
299                         rval = rval << shift;
300                         res |= rval;
301
302                         k++;
303                         num_opts -= 8;
304                 }
305
306                 if (lb_bits > 0) {
307                         // (8 - lb_bits) - padding in a last byte
308                         size_t shift = sizeof(DecoderCtx::map_type) * CHAR_BIT - 8*k + 8 - lb_bits;
309
310                         DecoderCtx::map_type rval = Tools::bit_accessor::get(lb_bits, ctx.refBuffer());
311
312                         rval  = rval << shift;
313                         res |= rval;
314                 }
315
316                 return res;
317         }
318 }
319 ;
320 */
321
322 template<class IE>
323 struct SeqMap<IE, std::enable_if_t< (IE::num_opt_entries <= 8)> > //todo: to add code for more than 8 optional elements
324 {
325         static void inline run(EncoderCtx& ctx, size_t val)
326         {
327                 Tools::bit_accessor::put((u8)val, IE::num_opt_entries, ctx.refBuffer());
328         }
329         static DecoderCtx::map_type inline run(DecoderCtx& ctx)
330         {
331                 size_t shift = sizeof(DecoderCtx::map_type) * CHAR_BIT - IE::num_opt_entries;
332                 DecoderCtx::map_type rval = Tools::bit_accessor::get(IE::num_opt_entries, ctx.refBuffer());
333                 rval = rval << shift;
334                 return rval;
335         }
336 };
337
338 /******************************************************************
339  * SeqExtMap
340  *****************************************************************/
341 template<class IE, bound_t NumExtEntries, class Enabler = void>
342 struct SeqExtMap
343 {
344         static void inline run(EncoderCtx& ctx, size_t val) {}
345         static DecoderCtx::map_type inline run(DecoderCtx& ctx)
346         {
347                 size_t len = NormallySmallLength<1>::run(ctx);
348                 size_t shift = sizeof(DecoderCtx::map_type) * CHAR_BIT - len;
349                 u8 tmp;
350                 DecoderCtx::map_type rval{ 0 };
351                 u8 val;
352
353                 while (len) {
354                         tmp = len > 8 ? 8 : (u8)len;
355                         val = Tools::bit_accessor::get(tmp, ctx.refBuffer());
356                         rval = rval << tmp;
357                         rval |= val;
358                         len -= tmp;
359                 }
360                 rval = rval << shift;
361                 return rval;
362         }
363 };
364
365 template<class IE, bound_t NumExtEntries>
366 struct SeqExtMap<IE, NumExtEntries, std::enable_if_t< ((NumExtEntries <= 8) && (NumExtEntries > 0)) > >
367 {
368         static void inline run(EncoderCtx& ctx, size_t val)
369         {
370                 NormallySmallLength<NumExtEntries>::run(ctx);
371                 Tools::bit_accessor::put((u8)val, NumExtEntries, ctx.refBuffer());
372         }
373 };
374
375 template<class IE, bound_t NumExtEntries>
376 struct SeqExtMap<IE, NumExtEntries, std::enable_if_t< (NumExtEntries > 8) > >
377 {
378         static void inline run(EncoderCtx& ctx, size_t val)
379         {
380                 NormallySmallLength<NumExtEntries>::run(ctx);
381
382                 size_t len = NumExtEntries;
383                 size_t tmp;
384
385                 while (len) {
386                         tmp = len > 8 ? 8 : len;
387                         Tools::bit_accessor::put((u8)val, tmp, ctx.refBuffer());
388                         val = val >> tmp;
389                         len -= tmp;
390                 }
391         }
392 };
393
394 /******************************************************************
395  * SeqMapBuilder
396  *****************************************************************/
397 struct SeqMapBuilder
398 {
399         SeqMapBuilder(uint64_t& map) : m_map(map) {}
400
401         template<typename IE>
402         bool operator()(IE const& ie)
403         {
404                 if(!IE::extension && IE::optional)
405                 {
406                         m_map = m_map << 1;
407                         if(ie.is_valid())
408                                 m_map |= 1;
409                 }
410                 return true;
411         }
412         uint64_t&       m_map;
413 };
414
415 /******************************************************************
416  * SeqExtMapBuilder
417  *****************************************************************/
418 struct SeqExtMapBuilder
419 {
420         SeqExtMapBuilder(uint64_t& map) : m_map(map) {}
421
422         template<typename IE>
423         bool operator()(IE const& ie)
424         {
425                 if(IE::extension)
426                 {
427                         m_map = m_map << 1;
428                         if(!IE::optional || (IE::optional &&  ie.is_valid()))
429                                 m_map |= 1;
430                 }
431                 return true;
432         }
433         uint64_t&       m_map;
434 };
435
436 /******************************************************************
437  * SeqNoExtDefault
438  *****************************************************************/
439 // Default (No OPT/DEF present within the extension root)
440 template <class IE>
441 struct SeqNoExtDefault
442 {
443         static void inline run(IE const& ie, EncoderCtx& ctx)
444         {
445                 RootEncoder<IE> ve(ctx, ie);
446                 ie.encode(ve);
447         }
448         static void inline run(IE& ie, DecoderCtx& ctx, DecoderCtx::map_type map = 0)
449         {
450                 RootDecoder<IE> ve(ctx, ie);
451                 
452                 DecoderCtx::map_type old_map = ctx.set_map(map);
453                 ie.decode(ve);
454                 ctx.set_map(old_map);
455         }
456 };
457
458 /******************************************************************
459  * SeqNoExt
460  *****************************************************************/
461 // Default (No OPT/DEF present within the extension root)
462 template <class IE, class Enabler = void>
463 struct SeqNoExt
464 {
465         static void inline run(IE const& ie, EncoderCtx& ctx)
466         {
467                 SeqNoExtDefault<IE>::run(ie, ctx);
468         }
469         static void inline run(IE& ie, DecoderCtx& ctx)
470         {
471                 SeqNoExtDefault<IE>::run(ie, ctx);
472         }
473 };
474
475 //18.2 OPT/DEF present within the extension root 
476 template <class IE>
477 struct SeqNoExt<IE, std::enable_if_t< (IE::num_opt_entries > 0) > >
478 {
479         static void inline run(IE const& ie, EncoderCtx& ctx)
480         {
481                 uint64_t map = 0;
482                 SeqMapBuilder mb(map);
483                 ie.encode(mb);
484                 SeqMap<IE>::run(ctx, map);
485                 SeqNoExtDefault<IE>::run(ie, ctx);
486         }
487         static void inline run(IE& ie, DecoderCtx& ctx)
488         {
489                 SeqNoExtDefault<IE>::run(ie, ctx, SeqMap<IE>::run(ctx));
490         }
491 };
492
493 /******************************************************************
494  * Seq
495  *****************************************************************/
496 template <class IE, class Enable = void>
497 struct Seq;
498
499 template <class IE>
500 struct Seq<IE, std::enable_if_t< (IE::constraint_t::extended == true)> >
501 {
502         static void inline run(IE const& ie, EncoderCtx& ctx)
503         {
504                 uint64_t map = 0;
505                 SeqExtMapBuilder emb(map);
506                 ie.encode(emb);
507                 
508                 if (map) {
509                         Tools::bit_accessor::put(1, 1, ctx.refBuffer());
510                         SeqNoExt<IE>::run(ie, ctx);
511                         SeqExtMap<IE, IE::num_ext_entries>::run(ctx, map);
512                         ExtEncoder<IE> ove(ctx, ie);
513                         ie.encode(ove);
514                 }
515                 else {
516                         Tools::bit_accessor::put(0, 1, ctx.refBuffer());
517                         SeqNoExt<IE>::run(ie, ctx);
518                 }
519         }
520         static void inline run(IE& ie, DecoderCtx& ctx)
521         {
522                 u8 ext = Tools::bit_accessor::get(1, ctx.refBuffer());
523                 if (ext)
524                 {
525                         SeqNoExt<IE>::run(ie, ctx);
526                         
527                         auto old_map = ctx.set_map(SeqExtMap<IE, 0>::run(ctx)); // we do not know how many exts can be received
528                         {
529                                 ExtDecoder<IE> ove(ctx, ie);
530                                 ie.decode(ove);
531                                 
532                                 auto& buffer = ctx.refBuffer();
533                                 while(ctx.get_map())
534                                 {
535                                         if(ctx.map_elm()) //skip unknown extensions
536                                         {
537                                                 size_t size = LengthDeterminantDefault::run(ctx);
538                                                 if (buffer.getBytesLeft() < size)
539                                                 {
540                                                         ctx.refErrorCtx().lengthErrorBytes(buffer.getBytesLeft(), size);
541                                                         break;
542                                                 }
543                                                 buffer.advance(size);
544                                         }
545                                 }
546                         }
547                         ctx.set_map(old_map);
548                 }
549                 else
550                         SeqNoExt<IE>::run(ie, ctx);
551         }
552 };
553
554 template <class IE>
555 struct Seq<IE, std::enable_if_t< (IE::constraint_t::extended == false)> >
556 {
557         static void inline run(IE const& ie, EncoderCtx& ctx)
558         {
559                 SeqNoExt<IE>::run(ie, ctx);
560         }
561         static void inline run(IE& ie, DecoderCtx& ctx)
562         {
563                 SeqNoExt<IE>::run(ie, ctx);
564         }
565 };
566
567 } //namespace per
568 } //namespace asn