Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / elements.hpp
diff --git a/e2sim/e2apv1sim/src/ASN1/asn/elements.hpp b/e2sim/e2apv1sim/src/ASN1/asn/elements.hpp
new file mode 100755 (executable)
index 0000000..9cbcd42
--- /dev/null
@@ -0,0 +1,565 @@
+#pragma once
+
+/******************************************************************************
+*
+*   Copyright (c) 2019 AT&T Intellectual Property.
+*   Copyright (c) 2018-2019 Nokia.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+******************************************************************************/
+
+// Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
+#include <boost/intrusive/list.hpp>
+#include <cstring>
+
+// Local Includes: Application specific classes, functions, and libraries
+#include "asn/constraints.hpp"
+#include "asn/identifier.hpp"
+
+namespace asn {
+
+enum class element_type : uint8_t
+{
+        T_BOOLEAN
+       ,T_INTEGER
+       ,T_ENUMERATED
+       ,T_REAL
+       ,T_BITSTRING
+       ,T_OCTETSTRING
+       ,T_NULL
+       ,T_SEQUENCE
+       ,T_SEQUENCE_OF
+       ,T_SET
+       ,T_SET_OF
+       ,T_CHOICE
+       ,T_OBJECTIDENTIFIER
+       ,T_OBJFIELD_FTV
+       ,T_OBJFIELD_TF
+};
+
+/***************************************************************************************
+* BASE
+***************************************************************************************/
+
+struct base
+{
+       static constexpr bool optional = false;
+       static constexpr bool extension = false;
+
+       static constexpr char const* name() {return "";}
+
+       void setpresent(bool p) {is_set = p;}
+       void clear() {is_set = false;}
+
+       bool is_valid() const {return is_set;}
+
+protected:
+       base() {}
+       void set() {is_set = true;}
+protected:
+       bool is_set {false};
+
+       base& operator=(const base&) = delete;
+       base (const base&) = delete;
+};
+
+/***************************************************************************************
+* IE_NULL
+***************************************************************************************/
+
+struct nulltype : base
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::NULL_TYPE), tag_type_t::IMPLICIT>;
+
+       static constexpr element_type ie_type = element_type::T_NULL;
+       static constexpr const char* name() {return "NULL";}
+
+       void clear() {}
+};
+
+/***************************************************************************************
+* T_BOOLEAN
+***************************************************************************************/
+
+struct boolean : base
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::BOOLEAN), tag_type_t::IMPLICIT>;
+
+       static constexpr element_type ie_type = element_type::T_BOOLEAN;
+       static constexpr const char* name() {return "BOOLEAN";}
+
+       using value_type = bool;
+
+       void set(value_type vl) { m_value = vl; base::set();}
+       value_type get() const { return m_value; }
+       void clear() { m_value = false; base::clear();}
+
+private:
+       value_type  m_value {false};
+};
+
+/***************************************************************************************
+* T_INTEGER
+***************************************************************************************/
+template < class Constraint = constraints<false> >
+struct integer : base
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::INTEGER), tag_type_t::IMPLICIT>;
+
+       static constexpr element_type ie_type = element_type::T_INTEGER;
+       static constexpr const char* name() {return "INTEGER";}
+
+       using constraint_t      = Constraint;
+       using value_type        = int64_t;
+
+       bool equal(value_type v) const {return m_value == v;}
+
+       void set(value_type v) { m_value = v; base::set();}
+       value_type get() const { return m_value; }
+
+       void clear() { m_value = 0; base::clear();}
+
+private:
+       value_type m_value;
+};
+
+/***************************************************************************************
+* T_ENUMERATED
+***************************************************************************************/
+template<int TotalNumEntries, int NumExtEntries, bool Extended>
+struct enumerated : base
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::ENUMERATED), tag_type_t::IMPLICIT>;
+
+       static constexpr element_type ie_type = element_type::T_ENUMERATED;
+       static constexpr const char* name() {return "ENUMERATED";}
+
+       using constraint_t      = seq_range<TotalNumEntries, NumExtEntries, Extended>;
+       using value_type        = typename constraint_t::value_type;
+
+       bool equal(value_type v) const {return m_value == v;}
+       void set(value_type vl) { m_value = vl; base::set();}
+       value_type get() const { return m_value; }
+       void clear() { m_value = constraint_t::default_value; base::clear();}
+
+private:
+       value_type m_value;
+};
+
+/***************************************************************************************
+* T_OCTETSTRING
+***************************************************************************************/
+template< class Constraint = constraints<false> >
+struct ostring : base
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::OCTET_STRING), tag_type_t::IMPLICIT>;
+
+       static constexpr element_type ie_type = element_type::T_OCTETSTRING;
+       static constexpr const char* name() {return "OCTET STING";}
+       using constraint_t      = Constraint;
+
+       struct value_type
+       {
+               value_type() {}
+               value_type(size_t size, const char* data) : m_size(size), m_data(reinterpret_cast<const uint8_t*>(data)) {}
+
+               size_t size() const                 { return m_size; }
+               const uint8_t* data() const         { return m_data; }
+
+               using const_iterator = uint8_t const*;
+               const_iterator begin() const        { return data(); }
+               const_iterator end() const          { return begin() + size(); }
+
+               void assign(void const* p, size_t sz)  { m_data = static_cast<uint8_t const*>(p); m_size = sz; }
+
+       private:
+               const uint8_t*  m_data{ 0 };
+               size_t                  m_size{ 0 };
+       };
+
+       value_type const& get() const { return m_value; }
+
+       //Use std::string, std::vector or IE_OSTR::value_type
+       template<typename T> value_type const& set(T const& tval)
+       {
+               set(tval.size(), tval.data());
+               base::set();
+               return m_value;
+       }
+
+       void set(size_t size, void const* data)
+       {
+               m_value.assign(data, size);
+               base::set();
+       }
+
+       template<class AT>
+       ostring& emplace(AT& allocator, size_t size, uint8_t const * data_in)
+       {
+               if(size)
+               {
+                       base::clear();
+                       uint8_t* data_out = allocator.alloc_bytes(size);
+                       if (data_out)
+                       {
+                               memcpy(data_out, data_in, size);
+                               set(size, data_out);
+                       }
+               }
+               else
+                       base::set();
+               return *this;
+       }
+
+       template<class AT, class T>
+       ostring& emplace(AT& allocator, T const& tval)
+       {
+               return emplace(allocator, tval.size(), reinterpret_cast<const uint8_t*>(tval.data()));
+       }
+
+       void clear() { m_value = value_type{}; base::clear();}
+
+private:
+       value_type m_value;
+};
+
+/***************************************************************************************
+* T_BITSTRING
+***************************************************************************************/
+template<class Constraint = constraints<false> >
+struct bstring : base
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::BIT_STRING), tag_type_t::IMPLICIT>;
+
+       static constexpr element_type ie_type = element_type::T_BITSTRING;
+       static constexpr const char* name() {return "BIT STING";}
+       using constraint_t      = Constraint;
+
+       struct value_type
+       {
+               value_type() {}
+               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){}
+
+               size_t size() const { return m_size; }
+               const uint8_t* data() const { return m_data; }
+               size_t bitqty() const { return m_bitqty; }
+
+               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; }
+
+       private:
+               const uint8_t*  m_data{ nullptr };
+               size_t                  m_size{ 0 };
+               size_t                  m_bitqty{ 0 };
+       };
+
+       value_type const& get_buffer() const { return m_value; }
+
+       size_t get_bitqty()            const { return m_value.bitqty(); }
+
+       //Use std::string, std::vector or IE_BSTR::value_type
+       template<typename T> value_type const& set_buffer(T& tval, size_t bitqty)
+       {
+               m_value.assign(tval.data(), tval.size(), bitqty);
+               base::set();
+               return m_value;
+       }
+
+       void set_buffer(size_t bitqty, const uint8_t* data)
+       {
+               m_value.assign(data, (bitqty +7) >> 3, bitqty);
+               base::set();
+       }
+
+       template<class AT>
+       bstring& emplace_buffer(AT& allocator, size_t bitqty, uint8_t const * data_in)
+       {
+               size_t size = (bitqty +7) >> 3;
+               uint8_t* data_out = allocator.alloc_bytes(size);
+               if (!data_out) {
+                       throw std::bad_alloc();
+               }
+               memcpy(data_out, data_in, size);
+               set_buffer(bitqty, data_out);
+               return *this;
+       }
+
+       void clear() { m_value = value_type{}; base::clear();}
+
+       uint64_t get_number() const
+       {
+               uint64_t retval{0};
+               size_t i = 0;
+               for(; i < m_value.size() - 1; ++i)
+               {
+                       retval <<= 8;
+                       retval |= m_value.data()[i];
+               }
+
+               uint8_t shift = m_value.bitqty() % 8;
+               if (shift)
+               {
+                       retval <<= shift;
+               }
+               else
+               {
+                       retval <<= 8;
+               }
+
+               retval |= m_value.data()[i];
+
+               return retval;
+       }
+
+       template<class AT>
+       void set_number(AT& allocator, size_t bitqty, uint64_t data)
+       {
+               size_t size = (bitqty +7) >> 3;
+               uint8_t* data_out = allocator.alloc_bytes(size);
+               if (!data_out) {
+                       throw std::bad_alloc();
+               }
+
+               const uint8_t shift = bitqty % 8;
+               if (shift)
+               {
+                       data_out[size-1] = data & (0xFF >> (8 - shift));
+                       data >>= shift;
+               }
+               else
+               {
+                       data_out[size-1] = data & (0xFF);
+                       data >>= 8;
+               }
+
+               for (size_t i = 1; i <= size - 1; i++)
+               {
+                       data_out[size-1-i] = data & (0xFF);
+                       data >>= 8;
+               }
+
+               m_value.assign(data_out, size, bitqty);
+               base::set();
+       }
+
+private:
+       value_type m_value;
+};
+
+/***************************************************************************************
+* T_CHOICE
+***************************************************************************************/
+template<int TotalNumEntries, int NumExtEntries, bool Extended>
+struct choice : base
+{
+  using asn_identifier_t = identifier<class_type_t::UNSPECIFIED, static_cast<tag_value_t>(tag_rvalue_t::CHOICE), tag_type_t::IMPLICIT>;
+
+       static constexpr element_type ie_type = element_type::T_CHOICE;
+       static constexpr const char* name() {return "CHOICE";}
+
+       using constraint_t      = seq_range<TotalNumEntries, NumExtEntries, Extended>;
+       using index_type        = size_t;
+       using value_type        = size_t;
+
+       static constexpr index_type fst_index = 1;
+       static constexpr index_type ext_index = fst_index + TotalNumEntries;
+
+       static index_type normalize(index_type idx)     {return idx - fst_index;}
+       static index_type denormalize(index_type idx)   {return idx + fst_index;}
+};
+
+/***************************************************************************************
+* T_SEQUENCE
+***************************************************************************************/
+template<int TotalNumEntries, int NumExtEntries, bool Extended, int NumOptEntries = 0>
+struct sequence : base
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::SEQUENCE), tag_type_t::IMPLICIT>;
+
+       static constexpr element_type ie_type = element_type::T_SEQUENCE;
+       static constexpr const char* name() {return "SEQUENCE";}
+
+       static constexpr bound_t num_total_entries      = TotalNumEntries;
+       static constexpr bound_t num_opt_entries        = NumOptEntries;
+       static constexpr bound_t num_ext_entries        = NumExtEntries;
+
+       using constraint_t      = seq_range<TotalNumEntries, NumExtEntries, Extended>;
+
+};
+
+/***************************************************************************************
+* T_SEQUENCE_OF
+***************************************************************************************/
+template<typename T, class Constraint = constraints<false> >
+struct sequenceof : base
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::SEQUENCE_OF), tag_type_t::IMPLICIT>;
+
+       static constexpr element_type ie_type = element_type::T_SEQUENCE_OF;
+       static constexpr const char* name() {return "SEQUENCE OF";}
+
+       struct value_type : T, boost::intrusive::list_base_hook< boost::intrusive::link_mode<boost::intrusive::auto_unlink> >
+       {
+               value_type(){}
+       private:
+               value_type& operator=(const value_type&) = delete;
+               value_type (const value_type&) = delete;
+       };
+
+       using values_t          = boost::intrusive::list<value_type, boost::intrusive::constant_time_size<false>>;
+       using constraint_t      = Constraint;
+       using element_t         = T;
+
+       void clear()                        { m_list.clear(); base::clear();}
+       size_t size() const                 { return m_list.size(); }
+       template<class Predicate>
+       void sort(Predicate const& p)       { m_list.sort(p); }
+
+       template<class V>
+       void set(V& v)                      {for(auto & e : v) {m_list.push_back(e);} base::set();}
+
+       void push_back(value_type& v)       { m_list.push_back(v); base::set();}
+
+       template<class AT> //Note: Allocator must return word alligned buffer!
+       T& emplace_back(AT& allocator)
+       {
+               uint8_t* data = allocator.alloc_bytes(sizeof(value_type));
+               if(!data)
+                       throw std::bad_alloc();
+               value_type* v = new (data) value_type;
+               push_back(*v);
+               return *v;
+       };
+
+       using iterator = typename values_t::iterator;
+       iterator begin()                    { return m_list.begin(); }
+       iterator end()                      { return m_list.end(); }
+
+       using const_iterator = typename values_t::const_iterator;
+       const_iterator begin() const        { return m_list.begin(); }
+       const_iterator end() const          { return m_list.end(); }
+
+       sequenceof(){}
+
+private:
+       values_t m_list;
+};
+
+/***************************************************************************************
+* T_OBJFIELD_FTV
+***************************************************************************************/
+template<typename T, bool>
+struct fixedtypefield : T
+{
+       static constexpr element_type ie_type = element_type::T_OBJFIELD_FTV;
+
+       T& ref_nested() {return *this;}
+       T const & ref_nested() const {return *this;}
+};
+
+/***************************************************************************************
+* T_OBJFIELD_TF
+***************************************************************************************/
+template<bool>
+struct typefield : base
+{
+       static constexpr element_type ie_type = element_type::T_OBJFIELD_TF;
+       static constexpr const char* name() {return "type-field";}
+
+       typefield& ref_nested() {return *this;}
+       typefield const& ref_nested() const {return *this;}
+
+       bool is_unknown() const {return false;}
+};
+
+/***************************************************************************************
+* T_OBJECTIDENTIFIER
+***************************************************************************************/
+struct oid : ostring<>
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::OBJECT_IDENTIFIER), tag_type_t::IMPLICIT>;
+
+       static constexpr element_type ie_type = element_type::T_OBJECTIDENTIFIER;
+       static constexpr const char* name() {return "OBJECT IDENTIFIER";}
+};
+
+/***************************************************************************************
+* T_PRINTABLESTRING
+***************************************************************************************/
+template<class Constraint = constraints<false> >
+struct printable_string : ostring<Constraint>
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::PrintableString), tag_type_t::IMPLICIT>;
+       static constexpr const char* name() {return "PrintableString";}
+};
+
+/***************************************************************************************
+* T_IA5_STRING
+***************************************************************************************/
+template<class Constraint = constraints<false> >
+struct ia5_string : ostring<Constraint>
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::IA5String), tag_type_t::IMPLICIT>;
+       static constexpr const char* name() {return "IA5String";}
+};
+
+/***************************************************************************************
+* T_GRAPHIC_STRING
+***************************************************************************************/
+template<class Constraint = asn::constraints<false> >
+struct graphic_string : ostring<Constraint>
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::GraphicString), tag_type_t::IMPLICIT>;
+       static constexpr const char* name() {return "IA5String";}
+};
+
+/***************************************************************************************
+* T_UTF8_STRING
+***************************************************************************************/
+template<class Constraint = asn::constraints<false> >
+struct utf8_string : ostring<Constraint>
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::UTF8String), tag_type_t::IMPLICIT>;
+       static constexpr const char* name() {return "UTF8String";}
+};
+
+/***************************************************************************************
+* T_SET
+***************************************************************************************/
+template<int TotalNumEntries, int NumExtEntries, bool Extended, int NumOptEntries = 0>
+struct set : base
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::SET), tag_type_t::IMPLICIT>;
+
+       static constexpr element_type ie_type = element_type::T_SET;
+       static constexpr const char* name() {return "SET";}
+
+       static constexpr bound_t num_total_entries      = TotalNumEntries;
+       static constexpr bound_t num_opt_entries        = NumOptEntries;
+       static constexpr bound_t num_ext_entries        = NumExtEntries;
+
+       using constraint_t      = seq_range<TotalNumEntries, NumExtEntries, Extended>;
+};
+
+/***************************************************************************************
+* T_SET_OF
+***************************************************************************************/
+template<typename T, class Constraint = constraints<false> >
+struct setof : sequenceof<T, Constraint>
+{
+       using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::SET_OF), tag_type_t::IMPLICIT>;
+
+       static constexpr element_type ie_type = element_type::T_SET_OF;
+       static constexpr const char* name() {return "SET OF";}
+};
+} //namespace asn