Keyple Card Calypso C++ Library 2.1.0
Reference Terminal Reader API for C++
FileDataAdapter.cpp
Go to the documentation of this file.
1/**************************************************************************************************
2 * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ *
3 * *
4 * See the NOTICE file(s) distributed with this work for additional information regarding *
5 * copyright ownership. *
6 * *
7 * This program and the accompanying materials are made available under the terms of the Eclipse *
8 * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 *
9 * *
10 * SPDX-License-Identifier: EPL-2.0 *
11 **************************************************************************************************/
12
13#include "FileDataAdapter.h"
14
15/* Keyple Core Util */
16#include "Arrays.h"
17#include "ByteArrayUtil.h"
18#include "IndexOutOfBoundsException.h"
19#include "KeypleAssert.h"
20#include "KeypleStd.h"
21#include "System.h"
22
23namespace keyple {
24namespace card {
25namespace calypso {
26
27using namespace keyple::core::util;
28using namespace keyple::core::util::cpp;
29using namespace keyple::core::util::cpp::exception;
30
32
33FileDataAdapter::FileDataAdapter(const std::shared_ptr<FileData> source)
34{
35 const std::map<const uint8_t, std::vector<uint8_t>>& sourceContent =
36 source->getAllRecordsContent();
37
38 for (const auto& entry : sourceContent) {
39 mRecords.insert({entry.first, entry.second});
40 }
41}
42
43const std::map<const uint8_t, std::vector<uint8_t>>& FileDataAdapter::getAllRecordsContent()
44 const
45{
46 return mRecords;
47}
48
49const std::vector<uint8_t> FileDataAdapter::getContent() const
50{
51 return getContent(1);
52}
53
54const std::vector<uint8_t> FileDataAdapter::getContent(const uint8_t numRecord) const
55{
56 const auto it = mRecords.find(numRecord);
57 if (it == mRecords.end()) {
58 mLogger->warn("Record #% is not set\n", numRecord);
59 return std::vector<uint8_t>();
60 } else {
61 return it->second;
62 }
63}
64
65const std::vector<uint8_t> FileDataAdapter::getContent(const uint8_t numRecord,
66 const uint8_t dataOffset,
67 const uint8_t dataLength) const
68{
69 Assert::getInstance().greaterOrEqual(dataOffset, 0, "dataOffset")
70 .greaterOrEqual(dataLength, 1, "dataLength");
71
72 const auto it = mRecords.find(numRecord);
73 if (it == mRecords.end()) {
74 mLogger->warn("Record #% is not set\n", numRecord);
75 return std::vector<uint8_t>();
76 }
77
78 const std::vector<uint8_t>& content = it->second;
79 if (dataOffset >= static_cast<int>(content.size())) {
80 throw IndexOutOfBoundsException("Offset [" + std::to_string(dataOffset) + "] >= " +
81 "content length [" + std::to_string(content.size()) + "].");
82 }
83
84 const int toIndex = dataOffset + dataLength;
85 if (toIndex > static_cast<int>(content.size())) {
86 throw IndexOutOfBoundsException("Offset [" + std::to_string(dataOffset) + "] + " +
87 "Length [" + std::to_string(dataLength) + "] = " +
88 "[" + std::to_string(toIndex) + "] > " +
89 "content length [" + std::to_string(content.size()) + "].");
90 }
91
92 return Arrays::copyOfRange(content, dataOffset, toIndex);
93}
94
95const std::shared_ptr<int> FileDataAdapter::getContentAsCounterValue(const int numCounter) const
96{
97 Assert::getInstance().greaterOrEqual(numCounter, 1, "numCounter");
98
99 const auto it = mRecords.find(1);
100 if (it == mRecords.end()) {
101 mLogger->warn("Record #1 is not set\n");
102 return nullptr;
103 }
104
105 const std::vector<uint8_t>& rec1 = it->second;
106 const int counterIndex = (numCounter - 1) * 3;
107 if (counterIndex >= static_cast<int>(rec1.size())) {
108 mLogger->warn("Counter #% is not set (nb of actual counters = %)\n",
109 numCounter,
110 rec1.size() / 3);
111 return nullptr;
112 }
113
114 if (counterIndex + 3 > static_cast<int>(rec1.size())) {
115 throw IndexOutOfBoundsException("Counter #" + std::to_string(numCounter) + " " +
116 "has a truncated value (nb of actual counters = " +
117 std::to_string(rec1.size() / 3) + ").");
118 }
119
120 return std::make_shared<int>(ByteArrayUtil::threeBytesToInt(rec1, counterIndex));
121}
122
123const std::map<const int, const int> FileDataAdapter::getAllCountersValue() const
124{
125 std::map<const int, const int> result;
126
127 const auto it = mRecords.find(1);
128
129 if (it == mRecords.end()) {
130 mLogger->warn("Record #1 is not set\n");
131 return result;
132 }
133
134 const std::vector<uint8_t> rec1 = it->second;
135 const int length = static_cast<int>(rec1.size() - (rec1.size() % 3));
136 for (int i = 0, c = 1; i < length; i += 3, c++) {
137 result.insert({c, ByteArrayUtil::threeBytesToInt(rec1, i)});
138 }
139
140 return result;
141}
142
143void FileDataAdapter::setContent(const uint8_t numRecord, const std::vector<uint8_t>& content)
144{
145 mRecords.insert({numRecord, content});
146}
147
148void FileDataAdapter::setCounter(const uint8_t numCounter, const std::vector<uint8_t>& content)
149{
150 setContent(1, content, (numCounter - 1) * 3);
151}
152
153void FileDataAdapter::setContent(const uint8_t numRecord,
154 const std::vector<uint8_t> content,
155 const uint8_t offset)
156{
157 std::vector<uint8_t> newContent;
158 const int newLength = static_cast<int>(offset + content.size());
159
160 const auto it = mRecords.find(numRecord);
161 if (it == mRecords.end()) {
162 newContent = std::vector<uint8_t>(newLength);
163 } else {
164 const std::vector<uint8_t> oldContent = it->second;
165 if (static_cast<int>(oldContent.size()) <= offset) {
166 newContent = std::vector<uint8_t>(newLength);
167 System::arraycopy(oldContent, 0, newContent, 0, oldContent.size());
168 } else if (static_cast<int>(oldContent.size()) < newLength) {
169 newContent = std::vector<uint8_t>(newLength);
170 System::arraycopy(oldContent, 0, newContent, 0, offset);
171 } else {
172 newContent = oldContent;
173 }
174 }
175
176 System::arraycopy(content, 0, newContent, offset, content.size());
177 mRecords.insert({numRecord, newContent});
178}
179
180void FileDataAdapter::fillContent(const uint8_t numRecord,
181 const std::vector<uint8_t> content,
182 const uint8_t offset)
183{
184 std::vector<uint8_t> contentLeftPadded = content;
185
186 if (offset != 0) {
187 contentLeftPadded = std::vector<uint8_t>(offset + content.size());
188 System::arraycopy(content, 0, contentLeftPadded, offset, content.size());
189 }
190
191 const auto it = mRecords.find(numRecord);
192 if (it == mRecords.end()) {
193 mRecords.insert({numRecord, contentLeftPadded});
194 } else {
195 /* Make sure it's a non-const reference as it is updated in-place in the 'else' section */
196 std::vector<uint8_t>& actualContent = it->second;
197
198 if (actualContent.size() < contentLeftPadded.size()) {
199 for (int i = 0; i < static_cast<int>(actualContent.size()); i++) {
200 contentLeftPadded[i] |= actualContent[i];
201 }
202
203 mRecords.insert({numRecord, contentLeftPadded});
204 } else {
205 for (int i = 0; i < static_cast<int>(contentLeftPadded.size()); i++) {
206 actualContent[i] |= contentLeftPadded[i];
207 }
208 }
209 }
210}
211
212void FileDataAdapter::addCyclicContent(const std::vector<uint8_t>& content)
213{
214 std::vector<uint8_t> descendingKeys;
215
216 for (auto it = mRecords.rbegin(); it != mRecords.rend(); ++it) {
217 descendingKeys.push_back(it->first);
218 }
219
220 for (const auto& i : descendingKeys) {
221 mRecords.insert({static_cast<uint8_t>(i + 1), mRecords[i]});
222 }
223
224 mRecords.insert({static_cast<uint8_t>(1), content});
225}
226
227std::ostream& operator<<(std::ostream& os, const FileDataAdapter& fda)
228{
229 os << "FILE_DATA_ADAPTER: {"
230 << "RECORDS = " << fda.mRecords
231 << "}";
232
233 return os;
234}
235
236}
237}
238}
const std::map< const int, const int > getAllCountersValue() const override
const std::shared_ptr< int > getContentAsCounterValue(const int numCounter) const override
void setCounter(const uint8_t numCounter, const std::vector< uint8_t > &content)
void fillContent(const uint8_t numRecord, const std::vector< uint8_t > content, const uint8_t offset)
const std::map< const uint8_t, std::vector< uint8_t > > & getAllRecordsContent() const override
void addCyclicContent(const std::vector< uint8_t > &content)
const std::vector< uint8_t > getContent() const override
void setContent(const uint8_t numRecord, const std::vector< uint8_t > &content)
std::ostream & operator<<(std::ostream &os, const std::shared_ptr< ApduRequestAdapter > ara)