#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 // Local Includes: Application specific classes, functions, and libraries #define IE_CLASS_SHIFT 6 #define IE_PC_SHIFT 5 #define IE_BIG_TAG_FST_OCTET 0b011111 namespace asn { namespace ber { constexpr tag_value_t invalid_tag = std::numeric_limits::max(); /*************************************************************************************** * Tag ***************************************************************************************/ template struct Tag; template struct Tag > { static constexpr tag_value_t value() { tag_value_t v = static_cast(IE::asn_identifier_t::class_type); v <<= IE_CLASS_SHIFT; v = constructed ? (v | (1u << IE_PC_SHIFT)) : v; v |= static_cast(IE::asn_identifier_t::tag_value); return v; } static void inline encode(EncoderCtx& ctx) { ctx.refBuffer().putByte(static_cast(value())); } }; template struct Tag= 31) > > { static constexpr tag_value_t value() { static_assert(IE::asn_identifier_t::tag_value > 0, "null tag value"); tag_value_t v = static_cast(IE::asn_identifier_t::class_type); v <<= IE_CLASS_SHIFT; v = constructed ? (v | (1u << IE_PC_SHIFT)) : v; v |= IE_BIG_TAG_FST_OCTET; size_t leadbits = __builtin_clzll(IE::asn_identifier_t::tag_value); tag_value_t tv = IE::asn_identifier_t::tag_value << leadbits; size_t length = sizeof(tag_value_t)*CHAR_BIT - leadbits; size_t shift = sizeof(tag_value_t)*CHAR_BIT - 7; size_t lb = length % 7; if(lb) { v <<= 8; v |= 0x80; v |= static_cast(tv >> (shift + 7 - lb)); tv <<= lb; length -= lb; } while(length) { v <<= 8; v |= 0x80; v |= static_cast(tv >> shift); tv <<= 7; length -= 7; } v &= ((tag_value_t)-1) & ~((tag_value_t) 0x80); return v; } static void inline encode(EncoderCtx& ctx) { size_t size = 0; tag_value_t tv = data(size); ctx.refBuffer().putBytes(reinterpret_cast(&tv), size); } private: static constexpr tag_value_t data(size_t& size) { tag_value_t rv = 0; tag_value_t tv = value(); size = sizeof(tag_value_t) - (__builtin_clzll(tv) >> 3); uint8_t* ptr = reinterpret_cast(&rv); size_t shift = (size - 1) * 8; for(size_t i = 0; i < size; ++i) { ptr[i] = static_cast(tv >> shift); shift -= 8; } return rv; } }; inline tag_value_t get_tag(DecoderCtx& ctx) { tag_value_t rv = 0; auto & buffer = ctx.refBuffer(); uint8_t const* data = buffer.getBytes(1); if (data) { rv = data[0]; if((data[0] & 0x1F) == IE_BIG_TAG_FST_OCTET) { size_t limit = sizeof(tag_value_t) - 1; while((data = buffer.getBytes(1))) { if(!limit) { ctx.refErrorCtx().sizeRangeError(0); break; } rv <<= 8; rv |= data[0]; --limit; if(!(data[0] & 0x80)) break; } } } return rv; } } //namespace ber } //namespace asn