3 /******************************************************************************
5 * Copyright (c) 2019 AT&T Intellectual Property.
6 * Copyright (c) 2018-2019 Nokia.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 ******************************************************************************/
22 // Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
23 #include <boost/intrusive/list.hpp>
26 // Local Includes: Application specific classes, functions, and libraries
27 #include "asn/constraints.hpp"
28 #include "asn/identifier.hpp"
32 enum class element_type : uint8_t
51 /***************************************************************************************
53 ***************************************************************************************/
57 static constexpr bool optional = false;
58 static constexpr bool extension = false;
60 static constexpr char const* name() {return "";}
62 void setpresent(bool p) {is_set = p;}
63 void clear() {is_set = false;}
65 bool is_valid() const {return is_set;}
69 void set() {is_set = true;}
73 base& operator=(const base&) = delete;
74 base (const base&) = delete;
77 /***************************************************************************************
79 ***************************************************************************************/
81 struct nulltype : base
83 using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::NULL_TYPE), tag_type_t::IMPLICIT>;
85 static constexpr element_type ie_type = element_type::T_NULL;
86 static constexpr const char* name() {return "NULL";}
91 /***************************************************************************************
93 ***************************************************************************************/
97 using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::BOOLEAN), tag_type_t::IMPLICIT>;
99 static constexpr element_type ie_type = element_type::T_BOOLEAN;
100 static constexpr const char* name() {return "BOOLEAN";}
102 using value_type = bool;
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();}
109 value_type m_value {false};
112 /***************************************************************************************
114 ***************************************************************************************/
115 template < class Constraint = constraints<false> >
116 struct integer : base
118 using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::INTEGER), tag_type_t::IMPLICIT>;
120 static constexpr element_type ie_type = element_type::T_INTEGER;
121 static constexpr const char* name() {return "INTEGER";}
123 using constraint_t = Constraint;
124 using value_type = int64_t;
126 bool equal(value_type v) const {return m_value == v;}
128 void set(value_type v) { m_value = v; base::set();}
129 value_type get() const { return m_value; }
131 void clear() { m_value = 0; base::clear();}
137 /***************************************************************************************
139 ***************************************************************************************/
140 template<int TotalNumEntries, int NumExtEntries, bool Extended>
141 struct enumerated : base
143 using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::ENUMERATED), tag_type_t::IMPLICIT>;
145 static constexpr element_type ie_type = element_type::T_ENUMERATED;
146 static constexpr const char* name() {return "ENUMERATED";}
148 using constraint_t = seq_range<TotalNumEntries, NumExtEntries, Extended>;
149 using value_type = typename constraint_t::value_type;
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();}
160 /***************************************************************************************
162 ***************************************************************************************/
163 template< class Constraint = constraints<false> >
164 struct ostring : base
166 using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::OCTET_STRING), tag_type_t::IMPLICIT>;
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;
175 value_type(size_t size, const char* data) : m_size(size), m_data(reinterpret_cast<const uint8_t*>(data)) {}
177 size_t size() const { return m_size; }
178 const uint8_t* data() const { return m_data; }
180 using const_iterator = uint8_t const*;
181 const_iterator begin() const { return data(); }
182 const_iterator end() const { return begin() + size(); }
184 void assign(void const* p, size_t sz) { m_data = static_cast<uint8_t const*>(p); m_size = sz; }
187 const uint8_t* m_data{ 0 };
191 value_type const& get() const { return m_value; }
193 //Use std::string, std::vector or IE_OSTR::value_type
194 template<typename T> value_type const& set(T const& tval)
196 set(tval.size(), tval.data());
201 void set(size_t size, void const* data)
203 m_value.assign(data, size);
208 ostring& emplace(AT& allocator, size_t size, uint8_t const * data_in)
213 uint8_t* data_out = allocator.alloc_bytes(size);
216 memcpy(data_out, data_in, size);
225 template<class AT, class T>
226 ostring& emplace(AT& allocator, T const& tval)
228 return emplace(allocator, tval.size(), reinterpret_cast<const uint8_t*>(tval.data()));
231 void clear() { m_value = value_type{}; base::clear();}
237 /***************************************************************************************
239 ***************************************************************************************/
240 template<class Constraint = constraints<false> >
241 struct bstring : base
243 using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::BIT_STRING), tag_type_t::IMPLICIT>;
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;
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){}
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; }
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; }
261 const uint8_t* m_data{ nullptr };
263 size_t m_bitqty{ 0 };
266 value_type const& get_buffer() const { return m_value; }
268 size_t get_bitqty() const { return m_value.bitqty(); }
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)
273 m_value.assign(tval.data(), tval.size(), bitqty);
278 void set_buffer(size_t bitqty, const uint8_t* data)
280 m_value.assign(data, (bitqty +7) >> 3, bitqty);
285 bstring& emplace_buffer(AT& allocator, size_t bitqty, uint8_t const * data_in)
287 size_t size = (bitqty +7) >> 3;
288 uint8_t* data_out = allocator.alloc_bytes(size);
290 throw std::bad_alloc();
292 memcpy(data_out, data_in, size);
293 set_buffer(bitqty, data_out);
297 void clear() { m_value = value_type{}; base::clear();}
299 uint64_t get_number() const
303 for(; i < m_value.size() - 1; ++i)
306 retval |= m_value.data()[i];
309 uint8_t shift = m_value.bitqty() % 8;
319 retval |= m_value.data()[i];
325 void set_number(AT& allocator, size_t bitqty, uint64_t data)
327 size_t size = (bitqty +7) >> 3;
328 uint8_t* data_out = allocator.alloc_bytes(size);
330 throw std::bad_alloc();
333 const uint8_t shift = bitqty % 8;
336 data_out[size-1] = data & (0xFF >> (8 - shift));
341 data_out[size-1] = data & (0xFF);
345 for (size_t i = 1; i <= size - 1; i++)
347 data_out[size-1-i] = data & (0xFF);
351 m_value.assign(data_out, size, bitqty);
359 /***************************************************************************************
361 ***************************************************************************************/
362 template<int TotalNumEntries, int NumExtEntries, bool Extended>
365 using asn_identifier_t = identifier<class_type_t::UNSPECIFIED, static_cast<tag_value_t>(tag_rvalue_t::CHOICE), tag_type_t::IMPLICIT>;
367 static constexpr element_type ie_type = element_type::T_CHOICE;
368 static constexpr const char* name() {return "CHOICE";}
370 using constraint_t = seq_range<TotalNumEntries, NumExtEntries, Extended>;
371 using index_type = size_t;
372 using value_type = size_t;
374 static constexpr index_type fst_index = 1;
375 static constexpr index_type ext_index = fst_index + TotalNumEntries;
377 static index_type normalize(index_type idx) {return idx - fst_index;}
378 static index_type denormalize(index_type idx) {return idx + fst_index;}
381 /***************************************************************************************
383 ***************************************************************************************/
384 template<int TotalNumEntries, int NumExtEntries, bool Extended, int NumOptEntries = 0>
385 struct sequence : base
387 using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::SEQUENCE), tag_type_t::IMPLICIT>;
389 static constexpr element_type ie_type = element_type::T_SEQUENCE;
390 static constexpr const char* name() {return "SEQUENCE";}
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;
396 using constraint_t = seq_range<TotalNumEntries, NumExtEntries, Extended>;
400 /***************************************************************************************
402 ***************************************************************************************/
403 template<typename T, class Constraint = constraints<false> >
404 struct sequenceof : base
406 using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::SEQUENCE_OF), tag_type_t::IMPLICIT>;
408 static constexpr element_type ie_type = element_type::T_SEQUENCE_OF;
409 static constexpr const char* name() {return "SEQUENCE OF";}
411 struct value_type : T, boost::intrusive::list_base_hook< boost::intrusive::link_mode<boost::intrusive::auto_unlink> >
415 value_type& operator=(const value_type&) = delete;
416 value_type (const value_type&) = delete;
419 using values_t = boost::intrusive::list<value_type, boost::intrusive::constant_time_size<false>>;
420 using constraint_t = Constraint;
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); }
429 void set(V& v) {for(auto & e : v) {m_list.push_back(e);} base::set();}
431 void push_back(value_type& v) { m_list.push_back(v); base::set();}
433 template<class AT> //Note: Allocator must return word alligned buffer!
434 T& emplace_back(AT& allocator)
436 uint8_t* data = allocator.alloc_bytes(sizeof(value_type));
438 throw std::bad_alloc();
439 value_type* v = new (data) value_type;
444 using iterator = typename values_t::iterator;
445 iterator begin() { return m_list.begin(); }
446 iterator end() { return m_list.end(); }
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(); }
458 /***************************************************************************************
460 ***************************************************************************************/
461 template<typename T, bool>
462 struct fixedtypefield : T
464 static constexpr element_type ie_type = element_type::T_OBJFIELD_FTV;
466 T& ref_nested() {return *this;}
467 T const & ref_nested() const {return *this;}
470 /***************************************************************************************
472 ***************************************************************************************/
474 struct typefield : base
476 static constexpr element_type ie_type = element_type::T_OBJFIELD_TF;
477 static constexpr const char* name() {return "type-field";}
479 typefield& ref_nested() {return *this;}
480 typefield const& ref_nested() const {return *this;}
482 bool is_unknown() const {return false;}
485 /***************************************************************************************
487 ***************************************************************************************/
488 struct oid : ostring<>
490 using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::OBJECT_IDENTIFIER), tag_type_t::IMPLICIT>;
492 static constexpr element_type ie_type = element_type::T_OBJECTIDENTIFIER;
493 static constexpr const char* name() {return "OBJECT IDENTIFIER";}
496 /***************************************************************************************
498 ***************************************************************************************/
499 template<class Constraint = constraints<false> >
500 struct printable_string : ostring<Constraint>
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";}
506 /***************************************************************************************
508 ***************************************************************************************/
509 template<class Constraint = constraints<false> >
510 struct ia5_string : ostring<Constraint>
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";}
516 /***************************************************************************************
518 ***************************************************************************************/
519 template<class Constraint = asn::constraints<false> >
520 struct graphic_string : ostring<Constraint>
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";}
526 /***************************************************************************************
528 ***************************************************************************************/
529 template<class Constraint = asn::constraints<false> >
530 struct utf8_string : ostring<Constraint>
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";}
536 /***************************************************************************************
538 ***************************************************************************************/
539 template<int TotalNumEntries, int NumExtEntries, bool Extended, int NumOptEntries = 0>
542 using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::SET), tag_type_t::IMPLICIT>;
544 static constexpr element_type ie_type = element_type::T_SET;
545 static constexpr const char* name() {return "SET";}
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;
551 using constraint_t = seq_range<TotalNumEntries, NumExtEntries, Extended>;
554 /***************************************************************************************
556 ***************************************************************************************/
557 template<typename T, class Constraint = constraints<false> >
558 struct setof : sequenceof<T, Constraint>
560 using asn_identifier_t = identifier<class_type_t::UNIVERSAL, static_cast<tag_value_t>(tag_rvalue_t::SET_OF), tag_type_t::IMPLICIT>;
562 static constexpr element_type ie_type = element_type::T_SET_OF;
563 static constexpr const char* name() {return "SET OF";}