1*09635541SAndroid Build Coastguard Worker /*
2*09635541SAndroid Build Coastguard Worker * Copyright 2019 Google LLC
3*09635541SAndroid Build Coastguard Worker *
4*09635541SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*09635541SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*09635541SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*09635541SAndroid Build Coastguard Worker *
8*09635541SAndroid Build Coastguard Worker * https://www.apache.org/licenses/LICENSE-2.0
9*09635541SAndroid Build Coastguard Worker *
10*09635541SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*09635541SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*09635541SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*09635541SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*09635541SAndroid Build Coastguard Worker * limitations under the License.
15*09635541SAndroid Build Coastguard Worker */
16*09635541SAndroid Build Coastguard Worker
17*09635541SAndroid Build Coastguard Worker #include "cppbor.h"
18*09635541SAndroid Build Coastguard Worker
19*09635541SAndroid Build Coastguard Worker #include <inttypes.h>
20*09635541SAndroid Build Coastguard Worker #include <openssl/sha.h>
21*09635541SAndroid Build Coastguard Worker #include <cstdint>
22*09635541SAndroid Build Coastguard Worker #include <cstdio>
23*09635541SAndroid Build Coastguard Worker
24*09635541SAndroid Build Coastguard Worker #include "cppbor_parse.h"
25*09635541SAndroid Build Coastguard Worker
26*09635541SAndroid Build Coastguard Worker using std::string;
27*09635541SAndroid Build Coastguard Worker using std::vector;
28*09635541SAndroid Build Coastguard Worker
29*09635541SAndroid Build Coastguard Worker #ifndef __TRUSTY__
30*09635541SAndroid Build Coastguard Worker #include <android-base/logging.h>
31*09635541SAndroid Build Coastguard Worker #define LOG_TAG "CppBor"
32*09635541SAndroid Build Coastguard Worker #else
33*09635541SAndroid Build Coastguard Worker #define CHECK(x) (void)(x)
34*09635541SAndroid Build Coastguard Worker #endif
35*09635541SAndroid Build Coastguard Worker
36*09635541SAndroid Build Coastguard Worker namespace cppbor {
37*09635541SAndroid Build Coastguard Worker
38*09635541SAndroid Build Coastguard Worker namespace {
39*09635541SAndroid Build Coastguard Worker
40*09635541SAndroid Build Coastguard Worker template <typename T, typename Iterator, typename = std::enable_if<std::is_unsigned<T>::value>>
41*09635541SAndroid Build Coastguard Worker Iterator writeBigEndian(T value, Iterator pos) {
42*09635541SAndroid Build Coastguard Worker for (unsigned i = 0; i < sizeof(value); ++i) {
43*09635541SAndroid Build Coastguard Worker *pos++ = static_cast<uint8_t>(value >> (8 * (sizeof(value) - 1)));
44*09635541SAndroid Build Coastguard Worker value = static_cast<T>(value << 8);
45*09635541SAndroid Build Coastguard Worker }
46*09635541SAndroid Build Coastguard Worker return pos;
47*09635541SAndroid Build Coastguard Worker }
48*09635541SAndroid Build Coastguard Worker
49*09635541SAndroid Build Coastguard Worker template <typename T, typename = std::enable_if<std::is_unsigned<T>::value>>
writeBigEndian(T value,std::function<void (uint8_t)> & cb)50*09635541SAndroid Build Coastguard Worker void writeBigEndian(T value, std::function<void(uint8_t)>& cb) {
51*09635541SAndroid Build Coastguard Worker for (unsigned i = 0; i < sizeof(value); ++i) {
52*09635541SAndroid Build Coastguard Worker cb(static_cast<uint8_t>(value >> (8 * (sizeof(value) - 1))));
53*09635541SAndroid Build Coastguard Worker value = static_cast<T>(value << 8);
54*09635541SAndroid Build Coastguard Worker }
55*09635541SAndroid Build Coastguard Worker }
56*09635541SAndroid Build Coastguard Worker
cborAreAllElementsNonCompound(const Item * compoundItem)57*09635541SAndroid Build Coastguard Worker bool cborAreAllElementsNonCompound(const Item* compoundItem) {
58*09635541SAndroid Build Coastguard Worker if (compoundItem->type() == ARRAY) {
59*09635541SAndroid Build Coastguard Worker const Array* array = compoundItem->asArray();
60*09635541SAndroid Build Coastguard Worker for (size_t n = 0; n < array->size(); n++) {
61*09635541SAndroid Build Coastguard Worker const Item* entry = (*array)[n].get();
62*09635541SAndroid Build Coastguard Worker switch (entry->type()) {
63*09635541SAndroid Build Coastguard Worker case ARRAY:
64*09635541SAndroid Build Coastguard Worker case MAP:
65*09635541SAndroid Build Coastguard Worker return false;
66*09635541SAndroid Build Coastguard Worker default:
67*09635541SAndroid Build Coastguard Worker break;
68*09635541SAndroid Build Coastguard Worker }
69*09635541SAndroid Build Coastguard Worker }
70*09635541SAndroid Build Coastguard Worker } else {
71*09635541SAndroid Build Coastguard Worker const Map* map = compoundItem->asMap();
72*09635541SAndroid Build Coastguard Worker for (auto& [keyEntry, valueEntry] : *map) {
73*09635541SAndroid Build Coastguard Worker switch (keyEntry->type()) {
74*09635541SAndroid Build Coastguard Worker case ARRAY:
75*09635541SAndroid Build Coastguard Worker case MAP:
76*09635541SAndroid Build Coastguard Worker return false;
77*09635541SAndroid Build Coastguard Worker default:
78*09635541SAndroid Build Coastguard Worker break;
79*09635541SAndroid Build Coastguard Worker }
80*09635541SAndroid Build Coastguard Worker switch (valueEntry->type()) {
81*09635541SAndroid Build Coastguard Worker case ARRAY:
82*09635541SAndroid Build Coastguard Worker case MAP:
83*09635541SAndroid Build Coastguard Worker return false;
84*09635541SAndroid Build Coastguard Worker default:
85*09635541SAndroid Build Coastguard Worker break;
86*09635541SAndroid Build Coastguard Worker }
87*09635541SAndroid Build Coastguard Worker }
88*09635541SAndroid Build Coastguard Worker }
89*09635541SAndroid Build Coastguard Worker return true;
90*09635541SAndroid Build Coastguard Worker }
91*09635541SAndroid Build Coastguard Worker
prettyPrintInternal(const Item * item,string & out,size_t indent,size_t maxBStrSize,const vector<string> & mapKeysToNotPrint)92*09635541SAndroid Build Coastguard Worker bool prettyPrintInternal(const Item* item, string& out, size_t indent, size_t maxBStrSize,
93*09635541SAndroid Build Coastguard Worker const vector<string>& mapKeysToNotPrint) {
94*09635541SAndroid Build Coastguard Worker if (!item) {
95*09635541SAndroid Build Coastguard Worker out.append("<NULL>");
96*09635541SAndroid Build Coastguard Worker return false;
97*09635541SAndroid Build Coastguard Worker }
98*09635541SAndroid Build Coastguard Worker
99*09635541SAndroid Build Coastguard Worker char buf[80];
100*09635541SAndroid Build Coastguard Worker
101*09635541SAndroid Build Coastguard Worker string indentString(indent, ' ');
102*09635541SAndroid Build Coastguard Worker
103*09635541SAndroid Build Coastguard Worker size_t tagCount = item->semanticTagCount();
104*09635541SAndroid Build Coastguard Worker while (tagCount > 0) {
105*09635541SAndroid Build Coastguard Worker --tagCount;
106*09635541SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "tag %" PRIu64 " ", item->semanticTag(tagCount));
107*09635541SAndroid Build Coastguard Worker out.append(buf);
108*09635541SAndroid Build Coastguard Worker }
109*09635541SAndroid Build Coastguard Worker
110*09635541SAndroid Build Coastguard Worker switch (item->type()) {
111*09635541SAndroid Build Coastguard Worker case SEMANTIC:
112*09635541SAndroid Build Coastguard Worker // Handled above.
113*09635541SAndroid Build Coastguard Worker break;
114*09635541SAndroid Build Coastguard Worker
115*09635541SAndroid Build Coastguard Worker case UINT:
116*09635541SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "%" PRIu64, item->asUint()->unsignedValue());
117*09635541SAndroid Build Coastguard Worker out.append(buf);
118*09635541SAndroid Build Coastguard Worker break;
119*09635541SAndroid Build Coastguard Worker
120*09635541SAndroid Build Coastguard Worker case NINT:
121*09635541SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "%" PRId64, item->asNint()->value());
122*09635541SAndroid Build Coastguard Worker out.append(buf);
123*09635541SAndroid Build Coastguard Worker break;
124*09635541SAndroid Build Coastguard Worker
125*09635541SAndroid Build Coastguard Worker case BSTR: {
126*09635541SAndroid Build Coastguard Worker const uint8_t* valueData;
127*09635541SAndroid Build Coastguard Worker size_t valueSize;
128*09635541SAndroid Build Coastguard Worker const Bstr* bstr = item->asBstr();
129*09635541SAndroid Build Coastguard Worker if (bstr != nullptr) {
130*09635541SAndroid Build Coastguard Worker const vector<uint8_t>& value = bstr->value();
131*09635541SAndroid Build Coastguard Worker valueData = value.data();
132*09635541SAndroid Build Coastguard Worker valueSize = value.size();
133*09635541SAndroid Build Coastguard Worker } else {
134*09635541SAndroid Build Coastguard Worker const ViewBstr* viewBstr = item->asViewBstr();
135*09635541SAndroid Build Coastguard Worker assert(viewBstr != nullptr);
136*09635541SAndroid Build Coastguard Worker
137*09635541SAndroid Build Coastguard Worker valueData = viewBstr->view().data();
138*09635541SAndroid Build Coastguard Worker valueSize = viewBstr->view().size();
139*09635541SAndroid Build Coastguard Worker }
140*09635541SAndroid Build Coastguard Worker
141*09635541SAndroid Build Coastguard Worker if (valueSize > maxBStrSize) {
142*09635541SAndroid Build Coastguard Worker unsigned char digest[SHA_DIGEST_LENGTH];
143*09635541SAndroid Build Coastguard Worker SHA_CTX ctx;
144*09635541SAndroid Build Coastguard Worker SHA1_Init(&ctx);
145*09635541SAndroid Build Coastguard Worker SHA1_Update(&ctx, valueData, valueSize);
146*09635541SAndroid Build Coastguard Worker SHA1_Final(digest, &ctx);
147*09635541SAndroid Build Coastguard Worker char buf2[SHA_DIGEST_LENGTH * 2 + 1];
148*09635541SAndroid Build Coastguard Worker for (size_t n = 0; n < SHA_DIGEST_LENGTH; n++) {
149*09635541SAndroid Build Coastguard Worker snprintf(buf2 + n * 2, 3, "%02x", digest[n]);
150*09635541SAndroid Build Coastguard Worker }
151*09635541SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "<bstr size=%zd sha1=%s>", valueSize, buf2);
152*09635541SAndroid Build Coastguard Worker out.append(buf);
153*09635541SAndroid Build Coastguard Worker } else {
154*09635541SAndroid Build Coastguard Worker out.append("{");
155*09635541SAndroid Build Coastguard Worker for (size_t n = 0; n < valueSize; n++) {
156*09635541SAndroid Build Coastguard Worker if (n > 0) {
157*09635541SAndroid Build Coastguard Worker out.append(", ");
158*09635541SAndroid Build Coastguard Worker }
159*09635541SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "0x%02x", valueData[n]);
160*09635541SAndroid Build Coastguard Worker out.append(buf);
161*09635541SAndroid Build Coastguard Worker }
162*09635541SAndroid Build Coastguard Worker out.append("}");
163*09635541SAndroid Build Coastguard Worker }
164*09635541SAndroid Build Coastguard Worker } break;
165*09635541SAndroid Build Coastguard Worker
166*09635541SAndroid Build Coastguard Worker case TSTR:
167*09635541SAndroid Build Coastguard Worker out.append("'");
168*09635541SAndroid Build Coastguard Worker {
169*09635541SAndroid Build Coastguard Worker // TODO: escape "'" characters
170*09635541SAndroid Build Coastguard Worker if (item->asTstr() != nullptr) {
171*09635541SAndroid Build Coastguard Worker out.append(item->asTstr()->value().c_str());
172*09635541SAndroid Build Coastguard Worker } else {
173*09635541SAndroid Build Coastguard Worker const ViewTstr* viewTstr = item->asViewTstr();
174*09635541SAndroid Build Coastguard Worker assert(viewTstr != nullptr);
175*09635541SAndroid Build Coastguard Worker out.append(viewTstr->view());
176*09635541SAndroid Build Coastguard Worker }
177*09635541SAndroid Build Coastguard Worker }
178*09635541SAndroid Build Coastguard Worker out.append("'");
179*09635541SAndroid Build Coastguard Worker break;
180*09635541SAndroid Build Coastguard Worker
181*09635541SAndroid Build Coastguard Worker case ARRAY: {
182*09635541SAndroid Build Coastguard Worker const Array* array = item->asArray();
183*09635541SAndroid Build Coastguard Worker if (array->size() == 0) {
184*09635541SAndroid Build Coastguard Worker out.append("[]");
185*09635541SAndroid Build Coastguard Worker } else if (cborAreAllElementsNonCompound(array)) {
186*09635541SAndroid Build Coastguard Worker out.append("[");
187*09635541SAndroid Build Coastguard Worker for (size_t n = 0; n < array->size(); n++) {
188*09635541SAndroid Build Coastguard Worker if (!prettyPrintInternal((*array)[n].get(), out, indent + 2, maxBStrSize,
189*09635541SAndroid Build Coastguard Worker mapKeysToNotPrint)) {
190*09635541SAndroid Build Coastguard Worker return false;
191*09635541SAndroid Build Coastguard Worker }
192*09635541SAndroid Build Coastguard Worker out.append(", ");
193*09635541SAndroid Build Coastguard Worker }
194*09635541SAndroid Build Coastguard Worker out.append("]");
195*09635541SAndroid Build Coastguard Worker } else {
196*09635541SAndroid Build Coastguard Worker out.append("[\n" + indentString);
197*09635541SAndroid Build Coastguard Worker for (size_t n = 0; n < array->size(); n++) {
198*09635541SAndroid Build Coastguard Worker out.append(" ");
199*09635541SAndroid Build Coastguard Worker if (!prettyPrintInternal((*array)[n].get(), out, indent + 2, maxBStrSize,
200*09635541SAndroid Build Coastguard Worker mapKeysToNotPrint)) {
201*09635541SAndroid Build Coastguard Worker return false;
202*09635541SAndroid Build Coastguard Worker }
203*09635541SAndroid Build Coastguard Worker out.append(",\n" + indentString);
204*09635541SAndroid Build Coastguard Worker }
205*09635541SAndroid Build Coastguard Worker out.append("]");
206*09635541SAndroid Build Coastguard Worker }
207*09635541SAndroid Build Coastguard Worker } break;
208*09635541SAndroid Build Coastguard Worker
209*09635541SAndroid Build Coastguard Worker case MAP: {
210*09635541SAndroid Build Coastguard Worker const Map* map = item->asMap();
211*09635541SAndroid Build Coastguard Worker
212*09635541SAndroid Build Coastguard Worker if (map->size() == 0) {
213*09635541SAndroid Build Coastguard Worker out.append("{}");
214*09635541SAndroid Build Coastguard Worker } else {
215*09635541SAndroid Build Coastguard Worker out.append("{\n" + indentString);
216*09635541SAndroid Build Coastguard Worker for (auto& [map_key, map_value] : *map) {
217*09635541SAndroid Build Coastguard Worker out.append(" ");
218*09635541SAndroid Build Coastguard Worker
219*09635541SAndroid Build Coastguard Worker if (!prettyPrintInternal(map_key.get(), out, indent + 2, maxBStrSize,
220*09635541SAndroid Build Coastguard Worker mapKeysToNotPrint)) {
221*09635541SAndroid Build Coastguard Worker return false;
222*09635541SAndroid Build Coastguard Worker }
223*09635541SAndroid Build Coastguard Worker out.append(" : ");
224*09635541SAndroid Build Coastguard Worker if (map_key->type() == TSTR &&
225*09635541SAndroid Build Coastguard Worker std::find(mapKeysToNotPrint.begin(), mapKeysToNotPrint.end(),
226*09635541SAndroid Build Coastguard Worker map_key->asTstr()->value()) != mapKeysToNotPrint.end()) {
227*09635541SAndroid Build Coastguard Worker out.append("<not printed>");
228*09635541SAndroid Build Coastguard Worker } else {
229*09635541SAndroid Build Coastguard Worker if (!prettyPrintInternal(map_value.get(), out, indent + 2, maxBStrSize,
230*09635541SAndroid Build Coastguard Worker mapKeysToNotPrint)) {
231*09635541SAndroid Build Coastguard Worker return false;
232*09635541SAndroid Build Coastguard Worker }
233*09635541SAndroid Build Coastguard Worker }
234*09635541SAndroid Build Coastguard Worker out.append(",\n" + indentString);
235*09635541SAndroid Build Coastguard Worker }
236*09635541SAndroid Build Coastguard Worker out.append("}");
237*09635541SAndroid Build Coastguard Worker }
238*09635541SAndroid Build Coastguard Worker } break;
239*09635541SAndroid Build Coastguard Worker
240*09635541SAndroid Build Coastguard Worker case SIMPLE:
241*09635541SAndroid Build Coastguard Worker switch (item->asSimple()->simpleType()) {
242*09635541SAndroid Build Coastguard Worker case BOOLEAN:
243*09635541SAndroid Build Coastguard Worker out.append(item->asSimple()->asBool()->value() ? "true" : "false");
244*09635541SAndroid Build Coastguard Worker break;
245*09635541SAndroid Build Coastguard Worker case NULL_T:
246*09635541SAndroid Build Coastguard Worker out.append("null");
247*09635541SAndroid Build Coastguard Worker break;
248*09635541SAndroid Build Coastguard Worker case FLOAT:
249*09635541SAndroid Build Coastguard Worker #if defined(__STDC_IEC_559__) || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
250*09635541SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "%f", item->asSimple()->asFloat()->value());
251*09635541SAndroid Build Coastguard Worker out.append(buf);
252*09635541SAndroid Build Coastguard Worker break;
253*09635541SAndroid Build Coastguard Worker #else
254*09635541SAndroid Build Coastguard Worker #ifndef __TRUSTY__
255*09635541SAndroid Build Coastguard Worker LOG(ERROR) << "float not supported for this platform.";
256*09635541SAndroid Build Coastguard Worker #endif // __TRUSTY__
257*09635541SAndroid Build Coastguard Worker return false;
258*09635541SAndroid Build Coastguard Worker #endif // __STDC_IEC_559__ || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
259*09635541SAndroid Build Coastguard Worker case DOUBLE:
260*09635541SAndroid Build Coastguard Worker #if defined(__STDC_IEC_559__) || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
261*09635541SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "%f", item->asSimple()->asDouble()->value());
262*09635541SAndroid Build Coastguard Worker out.append(buf);
263*09635541SAndroid Build Coastguard Worker break;
264*09635541SAndroid Build Coastguard Worker #else
265*09635541SAndroid Build Coastguard Worker #ifndef __TRUSTY__
266*09635541SAndroid Build Coastguard Worker LOG(ERROR) << "double not supported for this platform.";
267*09635541SAndroid Build Coastguard Worker #endif // __TRUSTY__
268*09635541SAndroid Build Coastguard Worker return false;
269*09635541SAndroid Build Coastguard Worker #endif // __STDC_IEC_559__ || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
270*09635541SAndroid Build Coastguard Worker default:
271*09635541SAndroid Build Coastguard Worker #ifndef __TRUSTY__
272*09635541SAndroid Build Coastguard Worker LOG(ERROR) << "Only boolean/null/float/double is implemented for SIMPLE";
273*09635541SAndroid Build Coastguard Worker #endif // __TRUSTY__
274*09635541SAndroid Build Coastguard Worker return false;
275*09635541SAndroid Build Coastguard Worker }
276*09635541SAndroid Build Coastguard Worker break;
277*09635541SAndroid Build Coastguard Worker }
278*09635541SAndroid Build Coastguard Worker
279*09635541SAndroid Build Coastguard Worker return true;
280*09635541SAndroid Build Coastguard Worker }
281*09635541SAndroid Build Coastguard Worker
282*09635541SAndroid Build Coastguard Worker } // namespace
283*09635541SAndroid Build Coastguard Worker
headerSize(uint64_t addlInfo)284*09635541SAndroid Build Coastguard Worker size_t headerSize(uint64_t addlInfo) {
285*09635541SAndroid Build Coastguard Worker if (addlInfo < ONE_BYTE_LENGTH) return 1;
286*09635541SAndroid Build Coastguard Worker if (addlInfo <= std::numeric_limits<uint8_t>::max()) return 2;
287*09635541SAndroid Build Coastguard Worker if (addlInfo <= std::numeric_limits<uint16_t>::max()) return 3;
288*09635541SAndroid Build Coastguard Worker if (addlInfo <= std::numeric_limits<uint32_t>::max()) return 5;
289*09635541SAndroid Build Coastguard Worker return 9;
290*09635541SAndroid Build Coastguard Worker }
291*09635541SAndroid Build Coastguard Worker
encodeHeader(MajorType type,uint64_t addlInfo,uint8_t * pos,const uint8_t * end)292*09635541SAndroid Build Coastguard Worker uint8_t* encodeHeader(MajorType type, uint64_t addlInfo, uint8_t* pos, const uint8_t* end) {
293*09635541SAndroid Build Coastguard Worker size_t sz = headerSize(addlInfo);
294*09635541SAndroid Build Coastguard Worker if (end - pos < static_cast<ssize_t>(sz)) return nullptr;
295*09635541SAndroid Build Coastguard Worker switch (sz) {
296*09635541SAndroid Build Coastguard Worker case 1:
297*09635541SAndroid Build Coastguard Worker *pos++ = type | static_cast<uint8_t>(addlInfo);
298*09635541SAndroid Build Coastguard Worker return pos;
299*09635541SAndroid Build Coastguard Worker case 2:
300*09635541SAndroid Build Coastguard Worker *pos++ = type | static_cast<MajorType>(ONE_BYTE_LENGTH);
301*09635541SAndroid Build Coastguard Worker *pos++ = static_cast<uint8_t>(addlInfo);
302*09635541SAndroid Build Coastguard Worker return pos;
303*09635541SAndroid Build Coastguard Worker case 3:
304*09635541SAndroid Build Coastguard Worker *pos++ = type | static_cast<MajorType>(TWO_BYTE_LENGTH);
305*09635541SAndroid Build Coastguard Worker return writeBigEndian(static_cast<uint16_t>(addlInfo), pos);
306*09635541SAndroid Build Coastguard Worker case 5:
307*09635541SAndroid Build Coastguard Worker *pos++ = type | static_cast<MajorType>(FOUR_BYTE_LENGTH);
308*09635541SAndroid Build Coastguard Worker return writeBigEndian(static_cast<uint32_t>(addlInfo), pos);
309*09635541SAndroid Build Coastguard Worker case 9:
310*09635541SAndroid Build Coastguard Worker *pos++ = type | static_cast<MajorType>(EIGHT_BYTE_LENGTH);
311*09635541SAndroid Build Coastguard Worker return writeBigEndian(addlInfo, pos);
312*09635541SAndroid Build Coastguard Worker default:
313*09635541SAndroid Build Coastguard Worker CHECK(false); // Impossible to get here.
314*09635541SAndroid Build Coastguard Worker return nullptr;
315*09635541SAndroid Build Coastguard Worker }
316*09635541SAndroid Build Coastguard Worker }
317*09635541SAndroid Build Coastguard Worker
encodeHeader(MajorType type,uint64_t addlInfo,EncodeCallback encodeCallback)318*09635541SAndroid Build Coastguard Worker void encodeHeader(MajorType type, uint64_t addlInfo, EncodeCallback encodeCallback) {
319*09635541SAndroid Build Coastguard Worker size_t sz = headerSize(addlInfo);
320*09635541SAndroid Build Coastguard Worker switch (sz) {
321*09635541SAndroid Build Coastguard Worker case 1:
322*09635541SAndroid Build Coastguard Worker encodeCallback(type | static_cast<uint8_t>(addlInfo));
323*09635541SAndroid Build Coastguard Worker break;
324*09635541SAndroid Build Coastguard Worker case 2:
325*09635541SAndroid Build Coastguard Worker encodeCallback(type | static_cast<MajorType>(ONE_BYTE_LENGTH));
326*09635541SAndroid Build Coastguard Worker encodeCallback(static_cast<uint8_t>(addlInfo));
327*09635541SAndroid Build Coastguard Worker break;
328*09635541SAndroid Build Coastguard Worker case 3:
329*09635541SAndroid Build Coastguard Worker encodeCallback(type | static_cast<MajorType>(TWO_BYTE_LENGTH));
330*09635541SAndroid Build Coastguard Worker writeBigEndian(static_cast<uint16_t>(addlInfo), encodeCallback);
331*09635541SAndroid Build Coastguard Worker break;
332*09635541SAndroid Build Coastguard Worker case 5:
333*09635541SAndroid Build Coastguard Worker encodeCallback(type | static_cast<MajorType>(FOUR_BYTE_LENGTH));
334*09635541SAndroid Build Coastguard Worker writeBigEndian(static_cast<uint32_t>(addlInfo), encodeCallback);
335*09635541SAndroid Build Coastguard Worker break;
336*09635541SAndroid Build Coastguard Worker case 9:
337*09635541SAndroid Build Coastguard Worker encodeCallback(type | static_cast<MajorType>(EIGHT_BYTE_LENGTH));
338*09635541SAndroid Build Coastguard Worker writeBigEndian(addlInfo, encodeCallback);
339*09635541SAndroid Build Coastguard Worker break;
340*09635541SAndroid Build Coastguard Worker default:
341*09635541SAndroid Build Coastguard Worker CHECK(false); // Impossible to get here.
342*09635541SAndroid Build Coastguard Worker }
343*09635541SAndroid Build Coastguard Worker }
344*09635541SAndroid Build Coastguard Worker
operator ==(const Item & other) const345*09635541SAndroid Build Coastguard Worker bool Item::operator==(const Item& other) const& {
346*09635541SAndroid Build Coastguard Worker if (type() != other.type()) return false;
347*09635541SAndroid Build Coastguard Worker switch (type()) {
348*09635541SAndroid Build Coastguard Worker case UINT:
349*09635541SAndroid Build Coastguard Worker return *asUint() == *(other.asUint());
350*09635541SAndroid Build Coastguard Worker case NINT:
351*09635541SAndroid Build Coastguard Worker return *asNint() == *(other.asNint());
352*09635541SAndroid Build Coastguard Worker case BSTR:
353*09635541SAndroid Build Coastguard Worker if (asBstr() != nullptr && other.asBstr() != nullptr) {
354*09635541SAndroid Build Coastguard Worker return *asBstr() == *(other.asBstr());
355*09635541SAndroid Build Coastguard Worker }
356*09635541SAndroid Build Coastguard Worker if (asViewBstr() != nullptr && other.asViewBstr() != nullptr) {
357*09635541SAndroid Build Coastguard Worker return *asViewBstr() == *(other.asViewBstr());
358*09635541SAndroid Build Coastguard Worker }
359*09635541SAndroid Build Coastguard Worker // Interesting corner case: comparing a Bstr and ViewBstr with
360*09635541SAndroid Build Coastguard Worker // identical contents. The function currently returns false for
361*09635541SAndroid Build Coastguard Worker // this case.
362*09635541SAndroid Build Coastguard Worker // TODO: if it should return true, this needs a deep comparison
363*09635541SAndroid Build Coastguard Worker return false;
364*09635541SAndroid Build Coastguard Worker case TSTR:
365*09635541SAndroid Build Coastguard Worker if (asTstr() != nullptr && other.asTstr() != nullptr) {
366*09635541SAndroid Build Coastguard Worker return *asTstr() == *(other.asTstr());
367*09635541SAndroid Build Coastguard Worker }
368*09635541SAndroid Build Coastguard Worker if (asViewTstr() != nullptr && other.asViewTstr() != nullptr) {
369*09635541SAndroid Build Coastguard Worker return *asViewTstr() == *(other.asViewTstr());
370*09635541SAndroid Build Coastguard Worker }
371*09635541SAndroid Build Coastguard Worker // Same corner case as Bstr
372*09635541SAndroid Build Coastguard Worker return false;
373*09635541SAndroid Build Coastguard Worker case ARRAY:
374*09635541SAndroid Build Coastguard Worker return *asArray() == *(other.asArray());
375*09635541SAndroid Build Coastguard Worker case MAP:
376*09635541SAndroid Build Coastguard Worker return *asMap() == *(other.asMap());
377*09635541SAndroid Build Coastguard Worker case SIMPLE:
378*09635541SAndroid Build Coastguard Worker return *asSimple() == *(other.asSimple());
379*09635541SAndroid Build Coastguard Worker case SEMANTIC:
380*09635541SAndroid Build Coastguard Worker return *asSemanticTag() == *(other.asSemanticTag());
381*09635541SAndroid Build Coastguard Worker default:
382*09635541SAndroid Build Coastguard Worker CHECK(false); // Impossible to get here.
383*09635541SAndroid Build Coastguard Worker return false;
384*09635541SAndroid Build Coastguard Worker }
385*09635541SAndroid Build Coastguard Worker }
386*09635541SAndroid Build Coastguard Worker
Nint(int64_t v)387*09635541SAndroid Build Coastguard Worker Nint::Nint(int64_t v) : mValue(v) {
388*09635541SAndroid Build Coastguard Worker CHECK(v < 0);
389*09635541SAndroid Build Coastguard Worker }
390*09635541SAndroid Build Coastguard Worker
operator ==(const Simple & other) const391*09635541SAndroid Build Coastguard Worker bool Simple::operator==(const Simple& other) const& {
392*09635541SAndroid Build Coastguard Worker if (simpleType() != other.simpleType()) return false;
393*09635541SAndroid Build Coastguard Worker
394*09635541SAndroid Build Coastguard Worker switch (simpleType()) {
395*09635541SAndroid Build Coastguard Worker case BOOLEAN:
396*09635541SAndroid Build Coastguard Worker return *asBool() == *(other.asBool());
397*09635541SAndroid Build Coastguard Worker case NULL_T:
398*09635541SAndroid Build Coastguard Worker return true;
399*09635541SAndroid Build Coastguard Worker #if defined(__STDC_IEC_559__) || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
400*09635541SAndroid Build Coastguard Worker case FLOAT:
401*09635541SAndroid Build Coastguard Worker return *asFloat() == *(other.asFloat());
402*09635541SAndroid Build Coastguard Worker #endif // __STDC_IEC_559__ || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
403*09635541SAndroid Build Coastguard Worker #if defined(__STDC_IEC_559__) || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
404*09635541SAndroid Build Coastguard Worker case DOUBLE:
405*09635541SAndroid Build Coastguard Worker return *asDouble() == *(other.asDouble());
406*09635541SAndroid Build Coastguard Worker #endif // __STDC_IEC_559__ || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
407*09635541SAndroid Build Coastguard Worker default:
408*09635541SAndroid Build Coastguard Worker CHECK(false); // Impossible to get here.
409*09635541SAndroid Build Coastguard Worker return false;
410*09635541SAndroid Build Coastguard Worker }
411*09635541SAndroid Build Coastguard Worker }
412*09635541SAndroid Build Coastguard Worker
encode(uint8_t * pos,const uint8_t * end) const413*09635541SAndroid Build Coastguard Worker uint8_t* Bstr::encode(uint8_t* pos, const uint8_t* end) const {
414*09635541SAndroid Build Coastguard Worker pos = encodeHeader(mValue.size(), pos, end);
415*09635541SAndroid Build Coastguard Worker if (!pos || end - pos < static_cast<ptrdiff_t>(mValue.size())) return nullptr;
416*09635541SAndroid Build Coastguard Worker return std::copy(mValue.begin(), mValue.end(), pos);
417*09635541SAndroid Build Coastguard Worker }
418*09635541SAndroid Build Coastguard Worker
encodeValue(EncodeCallback encodeCallback) const419*09635541SAndroid Build Coastguard Worker void Bstr::encodeValue(EncodeCallback encodeCallback) const {
420*09635541SAndroid Build Coastguard Worker for (auto c : mValue) {
421*09635541SAndroid Build Coastguard Worker encodeCallback(c);
422*09635541SAndroid Build Coastguard Worker }
423*09635541SAndroid Build Coastguard Worker }
424*09635541SAndroid Build Coastguard Worker
encode(uint8_t * pos,const uint8_t * end) const425*09635541SAndroid Build Coastguard Worker uint8_t* ViewBstr::encode(uint8_t* pos, const uint8_t* end) const {
426*09635541SAndroid Build Coastguard Worker pos = encodeHeader(mView.size(), pos, end);
427*09635541SAndroid Build Coastguard Worker if (!pos || end - pos < static_cast<ptrdiff_t>(mView.size())) return nullptr;
428*09635541SAndroid Build Coastguard Worker return std::copy(mView.begin(), mView.end(), pos);
429*09635541SAndroid Build Coastguard Worker }
430*09635541SAndroid Build Coastguard Worker
encodeValue(EncodeCallback encodeCallback) const431*09635541SAndroid Build Coastguard Worker void ViewBstr::encodeValue(EncodeCallback encodeCallback) const {
432*09635541SAndroid Build Coastguard Worker for (auto c : mView) {
433*09635541SAndroid Build Coastguard Worker encodeCallback(static_cast<uint8_t>(c));
434*09635541SAndroid Build Coastguard Worker }
435*09635541SAndroid Build Coastguard Worker }
436*09635541SAndroid Build Coastguard Worker
encode(uint8_t * pos,const uint8_t * end) const437*09635541SAndroid Build Coastguard Worker uint8_t* Tstr::encode(uint8_t* pos, const uint8_t* end) const {
438*09635541SAndroid Build Coastguard Worker pos = encodeHeader(mValue.size(), pos, end);
439*09635541SAndroid Build Coastguard Worker if (!pos || end - pos < static_cast<ptrdiff_t>(mValue.size())) return nullptr;
440*09635541SAndroid Build Coastguard Worker return std::copy(mValue.begin(), mValue.end(), pos);
441*09635541SAndroid Build Coastguard Worker }
442*09635541SAndroid Build Coastguard Worker
encodeValue(EncodeCallback encodeCallback) const443*09635541SAndroid Build Coastguard Worker void Tstr::encodeValue(EncodeCallback encodeCallback) const {
444*09635541SAndroid Build Coastguard Worker for (auto c : mValue) {
445*09635541SAndroid Build Coastguard Worker encodeCallback(static_cast<uint8_t>(c));
446*09635541SAndroid Build Coastguard Worker }
447*09635541SAndroid Build Coastguard Worker }
448*09635541SAndroid Build Coastguard Worker
encode(uint8_t * pos,const uint8_t * end) const449*09635541SAndroid Build Coastguard Worker uint8_t* ViewTstr::encode(uint8_t* pos, const uint8_t* end) const {
450*09635541SAndroid Build Coastguard Worker pos = encodeHeader(mView.size(), pos, end);
451*09635541SAndroid Build Coastguard Worker if (!pos || end - pos < static_cast<ptrdiff_t>(mView.size())) return nullptr;
452*09635541SAndroid Build Coastguard Worker return std::copy(mView.begin(), mView.end(), pos);
453*09635541SAndroid Build Coastguard Worker }
454*09635541SAndroid Build Coastguard Worker
encodeValue(EncodeCallback encodeCallback) const455*09635541SAndroid Build Coastguard Worker void ViewTstr::encodeValue(EncodeCallback encodeCallback) const {
456*09635541SAndroid Build Coastguard Worker for (auto c : mView) {
457*09635541SAndroid Build Coastguard Worker encodeCallback(static_cast<uint8_t>(c));
458*09635541SAndroid Build Coastguard Worker }
459*09635541SAndroid Build Coastguard Worker }
460*09635541SAndroid Build Coastguard Worker
operator ==(const Array & other) const461*09635541SAndroid Build Coastguard Worker bool Array::operator==(const Array& other) const& {
462*09635541SAndroid Build Coastguard Worker return size() == other.size()
463*09635541SAndroid Build Coastguard Worker // Can't use vector::operator== because the contents are pointers. std::equal lets us
464*09635541SAndroid Build Coastguard Worker // provide a predicate that does the dereferencing.
465*09635541SAndroid Build Coastguard Worker && std::equal(mEntries.begin(), mEntries.end(), other.mEntries.begin(),
466*09635541SAndroid Build Coastguard Worker [](auto& a, auto& b) -> bool { return *a == *b; });
467*09635541SAndroid Build Coastguard Worker }
468*09635541SAndroid Build Coastguard Worker
encode(uint8_t * pos,const uint8_t * end) const469*09635541SAndroid Build Coastguard Worker uint8_t* Array::encode(uint8_t* pos, const uint8_t* end) const {
470*09635541SAndroid Build Coastguard Worker pos = encodeHeader(size(), pos, end);
471*09635541SAndroid Build Coastguard Worker if (!pos) return nullptr;
472*09635541SAndroid Build Coastguard Worker for (auto& entry : mEntries) {
473*09635541SAndroid Build Coastguard Worker pos = entry->encode(pos, end);
474*09635541SAndroid Build Coastguard Worker if (!pos) return nullptr;
475*09635541SAndroid Build Coastguard Worker }
476*09635541SAndroid Build Coastguard Worker return pos;
477*09635541SAndroid Build Coastguard Worker }
478*09635541SAndroid Build Coastguard Worker
encode(EncodeCallback encodeCallback) const479*09635541SAndroid Build Coastguard Worker void Array::encode(EncodeCallback encodeCallback) const {
480*09635541SAndroid Build Coastguard Worker encodeHeader(size(), encodeCallback);
481*09635541SAndroid Build Coastguard Worker for (auto& entry : mEntries) {
482*09635541SAndroid Build Coastguard Worker entry->encode(encodeCallback);
483*09635541SAndroid Build Coastguard Worker }
484*09635541SAndroid Build Coastguard Worker }
485*09635541SAndroid Build Coastguard Worker
clone() const486*09635541SAndroid Build Coastguard Worker std::unique_ptr<Item> Array::clone() const {
487*09635541SAndroid Build Coastguard Worker auto res = std::make_unique<Array>();
488*09635541SAndroid Build Coastguard Worker for (size_t i = 0; i < mEntries.size(); i++) {
489*09635541SAndroid Build Coastguard Worker res->add(mEntries[i]->clone());
490*09635541SAndroid Build Coastguard Worker }
491*09635541SAndroid Build Coastguard Worker return res;
492*09635541SAndroid Build Coastguard Worker }
493*09635541SAndroid Build Coastguard Worker
operator ==(const Map & other) const494*09635541SAndroid Build Coastguard Worker bool Map::operator==(const Map& other) const& {
495*09635541SAndroid Build Coastguard Worker return size() == other.size()
496*09635541SAndroid Build Coastguard Worker // Can't use vector::operator== because the contents are pairs of pointers. std::equal
497*09635541SAndroid Build Coastguard Worker // lets us provide a predicate that does the dereferencing.
498*09635541SAndroid Build Coastguard Worker && std::equal(begin(), end(), other.begin(), [](auto& a, auto& b) {
499*09635541SAndroid Build Coastguard Worker return *a.first == *b.first && *a.second == *b.second;
500*09635541SAndroid Build Coastguard Worker });
501*09635541SAndroid Build Coastguard Worker }
502*09635541SAndroid Build Coastguard Worker
encode(uint8_t * pos,const uint8_t * end) const503*09635541SAndroid Build Coastguard Worker uint8_t* Map::encode(uint8_t* pos, const uint8_t* end) const {
504*09635541SAndroid Build Coastguard Worker pos = encodeHeader(size(), pos, end);
505*09635541SAndroid Build Coastguard Worker if (!pos) return nullptr;
506*09635541SAndroid Build Coastguard Worker for (auto& entry : mEntries) {
507*09635541SAndroid Build Coastguard Worker pos = entry.first->encode(pos, end);
508*09635541SAndroid Build Coastguard Worker if (!pos) return nullptr;
509*09635541SAndroid Build Coastguard Worker pos = entry.second->encode(pos, end);
510*09635541SAndroid Build Coastguard Worker if (!pos) return nullptr;
511*09635541SAndroid Build Coastguard Worker }
512*09635541SAndroid Build Coastguard Worker return pos;
513*09635541SAndroid Build Coastguard Worker }
514*09635541SAndroid Build Coastguard Worker
encode(EncodeCallback encodeCallback) const515*09635541SAndroid Build Coastguard Worker void Map::encode(EncodeCallback encodeCallback) const {
516*09635541SAndroid Build Coastguard Worker encodeHeader(size(), encodeCallback);
517*09635541SAndroid Build Coastguard Worker for (auto& entry : mEntries) {
518*09635541SAndroid Build Coastguard Worker entry.first->encode(encodeCallback);
519*09635541SAndroid Build Coastguard Worker entry.second->encode(encodeCallback);
520*09635541SAndroid Build Coastguard Worker }
521*09635541SAndroid Build Coastguard Worker }
522*09635541SAndroid Build Coastguard Worker
keyLess(const Item * a,const Item * b)523*09635541SAndroid Build Coastguard Worker bool Map::keyLess(const Item* a, const Item* b) {
524*09635541SAndroid Build Coastguard Worker // CBOR map canonicalization rules are:
525*09635541SAndroid Build Coastguard Worker
526*09635541SAndroid Build Coastguard Worker // 1. If two keys have different lengths, the shorter one sorts earlier.
527*09635541SAndroid Build Coastguard Worker if (a->encodedSize() < b->encodedSize()) return true;
528*09635541SAndroid Build Coastguard Worker if (a->encodedSize() > b->encodedSize()) return false;
529*09635541SAndroid Build Coastguard Worker
530*09635541SAndroid Build Coastguard Worker // 2. If two keys have the same length, the one with the lower value in (byte-wise) lexical
531*09635541SAndroid Build Coastguard Worker // order sorts earlier. This requires encoding both items.
532*09635541SAndroid Build Coastguard Worker auto encodedA = a->encode();
533*09635541SAndroid Build Coastguard Worker auto encodedB = b->encode();
534*09635541SAndroid Build Coastguard Worker
535*09635541SAndroid Build Coastguard Worker return std::lexicographical_compare(encodedA.begin(), encodedA.end(), //
536*09635541SAndroid Build Coastguard Worker encodedB.begin(), encodedB.end());
537*09635541SAndroid Build Coastguard Worker }
538*09635541SAndroid Build Coastguard Worker
recursivelyCanonicalize(std::unique_ptr<Item> & item)539*09635541SAndroid Build Coastguard Worker void recursivelyCanonicalize(std::unique_ptr<Item>& item) {
540*09635541SAndroid Build Coastguard Worker switch (item->type()) {
541*09635541SAndroid Build Coastguard Worker case UINT:
542*09635541SAndroid Build Coastguard Worker case NINT:
543*09635541SAndroid Build Coastguard Worker case BSTR:
544*09635541SAndroid Build Coastguard Worker case TSTR:
545*09635541SAndroid Build Coastguard Worker case SIMPLE:
546*09635541SAndroid Build Coastguard Worker return;
547*09635541SAndroid Build Coastguard Worker
548*09635541SAndroid Build Coastguard Worker case ARRAY:
549*09635541SAndroid Build Coastguard Worker std::for_each(item->asArray()->begin(), item->asArray()->end(),
550*09635541SAndroid Build Coastguard Worker recursivelyCanonicalize);
551*09635541SAndroid Build Coastguard Worker return;
552*09635541SAndroid Build Coastguard Worker
553*09635541SAndroid Build Coastguard Worker case MAP:
554*09635541SAndroid Build Coastguard Worker item->asMap()->canonicalize(true /* recurse */);
555*09635541SAndroid Build Coastguard Worker return;
556*09635541SAndroid Build Coastguard Worker
557*09635541SAndroid Build Coastguard Worker case SEMANTIC:
558*09635541SAndroid Build Coastguard Worker // This can't happen. SemanticTags delegate their type() method to the contained Item's
559*09635541SAndroid Build Coastguard Worker // type.
560*09635541SAndroid Build Coastguard Worker assert(false);
561*09635541SAndroid Build Coastguard Worker return;
562*09635541SAndroid Build Coastguard Worker }
563*09635541SAndroid Build Coastguard Worker }
564*09635541SAndroid Build Coastguard Worker
canonicalize(bool recurse)565*09635541SAndroid Build Coastguard Worker Map& Map::canonicalize(bool recurse) & {
566*09635541SAndroid Build Coastguard Worker if (recurse) {
567*09635541SAndroid Build Coastguard Worker for (auto& entry : mEntries) {
568*09635541SAndroid Build Coastguard Worker recursivelyCanonicalize(entry.first);
569*09635541SAndroid Build Coastguard Worker recursivelyCanonicalize(entry.second);
570*09635541SAndroid Build Coastguard Worker }
571*09635541SAndroid Build Coastguard Worker }
572*09635541SAndroid Build Coastguard Worker
573*09635541SAndroid Build Coastguard Worker if (size() < 2 || mCanonicalized) {
574*09635541SAndroid Build Coastguard Worker // Trivially or already canonical; do nothing.
575*09635541SAndroid Build Coastguard Worker return *this;
576*09635541SAndroid Build Coastguard Worker }
577*09635541SAndroid Build Coastguard Worker
578*09635541SAndroid Build Coastguard Worker std::sort(begin(), end(),
579*09635541SAndroid Build Coastguard Worker [](auto& a, auto& b) { return keyLess(a.first.get(), b.first.get()); });
580*09635541SAndroid Build Coastguard Worker mCanonicalized = true;
581*09635541SAndroid Build Coastguard Worker return *this;
582*09635541SAndroid Build Coastguard Worker }
583*09635541SAndroid Build Coastguard Worker
clone() const584*09635541SAndroid Build Coastguard Worker std::unique_ptr<Item> Map::clone() const {
585*09635541SAndroid Build Coastguard Worker auto res = std::make_unique<Map>();
586*09635541SAndroid Build Coastguard Worker for (auto& [key, value] : *this) {
587*09635541SAndroid Build Coastguard Worker res->add(key->clone(), value->clone());
588*09635541SAndroid Build Coastguard Worker }
589*09635541SAndroid Build Coastguard Worker res->mCanonicalized = mCanonicalized;
590*09635541SAndroid Build Coastguard Worker return res;
591*09635541SAndroid Build Coastguard Worker }
592*09635541SAndroid Build Coastguard Worker
clone() const593*09635541SAndroid Build Coastguard Worker std::unique_ptr<Item> SemanticTag::clone() const {
594*09635541SAndroid Build Coastguard Worker return std::make_unique<SemanticTag>(mValue, mTaggedItem->clone());
595*09635541SAndroid Build Coastguard Worker }
596*09635541SAndroid Build Coastguard Worker
encode(uint8_t * pos,const uint8_t * end) const597*09635541SAndroid Build Coastguard Worker uint8_t* SemanticTag::encode(uint8_t* pos, const uint8_t* end) const {
598*09635541SAndroid Build Coastguard Worker // Can't use the encodeHeader() method that calls type() to get the major type, since that will
599*09635541SAndroid Build Coastguard Worker // return the tagged Item's type.
600*09635541SAndroid Build Coastguard Worker pos = ::cppbor::encodeHeader(kMajorType, mValue, pos, end);
601*09635541SAndroid Build Coastguard Worker if (!pos) return nullptr;
602*09635541SAndroid Build Coastguard Worker return mTaggedItem->encode(pos, end);
603*09635541SAndroid Build Coastguard Worker }
604*09635541SAndroid Build Coastguard Worker
encode(EncodeCallback encodeCallback) const605*09635541SAndroid Build Coastguard Worker void SemanticTag::encode(EncodeCallback encodeCallback) const {
606*09635541SAndroid Build Coastguard Worker // Can't use the encodeHeader() method that calls type() to get the major type, since that will
607*09635541SAndroid Build Coastguard Worker // return the tagged Item's type.
608*09635541SAndroid Build Coastguard Worker ::cppbor::encodeHeader(kMajorType, mValue, encodeCallback);
609*09635541SAndroid Build Coastguard Worker mTaggedItem->encode(encodeCallback);
610*09635541SAndroid Build Coastguard Worker }
611*09635541SAndroid Build Coastguard Worker
semanticTagCount() const612*09635541SAndroid Build Coastguard Worker size_t SemanticTag::semanticTagCount() const {
613*09635541SAndroid Build Coastguard Worker size_t levelCount = 1; // Count this level.
614*09635541SAndroid Build Coastguard Worker const SemanticTag* cur = this;
615*09635541SAndroid Build Coastguard Worker while (cur->mTaggedItem && (cur = cur->mTaggedItem->asSemanticTag()) != nullptr) ++levelCount;
616*09635541SAndroid Build Coastguard Worker return levelCount;
617*09635541SAndroid Build Coastguard Worker }
618*09635541SAndroid Build Coastguard Worker
semanticTag(size_t nesting) const619*09635541SAndroid Build Coastguard Worker uint64_t SemanticTag::semanticTag(size_t nesting) const {
620*09635541SAndroid Build Coastguard Worker // Getting the value of a specific nested tag is a bit tricky, because we start with the outer
621*09635541SAndroid Build Coastguard Worker // tag and don't know how many are inside. We count the number of nesting levels to find out
622*09635541SAndroid Build Coastguard Worker // how many there are in total, then to get the one we want we have to walk down levelCount -
623*09635541SAndroid Build Coastguard Worker // nesting steps.
624*09635541SAndroid Build Coastguard Worker size_t levelCount = semanticTagCount();
625*09635541SAndroid Build Coastguard Worker if (nesting >= levelCount) return 0;
626*09635541SAndroid Build Coastguard Worker
627*09635541SAndroid Build Coastguard Worker levelCount -= nesting;
628*09635541SAndroid Build Coastguard Worker const SemanticTag* cur = this;
629*09635541SAndroid Build Coastguard Worker while (--levelCount > 0) cur = cur->mTaggedItem->asSemanticTag();
630*09635541SAndroid Build Coastguard Worker
631*09635541SAndroid Build Coastguard Worker return cur->mValue;
632*09635541SAndroid Build Coastguard Worker }
633*09635541SAndroid Build Coastguard Worker
prettyPrint(const Item * item,size_t maxBStrSize,const vector<string> & mapKeysToNotPrint)634*09635541SAndroid Build Coastguard Worker string prettyPrint(const Item* item, size_t maxBStrSize, const vector<string>& mapKeysToNotPrint) {
635*09635541SAndroid Build Coastguard Worker string out;
636*09635541SAndroid Build Coastguard Worker prettyPrintInternal(item, out, 0, maxBStrSize, mapKeysToNotPrint);
637*09635541SAndroid Build Coastguard Worker return out;
638*09635541SAndroid Build Coastguard Worker }
prettyPrint(const vector<uint8_t> & encodedCbor,size_t maxBStrSize,const vector<string> & mapKeysToNotPrint)639*09635541SAndroid Build Coastguard Worker string prettyPrint(const vector<uint8_t>& encodedCbor, size_t maxBStrSize,
640*09635541SAndroid Build Coastguard Worker const vector<string>& mapKeysToNotPrint) {
641*09635541SAndroid Build Coastguard Worker auto [item, _, message] = parse(encodedCbor);
642*09635541SAndroid Build Coastguard Worker if (item == nullptr) {
643*09635541SAndroid Build Coastguard Worker #ifndef __TRUSTY__
644*09635541SAndroid Build Coastguard Worker LOG(ERROR) << "Data to pretty print is not valid CBOR: " << message;
645*09635541SAndroid Build Coastguard Worker #endif // __TRUSTY__
646*09635541SAndroid Build Coastguard Worker return "";
647*09635541SAndroid Build Coastguard Worker }
648*09635541SAndroid Build Coastguard Worker
649*09635541SAndroid Build Coastguard Worker return prettyPrint(item.get(), maxBStrSize, mapKeysToNotPrint);
650*09635541SAndroid Build Coastguard Worker }
651*09635541SAndroid Build Coastguard Worker
652*09635541SAndroid Build Coastguard Worker } // namespace cppbor
653