14#include "keyple/core/util/BerTlvUtil.hpp"
19#include "keyple/core/util/cpp/Arrays.hpp"
20#include "keyple/core/util/cpp/exception/IllegalArgumentException.hpp"
21#include "keyple/core/util/cpp/exception/IndexOutOfBoundsException.hpp"
27using keyple::core::util::cpp::Arrays;
28using keyple::core::util::cpp::exception::IllegalArgumentException;
29using keyple::core::util::cpp::exception::IndexOutOfBoundsException;
31BerTlvUtil::BerTlvUtil()
35const std::map<const int, const std::vector<uint8_t>>
36BerTlvUtil::parseSimple(
37 const std::vector<uint8_t>& tlvStructure,
const bool primitiveOnly)
40 return parseBufferSimple(tlvStructure, primitiveOnly);
41 }
catch (
const IndexOutOfBoundsException& e) {
43 throw IllegalArgumentException(
"Invalid TLV structure.");
47const std::map<const int, std::vector<std::vector<uint8_t>>>
49 const std::vector<uint8_t>& tlvStructure,
const bool primitiveOnly)
52 return parseBuffer(tlvStructure, primitiveOnly);
53 }
catch (
const IndexOutOfBoundsException& e) {
55 throw IllegalArgumentException(
"Invalid TLV structure.");
60BerTlvUtil::isConstructed(
const int tagId)
62 if (tagId < 0 || tagId > 0xFFFFFF) {
63 throw IllegalArgumentException(
"Tag Id out of range.");
67 return (tagId & 0x20) != 0;
70 if (tagId <= 0xFFFF) {
71 return (tagId & 0x2000) != 0;
74 return (tagId & 0x200000) != 0;
77const std::map<const int, const std::vector<uint8_t>>
78BerTlvUtil::parseBufferSimple(
79 const std::vector<uint8_t>& tlvStructure,
const bool primitiveOnly)
81 std::map<const int, const std::vector<uint8_t>> tlvs;
85 const int tagSize = getTagSize(tlvStructure, offset);
86 const std::vector<uint8_t> tagBytes
87 = Arrays::copyOfRange(tlvStructure, offset, offset + tagSize);
88 const int tag = getTag(tlvStructure, offset, tagSize);
89 const int lengthSize = getLengthSize(tlvStructure, offset + tagSize);
91 = getLength(tlvStructure, offset + tagSize, lengthSize);
92 const std::vector<uint8_t> value = Arrays::copyOfRange(
94 offset + tagSize + lengthSize,
95 offset + tagSize + lengthSize + valueSize);
97 offset += tagSize + lengthSize + valueSize;
99 if ((tagBytes[0] & 0x20) != 0) {
101 if (!primitiveOnly) {
102 tlvs.insert({tag, value});
105 const std::map<const int, const std::vector<uint8_t>> parse
106 = parseSimple(value, primitiveOnly);
107 tlvs.insert(parse.begin(), parse.end());
110 tlvs.insert({tag, value});
112 }
while (offset <
static_cast<int>(tlvStructure.size()));
117const std::map<const int, std::vector<std::vector<uint8_t>>>
118BerTlvUtil::parseBuffer(
119 const std::vector<uint8_t>& tlvStructure,
const bool primitiveOnly)
121 std::map<const int, std::vector<std::vector<uint8_t>>> tlvs;
125 const int tagSize = getTagSize(tlvStructure, offset);
126 const std::vector<uint8_t> tagBytes
127 = Arrays::copyOfRange(tlvStructure, offset, offset + tagSize);
128 const int tag = getTag(tlvStructure, offset, tagSize);
129 const int lengthSize = getLengthSize(tlvStructure, offset + tagSize);
131 = getLength(tlvStructure, offset + tagSize, lengthSize);
132 const std::vector<uint8_t> value = Arrays::copyOfRange(
134 offset + tagSize + lengthSize,
135 offset + tagSize + lengthSize + valueSize);
137 offset += tagSize + lengthSize + valueSize;
139 if ((tagBytes[0] & 0x20) != 0) {
141 if (!primitiveOnly) {
142 std::vector<std::vector<uint8_t>>& values
143 = getOrInitTagValues(tlvs, tag);
144 values.push_back(value);
147 std::map<const int, std::vector<std::vector<uint8_t>>> tlvs2
148 = parse(value, primitiveOnly);
150 for (
const auto& entry : tlvs2) {
151 std::vector<std::vector<uint8_t>>& values
152 = getOrInitTagValues(tlvs, entry.first);
153 Arrays::addAll(values, entry.second);
157 std::vector<std::vector<uint8_t>>& values
158 = getOrInitTagValues(tlvs, tag);
159 values.push_back(value);
161 }
while (offset <
static_cast<int>(tlvStructure.size()));
166std::vector<std::vector<uint8_t>>&
167BerTlvUtil::getOrInitTagValues(
168 std::map<
const int, std::vector<std::vector<uint8_t>>>& tlvs,
const int tag)
170 const auto it = tlvs.find(tag);
172 if (it == tlvs.end()) {
173 std::vector<std::vector<uint8_t>> values;
174 tlvs.insert({tag, values});
178 return tlvs.find(tag)->second;
182BerTlvUtil::getTagSize(
183 const std::vector<uint8_t>& tlvStructure,
const int offset)
186 if (offset >=
static_cast<int>(tlvStructure.size())) {
187 throw IndexOutOfBoundsException(
"Invalid index");
190 if ((tlvStructure[offset] & 0x1F) == 0x1F) {
191 if ((tlvStructure[offset + 1] & 0x80) == 0) {
194 if ((tlvStructure[offset + 2] & 0x80) != 0) {
195 throw IllegalArgumentException(
"Invalid tag.");
207 const std::vector<uint8_t>& tlvStructure,
const int offset,
const int size)
211 return tlvStructure[offset] & 0xFF;
213 return ((tlvStructure[offset] & 0xFF) << 8)
214 + (tlvStructure[offset + 1] & 0xFF);
216 return ((tlvStructure[offset] & 0xFF) << 16)
217 + ((tlvStructure[offset + 1] & 0xFF) << 8)
218 + (tlvStructure[offset + 2] & 0xFF);
220 throw IllegalArgumentException(
"Bad tag size.");
225BerTlvUtil::getLengthSize(
226 const std::vector<uint8_t>& tlvStructure,
const int offset)
228 int firstByteLength = tlvStructure[offset] & 0xff;
230 switch (firstByteLength) {
236 if (firstByteLength >= 0x80) {
237 throw IllegalArgumentException(
"Invalid length.");
245BerTlvUtil::getLength(
246 const std::vector<uint8_t>& tlvStructure,
const int offset,
const int size)
250 return tlvStructure[offset] & 0x7F;
252 return tlvStructure[offset + 1] & 0xFF;
254 return ((tlvStructure[offset + 1] & 0xFF) << 8)
255 + (tlvStructure[offset + 2] & 0xFF);
257 throw IllegalArgumentException(
"Bad length size.");