2 /******************************************************************************
4 * Copyright (c) 2019 AT&T Intellectual Property.
5 * Copyright (c) 2018-2019 Nokia.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************************/
21 // Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
23 // Local Includes: Application specific classes, functions, and libraries
25 #define IE_CLASS_SHIFT 6
27 #define IE_BIG_TAG_FST_OCTET 0b011111
32 constexpr tag_value_t invalid_tag = std::numeric_limits<tag_value_t>::max();
34 /***************************************************************************************
36 ***************************************************************************************/
37 template <class IE, bool constructed, class Enable=void>
40 template <class IE, bool constructed>
41 struct Tag<IE, constructed, std::enable_if_t< (IE::asn_identifier_t::tag_value < 31) > >
43 static constexpr tag_value_t value()
45 tag_value_t v = static_cast<uint8_t>(IE::asn_identifier_t::class_type);
47 v = constructed ? (v | (1u << IE_PC_SHIFT)) : v;
48 v |= static_cast<uint8_t>(IE::asn_identifier_t::tag_value);
52 static void inline encode(EncoderCtx& ctx)
54 ctx.refBuffer().putByte(static_cast<uint8_t>(value()));
59 template <class IE, bool constructed>
60 struct Tag<IE, constructed, std::enable_if_t< (IE::asn_identifier_t::tag_value >= 31) > >
62 static constexpr tag_value_t value()
64 static_assert(IE::asn_identifier_t::tag_value > 0, "null tag value");
66 tag_value_t v = static_cast<uint8_t>(IE::asn_identifier_t::class_type);
68 v = constructed ? (v | (1u << IE_PC_SHIFT)) : v;
69 v |= IE_BIG_TAG_FST_OCTET;
71 size_t leadbits = __builtin_clzll(IE::asn_identifier_t::tag_value);
72 tag_value_t tv = IE::asn_identifier_t::tag_value << leadbits;
73 size_t length = sizeof(tag_value_t)*CHAR_BIT - leadbits;
75 size_t shift = sizeof(tag_value_t)*CHAR_BIT - 7;
77 size_t lb = length % 7;
82 v |= static_cast<uint8_t>(tv >> (shift + 7 - lb));
91 v |= static_cast<uint8_t>(tv >> shift);
95 v &= ((tag_value_t)-1) & ~((tag_value_t) 0x80);
100 static void inline encode(EncoderCtx& ctx)
103 tag_value_t tv = data(size);
104 ctx.refBuffer().putBytes(reinterpret_cast<uint8_t*>(&tv), size);
109 static constexpr tag_value_t data(size_t& size)
112 tag_value_t tv = value();
113 size = sizeof(tag_value_t) - (__builtin_clzll(tv) >> 3);
115 uint8_t* ptr = reinterpret_cast<uint8_t*>(&rv);
117 size_t shift = (size - 1) * 8;
118 for(size_t i = 0; i < size; ++i)
120 ptr[i] = static_cast<uint8_t>(tv >> shift);
129 tag_value_t get_tag(DecoderCtx& ctx)
132 auto & buffer = ctx.refBuffer();
133 uint8_t const* data = buffer.getBytes(1);
138 if((data[0] & 0x1F) == IE_BIG_TAG_FST_OCTET)
140 size_t limit = sizeof(tag_value_t) - 1;
141 while((data = buffer.getBytes(1)))
145 ctx.refErrorCtx().sizeRangeError(0);
153 if(!(data[0] & 0x80))