Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / elements.hpp
1 #pragma once
2
3 /******************************************************************************
4 *
5 *   Copyright (c) 2019 AT&T Intellectual Property.
6 *   Copyright (c) 2018-2019 Nokia.
7 *
8 *   Licensed under the Apache License, Version 2.0 (the "License");
9 *   you may not use this file except in compliance with the License.
10 *   You may obtain a copy of the License at
11 *
12 *       http://www.apache.org/licenses/LICENSE-2.0
13 *
14 *   Unless required by applicable law or agreed to in writing, software
15 *   distributed under the License is distributed on an "AS IS" BASIS,
16 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 *   See the License for the specific language governing permissions and
18 *   limitations under the License.
19 *
20 ******************************************************************************/
21
22 // Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
23 #include <boost/intrusive/list.hpp>
24 #include <cstring>
25
26 // Local Includes: Application specific classes, functions, and libraries
27 #include "asn/constraints.hpp"
28 #include "asn/identifier.hpp"
29
30 namespace asn {
31
32 enum class element_type : uint8_t
33 {
34          T_BOOLEAN
35         ,T_INTEGER
36         ,T_ENUMERATED
37         ,T_REAL
38         ,T_BITSTRING
39         ,T_OCTETSTRING
40         ,T_NULL
41         ,T_SEQUENCE
42         ,T_SEQUENCE_OF
43         ,T_SET
44         ,T_SET_OF
45         ,T_CHOICE
46         ,T_OBJECTIDENTIFIER
47         ,T_OBJFIELD_FTV
48         ,T_OBJFIELD_TF
49 };
50
51 /***************************************************************************************
52 * BASE
53 ***************************************************************************************/
54
55 struct base
56 {
57         static constexpr bool optional = false;
58         static constexpr bool extension = false;
59
60         static constexpr char const* name() {return "";}
61
62         void setpresent(bool p) {is_set = p;}
63         void clear() {is_set = false;}
64
65         bool is_valid() const {return is_set;}
66
67 protected:
68         base() {}
69         void set() {is_set = true;}
70 protected:
71         bool is_set {false};
72
73         base& operator=(const base&) = delete;
74         base (const base&) = delete;
75 };
76
77 /***************************************************************************************
78 * IE_NULL
79 ***************************************************************************************/
80
81 struct nulltype : base
82 {
83         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::NULL_TYPE), tag_type_t::IMPLICIT>;
84
85         static constexpr element_type ie_type = element_type::T_NULL;
86         static constexpr const char* name() {return "NULL";}
87
88         void clear() {}
89 };
90
91 /***************************************************************************************
92 * T_BOOLEAN
93 ***************************************************************************************/
94
95 struct boolean : base
96 {
97         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::BOOLEAN), tag_type_t::IMPLICIT>;
98
99         static constexpr element_type ie_type = element_type::T_BOOLEAN;
100         static constexpr const char* name() {return "BOOLEAN";}
101
102         using value_type = bool;
103
104         void set(value_type vl) { m_value = vl; base::set();}
105         value_type get() const { return m_value; }
106         void clear() { m_value = false; base::clear();}
107
108 private:
109         value_type  m_value {false};
110 };
111
112 /***************************************************************************************
113 * T_INTEGER
114 ***************************************************************************************/
115 template < class Constraint = constraints<false> >
116 struct integer : base
117 {
118         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::INTEGER), tag_type_t::IMPLICIT>;
119
120         static constexpr element_type ie_type = element_type::T_INTEGER;
121         static constexpr const char* name() {return "INTEGER";}
122
123         using constraint_t      = Constraint;
124         using value_type        = int64_t;
125
126         bool equal(value_type v) const {return m_value == v;}
127
128         void set(value_type v) { m_value = v; base::set();}
129         value_type get() const { return m_value; }
130
131         void clear() { m_value = 0; base::clear();}
132
133 private:
134         value_type m_value;
135 };
136
137 /***************************************************************************************
138 * T_ENUMERATED
139 ***************************************************************************************/
140 template<int TotalNumEntries, int NumExtEntries, bool Extended>
141 struct enumerated : base
142 {
143         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::ENUMERATED), tag_type_t::IMPLICIT>;
144
145         static constexpr element_type ie_type = element_type::T_ENUMERATED;
146         static constexpr const char* name() {return "ENUMERATED";}
147
148         using constraint_t      = seq_range<TotalNumEntries, NumExtEntries, Extended>;
149         using value_type        = typename constraint_t::value_type;
150
151         bool equal(value_type v) const {return m_value == v;}
152         void set(value_type vl) { m_value = vl; base::set();}
153         value_type get() const { return m_value; }
154         void clear() { m_value = constraint_t::default_value; base::clear();}
155
156 private:
157         value_type m_value;
158 };
159
160 /***************************************************************************************
161 * T_OCTETSTRING
162 ***************************************************************************************/
163 template< class Constraint = constraints<false> >
164 struct ostring : base
165 {
166         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::OCTET_STRING), tag_type_t::IMPLICIT>;
167
168         static constexpr element_type ie_type = element_type::T_OCTETSTRING;
169         static constexpr const char* name() {return "OCTET STING";}
170         using constraint_t      = Constraint;
171
172         struct value_type
173         {
174                 value_type() {}
175                 value_type(size_t size, const char* data) : m_size(size), m_data(reinterpret_cast<const uint8_t*>(data)) {}
176
177                 size_t size() const                 { return m_size; }
178                 const uint8_t* data() const         { return m_data; }
179
180                 using const_iterator = uint8_t const*;
181                 const_iterator begin() const        { return data(); }
182                 const_iterator end() const          { return begin() + size(); }
183
184                 void assign(void const* p, size_t sz)  { m_data = static_cast<uint8_t const*>(p); m_size = sz; }
185
186         private:
187                 const uint8_t*  m_data{ 0 };
188                 size_t                  m_size{ 0 };
189         };
190
191         value_type const& get() const { return m_value; }
192
193         //Use std::string, std::vector or IE_OSTR::value_type
194         template<typename T> value_type const& set(T const& tval)
195         {
196                 set(tval.size(), tval.data());
197                 base::set();
198                 return m_value;
199         }
200
201         void set(size_t size, void const* data)
202         {
203                 m_value.assign(data, size);
204                 base::set();
205         }
206
207         template<class AT>
208         ostring& emplace(AT& allocator, size_t size, uint8_t const * data_in)
209         {
210                 if(size)
211                 {
212                         base::clear();
213                         uint8_t* data_out = allocator.alloc_bytes(size);
214                         if (data_out)
215                         {
216                                 memcpy(data_out, data_in, size);
217                                 set(size, data_out);
218                         }
219                 }
220                 else
221                         base::set();
222                 return *this;
223         }
224
225         template<class AT, class T>
226         ostring& emplace(AT& allocator, T const& tval)
227         {
228                 return emplace(allocator, tval.size(), reinterpret_cast<const uint8_t*>(tval.data()));
229         }
230
231         void clear() { m_value = value_type{}; base::clear();}
232
233 private:
234         value_type m_value;
235 };
236
237 /***************************************************************************************
238 * T_BITSTRING
239 ***************************************************************************************/
240 template<class Constraint = constraints<false> >
241 struct bstring : base
242 {
243         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::BIT_STRING), tag_type_t::IMPLICIT>;
244
245         static constexpr element_type ie_type = element_type::T_BITSTRING;
246         static constexpr const char* name() {return "BIT STING";}
247         using constraint_t      = Constraint;
248
249         struct value_type
250         {
251                 value_type() {}
252                 value_type(size_t size, const char* data, size_t bitqty) : m_size(size), m_data(reinterpret_cast<const uint8_t*>(data)), m_bitqty(bitqty){}
253
254                 size_t size() const { return m_size; }
255                 const uint8_t* data() const { return m_data; }
256                 size_t bitqty() const { return m_bitqty; }
257
258                 void assign(void const* p, size_t sz, size_t bits)  { m_data = static_cast<uint8_t const*>(p); m_size = sz; m_bitqty = bits; }
259
260         private:
261                 const uint8_t*  m_data{ nullptr };
262                 size_t                  m_size{ 0 };
263                 size_t                  m_bitqty{ 0 };
264         };
265
266         value_type const& get_buffer() const { return m_value; }
267
268         size_t get_bitqty()            const { return m_value.bitqty(); }
269
270         //Use std::string, std::vector or IE_BSTR::value_type
271         template<typename T> value_type const& set_buffer(T& tval, size_t bitqty)
272         {
273                 m_value.assign(tval.data(), tval.size(), bitqty);
274                 base::set();
275                 return m_value;
276         }
277
278         void set_buffer(size_t bitqty, const uint8_t* data)
279         {
280                 m_value.assign(data, (bitqty +7) >> 3, bitqty);
281                 base::set();
282         }
283
284         template<class AT>
285         bstring& emplace_buffer(AT& allocator, size_t bitqty, uint8_t const * data_in)
286         {
287                 size_t size = (bitqty +7) >> 3;
288                 uint8_t* data_out = allocator.alloc_bytes(size);
289                 if (!data_out) {
290                         throw std::bad_alloc();
291                 }
292                 memcpy(data_out, data_in, size);
293                 set_buffer(bitqty, data_out);
294                 return *this;
295         }
296
297         void clear() { m_value = value_type{}; base::clear();}
298
299         uint64_t get_number() const
300         {
301                 uint64_t retval{0};
302                 size_t i = 0;
303                 for(; i < m_value.size() - 1; ++i)
304                 {
305                         retval <<= 8;
306                         retval |= m_value.data()[i];
307                 }
308
309                 uint8_t shift = m_value.bitqty() % 8;
310                 if (shift)
311                 {
312                         retval <<= shift;
313                 }
314                 else
315                 {
316                         retval <<= 8;
317                 }
318
319                 retval |= m_value.data()[i];
320
321                 return retval;
322         }
323
324         template<class AT>
325         void set_number(AT& allocator, size_t bitqty, uint64_t data)
326         {
327                 size_t size = (bitqty +7) >> 3;
328                 uint8_t* data_out = allocator.alloc_bytes(size);
329                 if (!data_out) {
330                         throw std::bad_alloc();
331                 }
332
333                 const uint8_t shift = bitqty % 8;
334                 if (shift)
335                 {
336                         data_out[size-1] = data & (0xFF >> (8 - shift));
337                         data >>= shift;
338                 }
339                 else
340                 {
341                         data_out[size-1] = data & (0xFF);
342                         data >>= 8;
343                 }
344
345                 for (size_t i = 1; i <= size - 1; i++)
346                 {
347                         data_out[size-1-i] = data & (0xFF);
348                         data >>= 8;
349                 }
350
351                 m_value.assign(data_out, size, bitqty);
352                 base::set();
353         }
354
355 private:
356         value_type m_value;
357 };
358
359 /***************************************************************************************
360 * T_CHOICE
361 ***************************************************************************************/
362 template<int TotalNumEntries, int NumExtEntries, bool Extended>
363 struct choice : base
364 {
365   using asn_identifier_t = identifier<class_type_t::UNSPECIFIED, static_cast<tag_value_t>(tag_rvalue_t::CHOICE), tag_type_t::IMPLICIT>;
366
367         static constexpr element_type ie_type = element_type::T_CHOICE;
368         static constexpr const char* name() {return "CHOICE";}
369
370         using constraint_t      = seq_range<TotalNumEntries, NumExtEntries, Extended>;
371         using index_type        = size_t;
372         using value_type        = size_t;
373
374         static constexpr index_type fst_index = 1;
375         static constexpr index_type ext_index = fst_index + TotalNumEntries;
376
377         static index_type normalize(index_type idx)     {return idx - fst_index;}
378         static index_type denormalize(index_type idx)   {return idx + fst_index;}
379 };
380
381 /***************************************************************************************
382 * T_SEQUENCE
383 ***************************************************************************************/
384 template<int TotalNumEntries, int NumExtEntries, bool Extended, int NumOptEntries = 0>
385 struct sequence : base
386 {
387         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::SEQUENCE), tag_type_t::IMPLICIT>;
388
389         static constexpr element_type ie_type = element_type::T_SEQUENCE;
390         static constexpr const char* name() {return "SEQUENCE";}
391
392         static constexpr bound_t num_total_entries      = TotalNumEntries;
393         static constexpr bound_t num_opt_entries        = NumOptEntries;
394         static constexpr bound_t num_ext_entries        = NumExtEntries;
395
396         using constraint_t      = seq_range<TotalNumEntries, NumExtEntries, Extended>;
397
398 };
399
400 /***************************************************************************************
401 * T_SEQUENCE_OF
402 ***************************************************************************************/
403 template<typename T, class Constraint = constraints<false> >
404 struct sequenceof : base
405 {
406         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::SEQUENCE_OF), tag_type_t::IMPLICIT>;
407
408         static constexpr element_type ie_type = element_type::T_SEQUENCE_OF;
409         static constexpr const char* name() {return "SEQUENCE OF";}
410
411         struct value_type : T, boost::intrusive::list_base_hook< boost::intrusive::link_mode<boost::intrusive::auto_unlink> >
412         {
413                 value_type(){}
414         private:
415                 value_type& operator=(const value_type&) = delete;
416                 value_type (const value_type&) = delete;
417         };
418
419         using values_t          = boost::intrusive::list<value_type, boost::intrusive::constant_time_size<false>>;
420         using constraint_t      = Constraint;
421         using element_t         = T;
422
423         void clear()                        { m_list.clear(); base::clear();}
424         size_t size() const                 { return m_list.size(); }
425         template<class Predicate>
426         void sort(Predicate const& p)       { m_list.sort(p); }
427
428         template<class V>
429         void set(V& v)                      {for(auto & e : v) {m_list.push_back(e);} base::set();}
430
431         void push_back(value_type& v)       { m_list.push_back(v); base::set();}
432
433         template<class AT> //Note: Allocator must return word alligned buffer!
434         T& emplace_back(AT& allocator)
435         {
436                 uint8_t* data = allocator.alloc_bytes(sizeof(value_type));
437                 if(!data)
438                         throw std::bad_alloc();
439                 value_type* v = new (data) value_type;
440                 push_back(*v);
441                 return *v;
442         };
443
444         using iterator = typename values_t::iterator;
445         iterator begin()                    { return m_list.begin(); }
446         iterator end()                      { return m_list.end(); }
447
448         using const_iterator = typename values_t::const_iterator;
449         const_iterator begin() const        { return m_list.begin(); }
450         const_iterator end() const          { return m_list.end(); }
451
452         sequenceof(){}
453
454 private:
455         values_t m_list;
456 };
457
458 /***************************************************************************************
459 * T_OBJFIELD_FTV
460 ***************************************************************************************/
461 template<typename T, bool>
462 struct fixedtypefield : T
463 {
464         static constexpr element_type ie_type = element_type::T_OBJFIELD_FTV;
465
466         T& ref_nested() {return *this;}
467         T const & ref_nested() const {return *this;}
468 };
469
470 /***************************************************************************************
471 * T_OBJFIELD_TF
472 ***************************************************************************************/
473 template<bool>
474 struct typefield : base
475 {
476         static constexpr element_type ie_type = element_type::T_OBJFIELD_TF;
477         static constexpr const char* name() {return "type-field";}
478
479         typefield& ref_nested() {return *this;}
480         typefield const& ref_nested() const {return *this;}
481
482         bool is_unknown() const {return false;}
483 };
484
485 /***************************************************************************************
486 * T_OBJECTIDENTIFIER
487 ***************************************************************************************/
488 struct oid : ostring<>
489 {
490         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::OBJECT_IDENTIFIER), tag_type_t::IMPLICIT>;
491
492         static constexpr element_type ie_type = element_type::T_OBJECTIDENTIFIER;
493         static constexpr const char* name() {return "OBJECT IDENTIFIER";}
494 };
495
496 /***************************************************************************************
497 * T_PRINTABLESTRING
498 ***************************************************************************************/
499 template<class Constraint = constraints<false> >
500 struct printable_string : ostring<Constraint>
501 {
502         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::PrintableString), tag_type_t::IMPLICIT>;
503         static constexpr const char* name() {return "PrintableString";}
504 };
505
506 /***************************************************************************************
507 * T_IA5_STRING
508 ***************************************************************************************/
509 template<class Constraint = constraints<false> >
510 struct ia5_string : ostring<Constraint>
511 {
512         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::IA5String), tag_type_t::IMPLICIT>;
513         static constexpr const char* name() {return "IA5String";}
514 };
515
516 /***************************************************************************************
517 * T_GRAPHIC_STRING
518 ***************************************************************************************/
519 template<class Constraint = asn::constraints<false> >
520 struct graphic_string : ostring<Constraint>
521 {
522         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::GraphicString), tag_type_t::IMPLICIT>;
523         static constexpr const char* name() {return "IA5String";}
524 };
525
526 /***************************************************************************************
527 * T_UTF8_STRING
528 ***************************************************************************************/
529 template<class Constraint = asn::constraints<false> >
530 struct utf8_string : ostring<Constraint>
531 {
532         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::UTF8String), tag_type_t::IMPLICIT>;
533         static constexpr const char* name() {return "UTF8String";}
534 };
535
536 /***************************************************************************************
537 * T_SET
538 ***************************************************************************************/
539 template<int TotalNumEntries, int NumExtEntries, bool Extended, int NumOptEntries = 0>
540 struct set : base
541 {
542         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::SET), tag_type_t::IMPLICIT>;
543
544         static constexpr element_type ie_type = element_type::T_SET;
545         static constexpr const char* name() {return "SET";}
546
547         static constexpr bound_t num_total_entries      = TotalNumEntries;
548         static constexpr bound_t num_opt_entries        = NumOptEntries;
549         static constexpr bound_t num_ext_entries        = NumExtEntries;
550
551         using constraint_t      = seq_range<TotalNumEntries, NumExtEntries, Extended>;
552 };
553
554 /***************************************************************************************
555 * T_SET_OF
556 ***************************************************************************************/
557 template<typename T, class Constraint = constraints<false> >
558 struct setof : sequenceof<T, Constraint>
559 {
560         using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::SET_OF), tag_type_t::IMPLICIT>;
561
562         static constexpr element_type ie_type = element_type::T_SET_OF;
563         static constexpr const char* name() {return "SET OF";}
564 };
565 } //namespace asn