xref: /aosp_15_r20/system/libcppbor/src/cppbor_parse.cpp (revision 0963554132e37a14524024fa04dc9e883c7a8221)
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_parse.h"
18*09635541SAndroid Build Coastguard Worker 
19*09635541SAndroid Build Coastguard Worker #include <algorithm>
20*09635541SAndroid Build Coastguard Worker #include <cstdint>
21*09635541SAndroid Build Coastguard Worker #include <cstring>
22*09635541SAndroid Build Coastguard Worker #include <memory>
23*09635541SAndroid Build Coastguard Worker #include <optional>
24*09635541SAndroid Build Coastguard Worker #include <sstream>
25*09635541SAndroid Build Coastguard Worker #include <stack>
26*09635541SAndroid Build Coastguard Worker #include <tuple>
27*09635541SAndroid Build Coastguard Worker #include <type_traits>
28*09635541SAndroid Build Coastguard Worker 
29*09635541SAndroid Build Coastguard Worker #include "cppbor.h"
30*09635541SAndroid Build Coastguard Worker 
31*09635541SAndroid Build Coastguard Worker #ifndef __TRUSTY__
32*09635541SAndroid Build Coastguard Worker #include <android-base/logging.h>
33*09635541SAndroid Build Coastguard Worker #define LOG_TAG "CppBor"
34*09635541SAndroid Build Coastguard Worker #else
35*09635541SAndroid Build Coastguard Worker #define CHECK(x) (void)(x)
36*09635541SAndroid Build Coastguard Worker #endif
37*09635541SAndroid Build Coastguard Worker 
38*09635541SAndroid Build Coastguard Worker namespace cppbor {
39*09635541SAndroid Build Coastguard Worker 
40*09635541SAndroid Build Coastguard Worker namespace {
41*09635541SAndroid Build Coastguard Worker 
42*09635541SAndroid Build Coastguard Worker const unsigned kMaxParseDepth = 1000;
43*09635541SAndroid Build Coastguard Worker const size_t kMaxReserveSize = 8192;
44*09635541SAndroid Build Coastguard Worker 
insufficientLengthString(size_t bytesNeeded,size_t bytesAvail,const std::string & type)45*09635541SAndroid Build Coastguard Worker std::string insufficientLengthString(size_t bytesNeeded, size_t bytesAvail,
46*09635541SAndroid Build Coastguard Worker                                      const std::string& type) {
47*09635541SAndroid Build Coastguard Worker     char buf[1024];
48*09635541SAndroid Build Coastguard Worker     snprintf(buf, sizeof(buf), "Need %zu byte(s) for %s, have %zu.", bytesNeeded, type.c_str(),
49*09635541SAndroid Build Coastguard Worker              bytesAvail);
50*09635541SAndroid Build Coastguard Worker     return std::string(buf);
51*09635541SAndroid Build Coastguard Worker }
52*09635541SAndroid Build Coastguard Worker 
53*09635541SAndroid Build Coastguard Worker template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
parseLength(const uint8_t * pos,const uint8_t * end,ParseClient * parseClient)54*09635541SAndroid Build Coastguard Worker std::tuple<bool, uint64_t, const uint8_t*> parseLength(const uint8_t* pos, const uint8_t* end,
55*09635541SAndroid Build Coastguard Worker                                                        ParseClient* parseClient) {
56*09635541SAndroid Build Coastguard Worker     if (pos + sizeof(T) > end) {
57*09635541SAndroid Build Coastguard Worker         parseClient->error(pos - 1, insufficientLengthString(sizeof(T), end - pos, "length field"));
58*09635541SAndroid Build Coastguard Worker         return {false, 0, pos};
59*09635541SAndroid Build Coastguard Worker     }
60*09635541SAndroid Build Coastguard Worker 
61*09635541SAndroid Build Coastguard Worker     const uint8_t* intEnd = pos + sizeof(T);
62*09635541SAndroid Build Coastguard Worker     T result = 0;
63*09635541SAndroid Build Coastguard Worker     do {
64*09635541SAndroid Build Coastguard Worker         result = static_cast<T>((result << 8) | *pos++);
65*09635541SAndroid Build Coastguard Worker     } while (pos < intEnd);
66*09635541SAndroid Build Coastguard Worker     return {true, result, pos};
67*09635541SAndroid Build Coastguard Worker }
68*09635541SAndroid Build Coastguard Worker 
69*09635541SAndroid Build Coastguard Worker std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
70*09635541SAndroid Build Coastguard Worker                                                           bool emitViews, ParseClient* parseClient,
71*09635541SAndroid Build Coastguard Worker                                                           unsigned depth);
72*09635541SAndroid Build Coastguard Worker 
handleUint(uint64_t value,const uint8_t * hdrBegin,const uint8_t * hdrEnd,ParseClient * parseClient)73*09635541SAndroid Build Coastguard Worker std::tuple<const uint8_t*, ParseClient*> handleUint(uint64_t value, const uint8_t* hdrBegin,
74*09635541SAndroid Build Coastguard Worker                                                     const uint8_t* hdrEnd,
75*09635541SAndroid Build Coastguard Worker                                                     ParseClient* parseClient) {
76*09635541SAndroid Build Coastguard Worker     std::unique_ptr<Item> item = std::make_unique<Uint>(value);
77*09635541SAndroid Build Coastguard Worker     return {hdrEnd,
78*09635541SAndroid Build Coastguard Worker             parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
79*09635541SAndroid Build Coastguard Worker }
80*09635541SAndroid Build Coastguard Worker 
handleNint(uint64_t value,const uint8_t * hdrBegin,const uint8_t * hdrEnd,ParseClient * parseClient)81*09635541SAndroid Build Coastguard Worker std::tuple<const uint8_t*, ParseClient*> handleNint(uint64_t value, const uint8_t* hdrBegin,
82*09635541SAndroid Build Coastguard Worker                                                     const uint8_t* hdrEnd,
83*09635541SAndroid Build Coastguard Worker                                                     ParseClient* parseClient) {
84*09635541SAndroid Build Coastguard Worker     if (value > std::numeric_limits<int64_t>::max()) {
85*09635541SAndroid Build Coastguard Worker         parseClient->error(hdrBegin, "NINT values that don't fit in int64_t are not supported.");
86*09635541SAndroid Build Coastguard Worker         return {hdrBegin, nullptr /* end parsing */};
87*09635541SAndroid Build Coastguard Worker     }
88*09635541SAndroid Build Coastguard Worker     std::unique_ptr<Item> item = std::make_unique<Nint>(-1 - static_cast<int64_t>(value));
89*09635541SAndroid Build Coastguard Worker     return {hdrEnd,
90*09635541SAndroid Build Coastguard Worker             parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
91*09635541SAndroid Build Coastguard Worker }
92*09635541SAndroid Build Coastguard Worker 
handleBool(uint64_t value,const uint8_t * hdrBegin,const uint8_t * hdrEnd,ParseClient * parseClient)93*09635541SAndroid Build Coastguard Worker std::tuple<const uint8_t*, ParseClient*> handleBool(uint64_t value, const uint8_t* hdrBegin,
94*09635541SAndroid Build Coastguard Worker                                                     const uint8_t* hdrEnd,
95*09635541SAndroid Build Coastguard Worker                                                     ParseClient* parseClient) {
96*09635541SAndroid Build Coastguard Worker     std::unique_ptr<Item> item = std::make_unique<Bool>(value == TRUE);
97*09635541SAndroid Build Coastguard Worker     return {hdrEnd,
98*09635541SAndroid Build Coastguard Worker             parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
99*09635541SAndroid Build Coastguard Worker }
100*09635541SAndroid Build Coastguard Worker 
handleNull(const uint8_t * hdrBegin,const uint8_t * hdrEnd,ParseClient * parseClient)101*09635541SAndroid Build Coastguard Worker std::tuple<const uint8_t*, ParseClient*> handleNull(const uint8_t* hdrBegin, const uint8_t* hdrEnd,
102*09635541SAndroid Build Coastguard Worker                                                     ParseClient* parseClient) {
103*09635541SAndroid Build Coastguard Worker     std::unique_ptr<Item> item = std::make_unique<Null>();
104*09635541SAndroid Build Coastguard Worker     return {hdrEnd,
105*09635541SAndroid Build Coastguard Worker             parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
106*09635541SAndroid Build Coastguard Worker }
107*09635541SAndroid Build Coastguard Worker 
108*09635541SAndroid Build Coastguard Worker #if defined(__STDC_IEC_559__) || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
handleFloat(uint32_t value,const uint8_t * hdrBegin,const uint8_t * hdrEnd,ParseClient * parseClient)109*09635541SAndroid Build Coastguard Worker std::tuple<const uint8_t*, ParseClient*> handleFloat(uint32_t value, const uint8_t* hdrBegin,
110*09635541SAndroid Build Coastguard Worker                                                      const uint8_t* hdrEnd,
111*09635541SAndroid Build Coastguard Worker                                                      ParseClient* parseClient) {
112*09635541SAndroid Build Coastguard Worker     float f;
113*09635541SAndroid Build Coastguard Worker     std::memcpy(&f, &value, sizeof(float));
114*09635541SAndroid Build Coastguard Worker     std::unique_ptr<Item> item = std::make_unique<Float>(f);
115*09635541SAndroid Build Coastguard Worker     return {hdrEnd,
116*09635541SAndroid Build Coastguard Worker             parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
117*09635541SAndroid Build Coastguard Worker }
118*09635541SAndroid Build Coastguard Worker #endif  // __STDC_IEC_559__ || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
119*09635541SAndroid Build Coastguard Worker 
120*09635541SAndroid Build Coastguard Worker #if defined(__STDC_IEC_559__) || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
handleDouble(uint64_t value,const uint8_t * hdrBegin,const uint8_t * hdrEnd,ParseClient * parseClient)121*09635541SAndroid Build Coastguard Worker std::tuple<const uint8_t*, ParseClient*> handleDouble(uint64_t value, const uint8_t* hdrBegin,
122*09635541SAndroid Build Coastguard Worker                                                       const uint8_t* hdrEnd,
123*09635541SAndroid Build Coastguard Worker                                                       ParseClient* parseClient) {
124*09635541SAndroid Build Coastguard Worker     double d;
125*09635541SAndroid Build Coastguard Worker     std::memcpy(&d, &value, sizeof(double));
126*09635541SAndroid Build Coastguard Worker     std::unique_ptr<Item> item = std::make_unique<Double>(d);
127*09635541SAndroid Build Coastguard Worker     return {hdrEnd,
128*09635541SAndroid Build Coastguard Worker             parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
129*09635541SAndroid Build Coastguard Worker }
130*09635541SAndroid Build Coastguard Worker #endif  // __STDC_IEC_559__ || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
131*09635541SAndroid Build Coastguard Worker 
132*09635541SAndroid Build Coastguard Worker template <typename T>
handleString(uint64_t length,const uint8_t * hdrBegin,const uint8_t * valueBegin,const uint8_t * end,const std::string & errLabel,ParseClient * parseClient)133*09635541SAndroid Build Coastguard Worker std::tuple<const uint8_t*, ParseClient*> handleString(uint64_t length, const uint8_t* hdrBegin,
134*09635541SAndroid Build Coastguard Worker                                                       const uint8_t* valueBegin, const uint8_t* end,
135*09635541SAndroid Build Coastguard Worker                                                       const std::string& errLabel,
136*09635541SAndroid Build Coastguard Worker                                                       ParseClient* parseClient) {
137*09635541SAndroid Build Coastguard Worker     ssize_t signed_length = static_cast<ssize_t>(length);
138*09635541SAndroid Build Coastguard Worker     if (end - valueBegin < signed_length || signed_length < 0) {
139*09635541SAndroid Build Coastguard Worker         parseClient->error(hdrBegin, insufficientLengthString(length, end - valueBegin, errLabel));
140*09635541SAndroid Build Coastguard Worker         return {hdrBegin, nullptr /* end parsing */};
141*09635541SAndroid Build Coastguard Worker     }
142*09635541SAndroid Build Coastguard Worker 
143*09635541SAndroid Build Coastguard Worker     std::unique_ptr<Item> item = std::make_unique<T>(valueBegin, valueBegin + length);
144*09635541SAndroid Build Coastguard Worker     return {valueBegin + length,
145*09635541SAndroid Build Coastguard Worker             parseClient->item(item, hdrBegin, valueBegin, valueBegin + length)};
146*09635541SAndroid Build Coastguard Worker }
147*09635541SAndroid Build Coastguard Worker 
handleIncompleteString(std::unique_ptr<Item> item,const uint8_t * hdrBegin,const uint8_t * valueBegin,const uint8_t * end,const std::string & errLabel,bool emitViews,ParseClient * parseClient,unsigned depth)148*09635541SAndroid Build Coastguard Worker std::tuple<const uint8_t*, ParseClient*> handleIncompleteString(
149*09635541SAndroid Build Coastguard Worker         std::unique_ptr<Item> item, const uint8_t* hdrBegin, const uint8_t* valueBegin,
150*09635541SAndroid Build Coastguard Worker         const uint8_t* end, const std::string& errLabel, bool emitViews, ParseClient* parseClient,
151*09635541SAndroid Build Coastguard Worker         unsigned depth) {
152*09635541SAndroid Build Coastguard Worker     parseClient =
153*09635541SAndroid Build Coastguard Worker             parseClient->item(item, hdrBegin, valueBegin, valueBegin /* don't know the end yet */);
154*09635541SAndroid Build Coastguard Worker     if (!parseClient) return {hdrBegin, nullptr};
155*09635541SAndroid Build Coastguard Worker 
156*09635541SAndroid Build Coastguard Worker     const uint8_t* pos = valueBegin;
157*09635541SAndroid Build Coastguard Worker     while (true) {
158*09635541SAndroid Build Coastguard Worker         if (pos == end) {
159*09635541SAndroid Build Coastguard Worker             parseClient->error(hdrBegin, "Not enough entries for " + errLabel + ".");
160*09635541SAndroid Build Coastguard Worker             return {hdrBegin, nullptr /* end parsing */};
161*09635541SAndroid Build Coastguard Worker         }
162*09635541SAndroid Build Coastguard Worker         if (*pos == 0xFF) {
163*09635541SAndroid Build Coastguard Worker             // We found a stop code.
164*09635541SAndroid Build Coastguard Worker             ++pos;
165*09635541SAndroid Build Coastguard Worker             break;
166*09635541SAndroid Build Coastguard Worker         }
167*09635541SAndroid Build Coastguard Worker         std::tie(pos, parseClient) = parseRecursively(pos, end, emitViews, parseClient, depth + 1);
168*09635541SAndroid Build Coastguard Worker         if (!parseClient) return {hdrBegin, nullptr};
169*09635541SAndroid Build Coastguard Worker     }
170*09635541SAndroid Build Coastguard Worker     if (!parseClient) return {hdrBegin, nullptr};
171*09635541SAndroid Build Coastguard Worker 
172*09635541SAndroid Build Coastguard Worker     return {pos, parseClient->itemEnd(item, hdrBegin, valueBegin, pos)};
173*09635541SAndroid Build Coastguard Worker }
174*09635541SAndroid Build Coastguard Worker 
175*09635541SAndroid Build Coastguard Worker class IncompleteItem {
176*09635541SAndroid Build Coastguard Worker   public:
177*09635541SAndroid Build Coastguard Worker     static IncompleteItem* cast(Item* item);
178*09635541SAndroid Build Coastguard Worker 
~IncompleteItem()179*09635541SAndroid Build Coastguard Worker     virtual ~IncompleteItem() {}
180*09635541SAndroid Build Coastguard Worker     virtual void add(std::unique_ptr<Item> item) = 0;
181*09635541SAndroid Build Coastguard Worker     virtual std::unique_ptr<Item> finalize() && = 0;
182*09635541SAndroid Build Coastguard Worker };
183*09635541SAndroid Build Coastguard Worker 
184*09635541SAndroid Build Coastguard Worker class IncompleteBstr : public Bstr, public IncompleteItem {
185*09635541SAndroid Build Coastguard Worker   public:
IncompleteBstr()186*09635541SAndroid Build Coastguard Worker     explicit IncompleteBstr() {}
187*09635541SAndroid Build Coastguard Worker 
188*09635541SAndroid Build Coastguard Worker     // The finalized version creates a copy which will not have this overridden.
isCompound() const189*09635541SAndroid Build Coastguard Worker     bool isCompound() const override { return true; }
190*09635541SAndroid Build Coastguard Worker 
add(std::unique_ptr<Item> item)191*09635541SAndroid Build Coastguard Worker     void add(std::unique_ptr<Item> item) override {
192*09635541SAndroid Build Coastguard Worker         if (item->type() == BSTR) {
193*09635541SAndroid Build Coastguard Worker             mValue.insert(mValue.end(), item->asBstr()->moveValue().begin(),
194*09635541SAndroid Build Coastguard Worker                           item->asBstr()->moveValue().end());
195*09635541SAndroid Build Coastguard Worker         } else {
196*09635541SAndroid Build Coastguard Worker #ifndef __TRUSTY__
197*09635541SAndroid Build Coastguard Worker             LOG(FATAL) << "Should not happen: Expected BSTR";
198*09635541SAndroid Build Coastguard Worker #endif  // __TRUSTY__
199*09635541SAndroid Build Coastguard Worker         }
200*09635541SAndroid Build Coastguard Worker     }
201*09635541SAndroid Build Coastguard Worker 
finalize()202*09635541SAndroid Build Coastguard Worker     std::unique_ptr<Item> finalize() && override { return std::make_unique<Bstr>(mValue); }
203*09635541SAndroid Build Coastguard Worker };
204*09635541SAndroid Build Coastguard Worker 
205*09635541SAndroid Build Coastguard Worker class IncompleteTstr : public Tstr, public IncompleteItem {
206*09635541SAndroid Build Coastguard Worker   public:
IncompleteTstr()207*09635541SAndroid Build Coastguard Worker     explicit IncompleteTstr() {}
208*09635541SAndroid Build Coastguard Worker 
209*09635541SAndroid Build Coastguard Worker     // The finalized version creates a copy which will not have this overridden.
isCompound() const210*09635541SAndroid Build Coastguard Worker     bool isCompound() const override { return true; }
211*09635541SAndroid Build Coastguard Worker 
add(std::unique_ptr<Item> item)212*09635541SAndroid Build Coastguard Worker     void add(std::unique_ptr<Item> item) override {
213*09635541SAndroid Build Coastguard Worker         if (item->type() == TSTR) {
214*09635541SAndroid Build Coastguard Worker             ss << item->asTstr()->moveValue();
215*09635541SAndroid Build Coastguard Worker         } else {
216*09635541SAndroid Build Coastguard Worker #ifndef __TRUSTY__
217*09635541SAndroid Build Coastguard Worker             LOG(FATAL) << "Should not happen: Expected TSTR";
218*09635541SAndroid Build Coastguard Worker #endif  // __TRUSTY__
219*09635541SAndroid Build Coastguard Worker         }
220*09635541SAndroid Build Coastguard Worker     }
221*09635541SAndroid Build Coastguard Worker 
finalize()222*09635541SAndroid Build Coastguard Worker     std::unique_ptr<Item> finalize() && override { return std::make_unique<Tstr>(ss.str()); }
223*09635541SAndroid Build Coastguard Worker 
224*09635541SAndroid Build Coastguard Worker   private:
225*09635541SAndroid Build Coastguard Worker     std::stringstream ss;
226*09635541SAndroid Build Coastguard Worker };
227*09635541SAndroid Build Coastguard Worker 
228*09635541SAndroid Build Coastguard Worker class IncompleteArray : public Array, public IncompleteItem {
229*09635541SAndroid Build Coastguard Worker   public:
IncompleteArray(std::optional<size_t> size)230*09635541SAndroid Build Coastguard Worker     explicit IncompleteArray(std::optional<size_t> size) : mSize(size) {}
231*09635541SAndroid Build Coastguard Worker 
232*09635541SAndroid Build Coastguard Worker     // If the "complete" size is known, return it, otherwise return the current size.
size() const233*09635541SAndroid Build Coastguard Worker     size_t size() const override { return mSize.value_or(Array::size()); }
234*09635541SAndroid Build Coastguard Worker 
add(std::unique_ptr<Item> item)235*09635541SAndroid Build Coastguard Worker     void add(std::unique_ptr<Item> item) override {
236*09635541SAndroid Build Coastguard Worker         if (mSize) mEntries.reserve(std::min(mSize.value(), kMaxReserveSize));
237*09635541SAndroid Build Coastguard Worker         mEntries.push_back(std::move(item));
238*09635541SAndroid Build Coastguard Worker     }
239*09635541SAndroid Build Coastguard Worker 
finalize()240*09635541SAndroid Build Coastguard Worker     virtual std::unique_ptr<Item> finalize() && override {
241*09635541SAndroid Build Coastguard Worker         // Use Array explicitly so the compiler picks the correct ctor overload
242*09635541SAndroid Build Coastguard Worker         Array* thisArray = this;
243*09635541SAndroid Build Coastguard Worker         return std::make_unique<Array>(std::move(*thisArray));
244*09635541SAndroid Build Coastguard Worker     }
245*09635541SAndroid Build Coastguard Worker 
246*09635541SAndroid Build Coastguard Worker   private:
247*09635541SAndroid Build Coastguard Worker     std::optional<size_t> mSize;
248*09635541SAndroid Build Coastguard Worker };
249*09635541SAndroid Build Coastguard Worker 
250*09635541SAndroid Build Coastguard Worker class IncompleteMap : public Map, public IncompleteItem {
251*09635541SAndroid Build Coastguard Worker   public:
IncompleteMap(std::optional<size_t> size)252*09635541SAndroid Build Coastguard Worker     explicit IncompleteMap(std::optional<size_t> size) : mSize(size) {}
253*09635541SAndroid Build Coastguard Worker 
254*09635541SAndroid Build Coastguard Worker     // If the "complete" size is known, return it, otherwise return the current size.
size() const255*09635541SAndroid Build Coastguard Worker     size_t size() const override { return mSize.value_or(Map::size()); }
256*09635541SAndroid Build Coastguard Worker 
add(std::unique_ptr<Item> item)257*09635541SAndroid Build Coastguard Worker     void add(std::unique_ptr<Item> item) override {
258*09635541SAndroid Build Coastguard Worker         if (mKeyHeldForAdding) {
259*09635541SAndroid Build Coastguard Worker             if (mSize) mEntries.reserve(std::min(mSize.value(), kMaxReserveSize));
260*09635541SAndroid Build Coastguard Worker             mEntries.push_back({std::move(mKeyHeldForAdding), std::move(item)});
261*09635541SAndroid Build Coastguard Worker         } else {
262*09635541SAndroid Build Coastguard Worker             mKeyHeldForAdding = std::move(item);
263*09635541SAndroid Build Coastguard Worker         }
264*09635541SAndroid Build Coastguard Worker     }
265*09635541SAndroid Build Coastguard Worker 
finalize()266*09635541SAndroid Build Coastguard Worker     virtual std::unique_ptr<Item> finalize() && override {
267*09635541SAndroid Build Coastguard Worker         return std::make_unique<Map>(std::move(*this));
268*09635541SAndroid Build Coastguard Worker     }
269*09635541SAndroid Build Coastguard Worker 
270*09635541SAndroid Build Coastguard Worker   private:
271*09635541SAndroid Build Coastguard Worker     std::unique_ptr<Item> mKeyHeldForAdding;
272*09635541SAndroid Build Coastguard Worker     std::optional<size_t> mSize;
273*09635541SAndroid Build Coastguard Worker };
274*09635541SAndroid Build Coastguard Worker 
275*09635541SAndroid Build Coastguard Worker class IncompleteSemanticTag : public SemanticTag, public IncompleteItem {
276*09635541SAndroid Build Coastguard Worker   public:
IncompleteSemanticTag(uint64_t value)277*09635541SAndroid Build Coastguard Worker     explicit IncompleteSemanticTag(uint64_t value) : SemanticTag(value) {}
278*09635541SAndroid Build Coastguard Worker 
279*09635541SAndroid Build Coastguard Worker     // We return the "complete" size, rather than the actual size.
size() const280*09635541SAndroid Build Coastguard Worker     size_t size() const override { return 1; }
281*09635541SAndroid Build Coastguard Worker 
add(std::unique_ptr<Item> item)282*09635541SAndroid Build Coastguard Worker     void add(std::unique_ptr<Item> item) override { mTaggedItem = std::move(item); }
283*09635541SAndroid Build Coastguard Worker 
finalize()284*09635541SAndroid Build Coastguard Worker     virtual std::unique_ptr<Item> finalize() && override {
285*09635541SAndroid Build Coastguard Worker         return std::make_unique<SemanticTag>(std::move(*this));
286*09635541SAndroid Build Coastguard Worker     }
287*09635541SAndroid Build Coastguard Worker };
288*09635541SAndroid Build Coastguard Worker 
cast(Item * item)289*09635541SAndroid Build Coastguard Worker IncompleteItem* IncompleteItem::cast(Item* item) {
290*09635541SAndroid Build Coastguard Worker     CHECK(item->isCompound());
291*09635541SAndroid Build Coastguard Worker     // Semantic tag must be check first, because SemanticTag::type returns the wrapped item's type.
292*09635541SAndroid Build Coastguard Worker     if (item->asSemanticTag()) {
293*09635541SAndroid Build Coastguard Worker #if __has_feature(cxx_rtti)
294*09635541SAndroid Build Coastguard Worker         CHECK(dynamic_cast<IncompleteSemanticTag*>(item));
295*09635541SAndroid Build Coastguard Worker #endif
296*09635541SAndroid Build Coastguard Worker         return static_cast<IncompleteSemanticTag*>(item);
297*09635541SAndroid Build Coastguard Worker     } else if (item->type() == ARRAY) {
298*09635541SAndroid Build Coastguard Worker #if __has_feature(cxx_rtti)
299*09635541SAndroid Build Coastguard Worker         CHECK(dynamic_cast<IncompleteArray*>(item));
300*09635541SAndroid Build Coastguard Worker #endif
301*09635541SAndroid Build Coastguard Worker         return static_cast<IncompleteArray*>(item);
302*09635541SAndroid Build Coastguard Worker     } else if (item->type() == MAP) {
303*09635541SAndroid Build Coastguard Worker #if __has_feature(cxx_rtti)
304*09635541SAndroid Build Coastguard Worker         CHECK(dynamic_cast<IncompleteMap*>(item));
305*09635541SAndroid Build Coastguard Worker #endif
306*09635541SAndroid Build Coastguard Worker         return static_cast<IncompleteMap*>(item);
307*09635541SAndroid Build Coastguard Worker     } else if (item->type() == BSTR) {
308*09635541SAndroid Build Coastguard Worker #if __has_feature(cxx_rtti)
309*09635541SAndroid Build Coastguard Worker         CHECK(dynamic_cast<IncompleteBstr*>(item));
310*09635541SAndroid Build Coastguard Worker #endif
311*09635541SAndroid Build Coastguard Worker         return static_cast<IncompleteBstr*>(item);
312*09635541SAndroid Build Coastguard Worker     } else if (item->type() == TSTR) {
313*09635541SAndroid Build Coastguard Worker #if __has_feature(cxx_rtti)
314*09635541SAndroid Build Coastguard Worker         CHECK(dynamic_cast<IncompleteTstr*>(item));
315*09635541SAndroid Build Coastguard Worker #endif
316*09635541SAndroid Build Coastguard Worker         return static_cast<IncompleteTstr*>(item);
317*09635541SAndroid Build Coastguard Worker     } else {
318*09635541SAndroid Build Coastguard Worker         CHECK(false);  // Impossible to get here.
319*09635541SAndroid Build Coastguard Worker     }
320*09635541SAndroid Build Coastguard Worker     return nullptr;
321*09635541SAndroid Build Coastguard Worker }
322*09635541SAndroid Build Coastguard Worker 
handleEntries(std::optional<size_t> entryCount,const uint8_t * hdrBegin,const uint8_t * pos,const uint8_t * end,const std::string & typeName,bool emitViews,ParseClient * parseClient,unsigned depth)323*09635541SAndroid Build Coastguard Worker std::tuple<const uint8_t*, ParseClient*> handleEntries(std::optional<size_t> entryCount,
324*09635541SAndroid Build Coastguard Worker                                                        const uint8_t* hdrBegin, const uint8_t* pos,
325*09635541SAndroid Build Coastguard Worker                                                        const uint8_t* end,
326*09635541SAndroid Build Coastguard Worker                                                        const std::string& typeName, bool emitViews,
327*09635541SAndroid Build Coastguard Worker                                                        ParseClient* parseClient, unsigned depth) {
328*09635541SAndroid Build Coastguard Worker     while (entryCount.value_or(1) > 0) {
329*09635541SAndroid Build Coastguard Worker         if (entryCount.has_value()) {
330*09635541SAndroid Build Coastguard Worker             --*entryCount;
331*09635541SAndroid Build Coastguard Worker         }
332*09635541SAndroid Build Coastguard Worker         if (pos == end) {
333*09635541SAndroid Build Coastguard Worker             parseClient->error(hdrBegin, "Not enough entries for " + typeName + ".");
334*09635541SAndroid Build Coastguard Worker             return {hdrBegin, nullptr /* end parsing */};
335*09635541SAndroid Build Coastguard Worker         }
336*09635541SAndroid Build Coastguard Worker         if (!entryCount.has_value() && *pos == 0xFF) {
337*09635541SAndroid Build Coastguard Worker             // We're in an indeterminate-length object and found a stop code.
338*09635541SAndroid Build Coastguard Worker             ++pos;
339*09635541SAndroid Build Coastguard Worker             break;
340*09635541SAndroid Build Coastguard Worker         }
341*09635541SAndroid Build Coastguard Worker         std::tie(pos, parseClient) = parseRecursively(pos, end, emitViews, parseClient, depth + 1);
342*09635541SAndroid Build Coastguard Worker         if (!parseClient) return {hdrBegin, nullptr};
343*09635541SAndroid Build Coastguard Worker     }
344*09635541SAndroid Build Coastguard Worker     return {pos, parseClient};
345*09635541SAndroid Build Coastguard Worker }
346*09635541SAndroid Build Coastguard Worker 
handleCompound(std::unique_ptr<Item> item,std::optional<uint64_t> entryCount,const uint8_t * hdrBegin,const uint8_t * valueBegin,const uint8_t * end,const std::string & typeName,bool emitViews,ParseClient * parseClient,unsigned depth)347*09635541SAndroid Build Coastguard Worker std::tuple<const uint8_t*, ParseClient*> handleCompound(
348*09635541SAndroid Build Coastguard Worker         std::unique_ptr<Item> item, std::optional<uint64_t> entryCount, const uint8_t* hdrBegin,
349*09635541SAndroid Build Coastguard Worker         const uint8_t* valueBegin, const uint8_t* end, const std::string& typeName, bool emitViews,
350*09635541SAndroid Build Coastguard Worker         ParseClient* parseClient, unsigned depth) {
351*09635541SAndroid Build Coastguard Worker     parseClient =
352*09635541SAndroid Build Coastguard Worker             parseClient->item(item, hdrBegin, valueBegin, valueBegin /* don't know the end yet */);
353*09635541SAndroid Build Coastguard Worker     if (!parseClient) return {hdrBegin, nullptr};
354*09635541SAndroid Build Coastguard Worker 
355*09635541SAndroid Build Coastguard Worker     const uint8_t* pos;
356*09635541SAndroid Build Coastguard Worker     std::tie(pos, parseClient) = handleEntries(entryCount, hdrBegin, valueBegin, end, typeName,
357*09635541SAndroid Build Coastguard Worker                                                emitViews, parseClient, depth);
358*09635541SAndroid Build Coastguard Worker     if (!parseClient) return {hdrBegin, nullptr};
359*09635541SAndroid Build Coastguard Worker 
360*09635541SAndroid Build Coastguard Worker     return {pos, parseClient->itemEnd(item, hdrBegin, valueBegin, pos)};
361*09635541SAndroid Build Coastguard Worker }
362*09635541SAndroid Build Coastguard Worker 
parseRecursively(const uint8_t * begin,const uint8_t * end,bool emitViews,ParseClient * parseClient,unsigned depth)363*09635541SAndroid Build Coastguard Worker std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
364*09635541SAndroid Build Coastguard Worker                                                           bool emitViews, ParseClient* parseClient,
365*09635541SAndroid Build Coastguard Worker                                                           unsigned depth) {
366*09635541SAndroid Build Coastguard Worker     if (begin == end) {
367*09635541SAndroid Build Coastguard Worker         parseClient->error(
368*09635541SAndroid Build Coastguard Worker                 begin, "Input buffer is empty. Begin and end cannot point to the same location.");
369*09635541SAndroid Build Coastguard Worker         return {begin, nullptr};
370*09635541SAndroid Build Coastguard Worker     }
371*09635541SAndroid Build Coastguard Worker 
372*09635541SAndroid Build Coastguard Worker     // Limit recursion depth to avoid overflowing the stack.
373*09635541SAndroid Build Coastguard Worker     if (depth > kMaxParseDepth) {
374*09635541SAndroid Build Coastguard Worker         parseClient->error(begin,
375*09635541SAndroid Build Coastguard Worker                            "Max depth reached.  Cannot parse CBOR structures with more "
376*09635541SAndroid Build Coastguard Worker                            "than " +
377*09635541SAndroid Build Coastguard Worker                                    std::to_string(kMaxParseDepth) + " levels.");
378*09635541SAndroid Build Coastguard Worker         return {begin, nullptr};
379*09635541SAndroid Build Coastguard Worker     }
380*09635541SAndroid Build Coastguard Worker 
381*09635541SAndroid Build Coastguard Worker     const uint8_t* pos = begin;
382*09635541SAndroid Build Coastguard Worker 
383*09635541SAndroid Build Coastguard Worker     MajorType type = static_cast<MajorType>(*pos & 0xE0);
384*09635541SAndroid Build Coastguard Worker     uint8_t tagInt = *pos & 0x1F;
385*09635541SAndroid Build Coastguard Worker     ++pos;
386*09635541SAndroid Build Coastguard Worker 
387*09635541SAndroid Build Coastguard Worker     bool success = true;
388*09635541SAndroid Build Coastguard Worker     std::optional<uint64_t> addlData;
389*09635541SAndroid Build Coastguard Worker     if (tagInt < ONE_BYTE_LENGTH) {
390*09635541SAndroid Build Coastguard Worker         addlData = tagInt;
391*09635541SAndroid Build Coastguard Worker     } else if (tagInt > EIGHT_BYTE_LENGTH && tagInt != INDEFINITE_LENGTH) {
392*09635541SAndroid Build Coastguard Worker         parseClient->error(begin, "Reserved additional information value.");
393*09635541SAndroid Build Coastguard Worker         return {begin, nullptr};
394*09635541SAndroid Build Coastguard Worker     } else {
395*09635541SAndroid Build Coastguard Worker         switch (tagInt) {
396*09635541SAndroid Build Coastguard Worker             case ONE_BYTE_LENGTH:
397*09635541SAndroid Build Coastguard Worker                 std::tie(success, addlData, pos) = parseLength<uint8_t>(pos, end, parseClient);
398*09635541SAndroid Build Coastguard Worker                 break;
399*09635541SAndroid Build Coastguard Worker 
400*09635541SAndroid Build Coastguard Worker             case TWO_BYTE_LENGTH:
401*09635541SAndroid Build Coastguard Worker                 std::tie(success, addlData, pos) = parseLength<uint16_t>(pos, end, parseClient);
402*09635541SAndroid Build Coastguard Worker                 break;
403*09635541SAndroid Build Coastguard Worker 
404*09635541SAndroid Build Coastguard Worker             case FOUR_BYTE_LENGTH:
405*09635541SAndroid Build Coastguard Worker                 std::tie(success, addlData, pos) = parseLength<uint32_t>(pos, end, parseClient);
406*09635541SAndroid Build Coastguard Worker                 break;
407*09635541SAndroid Build Coastguard Worker 
408*09635541SAndroid Build Coastguard Worker             case EIGHT_BYTE_LENGTH:
409*09635541SAndroid Build Coastguard Worker                 std::tie(success, addlData, pos) = parseLength<uint64_t>(pos, end, parseClient);
410*09635541SAndroid Build Coastguard Worker                 break;
411*09635541SAndroid Build Coastguard Worker 
412*09635541SAndroid Build Coastguard Worker             case INDEFINITE_LENGTH:
413*09635541SAndroid Build Coastguard Worker                 // View only strings are not yet supported due to their disjoint nature.
414*09635541SAndroid Build Coastguard Worker                 if (type != ARRAY && type != MAP && !(type == BSTR && !emitViews) &&
415*09635541SAndroid Build Coastguard Worker                     !(type == TSTR && !emitViews)) {
416*09635541SAndroid Build Coastguard Worker                     parseClient->error(begin, "Unsupported indefinite length item.");
417*09635541SAndroid Build Coastguard Worker                     return {begin, nullptr};
418*09635541SAndroid Build Coastguard Worker                 }
419*09635541SAndroid Build Coastguard Worker                 addlData = std::nullopt;
420*09635541SAndroid Build Coastguard Worker                 break;
421*09635541SAndroid Build Coastguard Worker 
422*09635541SAndroid Build Coastguard Worker             default:
423*09635541SAndroid Build Coastguard Worker                 CHECK(false);  //  It's impossible to get here
424*09635541SAndroid Build Coastguard Worker                 break;
425*09635541SAndroid Build Coastguard Worker         }
426*09635541SAndroid Build Coastguard Worker     }
427*09635541SAndroid Build Coastguard Worker 
428*09635541SAndroid Build Coastguard Worker     if (!success) return {begin, nullptr};
429*09635541SAndroid Build Coastguard Worker 
430*09635541SAndroid Build Coastguard Worker     switch (type) {
431*09635541SAndroid Build Coastguard Worker         case UINT:
432*09635541SAndroid Build Coastguard Worker             return handleUint(*addlData, begin, pos, parseClient);
433*09635541SAndroid Build Coastguard Worker 
434*09635541SAndroid Build Coastguard Worker         case NINT:
435*09635541SAndroid Build Coastguard Worker             return handleNint(*addlData, begin, pos, parseClient);
436*09635541SAndroid Build Coastguard Worker 
437*09635541SAndroid Build Coastguard Worker         case BSTR:
438*09635541SAndroid Build Coastguard Worker             if (!addlData.has_value()) {
439*09635541SAndroid Build Coastguard Worker                 return handleIncompleteString(std::make_unique<IncompleteBstr>(), begin, pos, end,
440*09635541SAndroid Build Coastguard Worker                                               "byte string", emitViews, parseClient, depth);
441*09635541SAndroid Build Coastguard Worker             } else if (emitViews) {
442*09635541SAndroid Build Coastguard Worker                 return handleString<ViewBstr>(*addlData, begin, pos, end, "byte string",
443*09635541SAndroid Build Coastguard Worker                                               parseClient);
444*09635541SAndroid Build Coastguard Worker             } else {
445*09635541SAndroid Build Coastguard Worker                 return handleString<Bstr>(*addlData, begin, pos, end, "byte string", parseClient);
446*09635541SAndroid Build Coastguard Worker             }
447*09635541SAndroid Build Coastguard Worker 
448*09635541SAndroid Build Coastguard Worker         case TSTR:
449*09635541SAndroid Build Coastguard Worker             if (!addlData.has_value()) {
450*09635541SAndroid Build Coastguard Worker                 return handleIncompleteString(std::make_unique<IncompleteTstr>(), begin, pos, end,
451*09635541SAndroid Build Coastguard Worker                                               "text string", emitViews, parseClient, depth);
452*09635541SAndroid Build Coastguard Worker             } else if (emitViews) {
453*09635541SAndroid Build Coastguard Worker                 return handleString<ViewTstr>(*addlData, begin, pos, end, "text string",
454*09635541SAndroid Build Coastguard Worker                                               parseClient);
455*09635541SAndroid Build Coastguard Worker             } else {
456*09635541SAndroid Build Coastguard Worker                 return handleString<Tstr>(*addlData, begin, pos, end, "text string", parseClient);
457*09635541SAndroid Build Coastguard Worker             }
458*09635541SAndroid Build Coastguard Worker 
459*09635541SAndroid Build Coastguard Worker         case ARRAY:
460*09635541SAndroid Build Coastguard Worker             return handleCompound(std::make_unique<IncompleteArray>(addlData), addlData, begin, pos,
461*09635541SAndroid Build Coastguard Worker                                   end, "array", emitViews, parseClient, depth);
462*09635541SAndroid Build Coastguard Worker 
463*09635541SAndroid Build Coastguard Worker         case MAP:
464*09635541SAndroid Build Coastguard Worker             return handleCompound(std::make_unique<IncompleteMap>(addlData),
465*09635541SAndroid Build Coastguard Worker                                   addlData.has_value() ? *addlData * 2 : addlData, begin, pos, end,
466*09635541SAndroid Build Coastguard Worker                                   "map", emitViews, parseClient, depth);
467*09635541SAndroid Build Coastguard Worker 
468*09635541SAndroid Build Coastguard Worker         case SEMANTIC:
469*09635541SAndroid Build Coastguard Worker             return handleCompound(std::make_unique<IncompleteSemanticTag>(*addlData), 1, begin, pos,
470*09635541SAndroid Build Coastguard Worker                                   end, "semantic", emitViews, parseClient, depth);
471*09635541SAndroid Build Coastguard Worker 
472*09635541SAndroid Build Coastguard Worker         case SIMPLE:
473*09635541SAndroid Build Coastguard Worker             switch (tagInt) {
474*09635541SAndroid Build Coastguard Worker                 case TRUE:
475*09635541SAndroid Build Coastguard Worker                 case FALSE:
476*09635541SAndroid Build Coastguard Worker                     return handleBool(*addlData, begin, pos, parseClient);
477*09635541SAndroid Build Coastguard Worker                 case FLOAT_V:
478*09635541SAndroid Build Coastguard Worker #if defined(__STDC_IEC_559__) || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
479*09635541SAndroid Build Coastguard Worker                     return handleFloat(*addlData, begin, pos, parseClient);
480*09635541SAndroid Build Coastguard Worker #else
481*09635541SAndroid Build Coastguard Worker                     parseClient->error(begin, "Value float is not supported for platform.");
482*09635541SAndroid Build Coastguard Worker                     return {begin, nullptr};
483*09635541SAndroid Build Coastguard Worker #endif  // __STDC_IEC_559__ || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
484*09635541SAndroid Build Coastguard Worker                 case DOUBLE_V:
485*09635541SAndroid Build Coastguard Worker #if defined(__STDC_IEC_559__) || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
486*09635541SAndroid Build Coastguard Worker                     return handleDouble(*addlData, begin, pos, parseClient);
487*09635541SAndroid Build Coastguard Worker #else
488*09635541SAndroid Build Coastguard Worker                     parseClient->error(begin, "Value double is not supported for platform.");
489*09635541SAndroid Build Coastguard Worker                     return {begin, nullptr};
490*09635541SAndroid Build Coastguard Worker #endif  // __STDC_IEC_559__ || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
491*09635541SAndroid Build Coastguard Worker                 case NULL_V:
492*09635541SAndroid Build Coastguard Worker                     return handleNull(begin, pos, parseClient);
493*09635541SAndroid Build Coastguard Worker                 default:
494*09635541SAndroid Build Coastguard Worker                     parseClient->error(begin, "Unsupported half-floating-point or simple value.");
495*09635541SAndroid Build Coastguard Worker                     return {begin, nullptr};
496*09635541SAndroid Build Coastguard Worker             }
497*09635541SAndroid Build Coastguard Worker     }
498*09635541SAndroid Build Coastguard Worker     CHECK(false);  // Impossible to get here.
499*09635541SAndroid Build Coastguard Worker     return {};
500*09635541SAndroid Build Coastguard Worker }
501*09635541SAndroid Build Coastguard Worker 
502*09635541SAndroid Build Coastguard Worker class FullParseClient : public ParseClient {
503*09635541SAndroid Build Coastguard Worker   public:
item(std::unique_ptr<Item> & item,const uint8_t *,const uint8_t *,const uint8_t * end)504*09635541SAndroid Build Coastguard Worker     virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
505*09635541SAndroid Build Coastguard Worker                               const uint8_t* end) override {
506*09635541SAndroid Build Coastguard Worker         if (mParentStack.empty() && !item->isCompound()) {
507*09635541SAndroid Build Coastguard Worker             // This is the first and only item.
508*09635541SAndroid Build Coastguard Worker             mTheItem = std::move(item);
509*09635541SAndroid Build Coastguard Worker             mPosition = end;
510*09635541SAndroid Build Coastguard Worker             return nullptr;  //  We're done.
511*09635541SAndroid Build Coastguard Worker         }
512*09635541SAndroid Build Coastguard Worker 
513*09635541SAndroid Build Coastguard Worker         if (item->isCompound()) {
514*09635541SAndroid Build Coastguard Worker             // Starting a new compound data item, i.e. a new parent.  Save it on the parent stack.
515*09635541SAndroid Build Coastguard Worker             // It's safe to save a raw pointer because the unique_ptr is guaranteed to stay in
516*09635541SAndroid Build Coastguard Worker             // existence until the corresponding itemEnd() call.
517*09635541SAndroid Build Coastguard Worker             mParentStack.push(item.get());
518*09635541SAndroid Build Coastguard Worker             return this;
519*09635541SAndroid Build Coastguard Worker         } else {
520*09635541SAndroid Build Coastguard Worker             return appendToLastParent(std::move(item));
521*09635541SAndroid Build Coastguard Worker         }
522*09635541SAndroid Build Coastguard Worker     }
523*09635541SAndroid Build Coastguard Worker 
itemEnd(std::unique_ptr<Item> & item,const uint8_t *,const uint8_t *,const uint8_t * end)524*09635541SAndroid Build Coastguard Worker     virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
525*09635541SAndroid Build Coastguard Worker                                  const uint8_t* end) override {
526*09635541SAndroid Build Coastguard Worker         CHECK(item->isCompound() && item.get() == mParentStack.top());
527*09635541SAndroid Build Coastguard Worker         mParentStack.pop();
528*09635541SAndroid Build Coastguard Worker         IncompleteItem* incompleteItem = IncompleteItem::cast(item.get());
529*09635541SAndroid Build Coastguard Worker         std::unique_ptr<Item> finalizedItem = std::move(*incompleteItem).finalize();
530*09635541SAndroid Build Coastguard Worker 
531*09635541SAndroid Build Coastguard Worker         if (mParentStack.empty()) {
532*09635541SAndroid Build Coastguard Worker             mTheItem = std::move(finalizedItem);
533*09635541SAndroid Build Coastguard Worker             mPosition = end;
534*09635541SAndroid Build Coastguard Worker             return nullptr;  // We're done
535*09635541SAndroid Build Coastguard Worker         } else {
536*09635541SAndroid Build Coastguard Worker             return appendToLastParent(std::move(finalizedItem));
537*09635541SAndroid Build Coastguard Worker         }
538*09635541SAndroid Build Coastguard Worker     }
539*09635541SAndroid Build Coastguard Worker 
error(const uint8_t * position,const std::string & errorMessage)540*09635541SAndroid Build Coastguard Worker     virtual void error(const uint8_t* position, const std::string& errorMessage) override {
541*09635541SAndroid Build Coastguard Worker         mPosition = position;
542*09635541SAndroid Build Coastguard Worker         mErrorMessage = errorMessage;
543*09635541SAndroid Build Coastguard Worker     }
544*09635541SAndroid Build Coastguard Worker 
545*09635541SAndroid Build Coastguard Worker     std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
546*09635541SAndroid Build Coastguard Worker                std::string /* errMsg */>
parseResult()547*09635541SAndroid Build Coastguard Worker     parseResult() {
548*09635541SAndroid Build Coastguard Worker         std::unique_ptr<Item> p = std::move(mTheItem);
549*09635541SAndroid Build Coastguard Worker         return {std::move(p), mPosition, std::move(mErrorMessage)};
550*09635541SAndroid Build Coastguard Worker     }
551*09635541SAndroid Build Coastguard Worker 
552*09635541SAndroid Build Coastguard Worker   private:
appendToLastParent(std::unique_ptr<Item> item)553*09635541SAndroid Build Coastguard Worker     ParseClient* appendToLastParent(std::unique_ptr<Item> item) {
554*09635541SAndroid Build Coastguard Worker         auto parent = mParentStack.top();
555*09635541SAndroid Build Coastguard Worker         switch (parent->type()) {
556*09635541SAndroid Build Coastguard Worker             case BSTR:
557*09635541SAndroid Build Coastguard Worker                 if (item->type() != BSTR) {
558*09635541SAndroid Build Coastguard Worker                     mErrorMessage += "Expected BSTR in indefinite-length string.";
559*09635541SAndroid Build Coastguard Worker                     return nullptr;
560*09635541SAndroid Build Coastguard Worker                 }
561*09635541SAndroid Build Coastguard Worker                 IncompleteItem::cast(parent)->add(std::move(item));
562*09635541SAndroid Build Coastguard Worker                 break;
563*09635541SAndroid Build Coastguard Worker             case TSTR:
564*09635541SAndroid Build Coastguard Worker                 if (item->type() != TSTR) {
565*09635541SAndroid Build Coastguard Worker                     mErrorMessage += "Expected TSTR in indefinite-length string.";
566*09635541SAndroid Build Coastguard Worker                     return nullptr;
567*09635541SAndroid Build Coastguard Worker                 }
568*09635541SAndroid Build Coastguard Worker                 IncompleteItem::cast(parent)->add(std::move(item));
569*09635541SAndroid Build Coastguard Worker                 break;
570*09635541SAndroid Build Coastguard Worker             default:
571*09635541SAndroid Build Coastguard Worker                 IncompleteItem::cast(parent)->add(std::move(item));
572*09635541SAndroid Build Coastguard Worker                 break;
573*09635541SAndroid Build Coastguard Worker         }
574*09635541SAndroid Build Coastguard Worker         return this;
575*09635541SAndroid Build Coastguard Worker     }
576*09635541SAndroid Build Coastguard Worker 
577*09635541SAndroid Build Coastguard Worker     std::unique_ptr<Item> mTheItem;
578*09635541SAndroid Build Coastguard Worker     std::stack<Item*> mParentStack;
579*09635541SAndroid Build Coastguard Worker     const uint8_t* mPosition = nullptr;
580*09635541SAndroid Build Coastguard Worker     std::string mErrorMessage;
581*09635541SAndroid Build Coastguard Worker };
582*09635541SAndroid Build Coastguard Worker 
583*09635541SAndroid Build Coastguard Worker }  // anonymous namespace
584*09635541SAndroid Build Coastguard Worker 
parse(const uint8_t * begin,const uint8_t * end,ParseClient * parseClient)585*09635541SAndroid Build Coastguard Worker void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient) {
586*09635541SAndroid Build Coastguard Worker     parseRecursively(begin, end, false, parseClient, 0);
587*09635541SAndroid Build Coastguard Worker }
588*09635541SAndroid Build Coastguard Worker 
589*09635541SAndroid Build Coastguard Worker std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
590*09635541SAndroid Build Coastguard Worker            std::string /* errMsg */>
parse(const uint8_t * begin,const uint8_t * end)591*09635541SAndroid Build Coastguard Worker parse(const uint8_t* begin, const uint8_t* end) {
592*09635541SAndroid Build Coastguard Worker     FullParseClient parseClient;
593*09635541SAndroid Build Coastguard Worker     parse(begin, end, &parseClient);
594*09635541SAndroid Build Coastguard Worker     return parseClient.parseResult();
595*09635541SAndroid Build Coastguard Worker }
596*09635541SAndroid Build Coastguard Worker 
parseWithViews(const uint8_t * begin,const uint8_t * end,ParseClient * parseClient)597*09635541SAndroid Build Coastguard Worker void parseWithViews(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient) {
598*09635541SAndroid Build Coastguard Worker     parseRecursively(begin, end, true, parseClient, 0);
599*09635541SAndroid Build Coastguard Worker }
600*09635541SAndroid Build Coastguard Worker 
601*09635541SAndroid Build Coastguard Worker std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
602*09635541SAndroid Build Coastguard Worker            std::string /* errMsg */>
parseWithViews(const uint8_t * begin,const uint8_t * end)603*09635541SAndroid Build Coastguard Worker parseWithViews(const uint8_t* begin, const uint8_t* end) {
604*09635541SAndroid Build Coastguard Worker     FullParseClient parseClient;
605*09635541SAndroid Build Coastguard Worker     parseWithViews(begin, end, &parseClient);
606*09635541SAndroid Build Coastguard Worker     return parseClient.parseResult();
607*09635541SAndroid Build Coastguard Worker }
608*09635541SAndroid Build Coastguard Worker 
609*09635541SAndroid Build Coastguard Worker }  // namespace cppbor
610