• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include "cppbor.h"
20 
21 namespace cppbor {
22 
23 using ParseResult = std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
24                                std::string /* errMsg */>;
25 
26 /**
27  * Parse the first CBOR data item (possibly compound) from the range [begin, end).
28  *
29  * Returns a tuple of Item pointer, buffer pointer and error message.  If parsing is successful, the
30  * Item pointer is non-null, the buffer pointer points to the first byte after the
31  * successfully-parsed item and the error message string is empty.  If parsing fails, the Item
32  * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
33  * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
34  * too large for the remaining buffer, etc.) and the string contains an error message describing the
35  * problem encountered.
36  */
37 ParseResult parse(const uint8_t* begin, const uint8_t* end);
38 
39 /**
40  * Parse the first CBOR data item (possibly compound) from the range [begin, end).
41  *
42  * Returns a tuple of Item pointer, buffer pointer and error message.  If parsing is successful, the
43  * Item pointer is non-null, the buffer pointer points to the first byte after the
44  * successfully-parsed item and the error message string is empty.  If parsing fails, the Item
45  * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
46  * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
47  * too large for the remaining buffer, etc.) and the string contains an error message describing the
48  * problem encountered.
49  *
50  * The returned CBOR data item will contain View* items backed by
51  * std::string_view types over the input range.
52  * WARNING! If the input range changes underneath, the corresponding views will
53  * carry the same change.
54  */
55 ParseResult parseWithViews(const uint8_t* begin, const uint8_t* end);
56 
57 /**
58  * Parse the first CBOR data item (possibly compound) from the byte vector.
59  *
60  * Returns a tuple of Item pointer, buffer pointer and error message.  If parsing is successful, the
61  * Item pointer is non-null, the buffer pointer points to the first byte after the
62  * successfully-parsed item and the error message string is empty.  If parsing fails, the Item
63  * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
64  * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
65  * too large for the remaining buffer, etc.) and the string contains an error message describing the
66  * problem encountered.
67  */
parse(const std::vector<uint8_t> & encoding)68 inline ParseResult parse(const std::vector<uint8_t>& encoding) {
69     return parse(encoding.data(), encoding.data() + encoding.size());
70 }
71 
72 /**
73  * Parse the first CBOR data item (possibly compound) from the range [begin, begin + size).
74  *
75  * Returns a tuple of Item pointer, buffer pointer and error message.  If parsing is successful, the
76  * Item pointer is non-null, the buffer pointer points to the first byte after the
77  * successfully-parsed item and the error message string is empty.  If parsing fails, the Item
78  * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
79  * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
80  * too large for the remaining buffer, etc.) and the string contains an error message describing the
81  * problem encountered.
82  */
parse(const uint8_t * begin,size_t size)83 inline ParseResult parse(const uint8_t* begin, size_t size) {
84     return parse(begin, begin + size);
85 }
86 
87 /**
88  * Parse the first CBOR data item (possibly compound) from the range [begin, begin + size).
89  *
90  * Returns a tuple of Item pointer, buffer pointer and error message.  If parsing is successful, the
91  * Item pointer is non-null, the buffer pointer points to the first byte after the
92  * successfully-parsed item and the error message string is empty.  If parsing fails, the Item
93  * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
94  * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
95  * too large for the remaining buffer, etc.) and the string contains an error message describing the
96  * problem encountered.
97  *
98  * The returned CBOR data item will contain View* items backed by
99  * std::string_view types over the input range.
100  * WARNING! If the input range changes underneath, the corresponding views will
101  * carry the same change.
102  */
parseWithViews(const uint8_t * begin,size_t size)103 inline ParseResult parseWithViews(const uint8_t* begin, size_t size) {
104     return parseWithViews(begin, begin + size);
105 }
106 
107 /**
108  * Parse the first CBOR data item (possibly compound) from the value contained in a Bstr.
109  *
110  * Returns a tuple of Item pointer, buffer pointer and error message.  If parsing is successful, the
111  * Item pointer is non-null, the buffer pointer points to the first byte after the
112  * successfully-parsed item and the error message string is empty.  If parsing fails, the Item
113  * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
114  * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
115  * too large for the remaining buffer, etc.) and the string contains an error message describing the
116  * problem encountered.
117  */
parse(const Bstr * bstr)118 inline ParseResult parse(const Bstr* bstr) {
119     if (!bstr)
120         return ParseResult(nullptr, nullptr, "Null Bstr pointer");
121     return parse(bstr->value());
122 }
123 
124 class ParseClient;
125 
126 /**
127  * Parse the CBOR data in the range [begin, end) in streaming fashion, calling methods on the
128  * provided ParseClient when elements are found.
129  */
130 void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient);
131 
132 /**
133  * Parse the CBOR data in the range [begin, end) in streaming fashion, calling methods on the
134  * provided ParseClient when elements are found. Uses the View* item types
135  * instead of the copying ones.
136  */
137 void parseWithViews(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient);
138 
139 /**
140  * Parse the CBOR data in the vector in streaming fashion, calling methods on the
141  * provided ParseClient when elements are found.
142  */
parse(const std::vector<uint8_t> & encoding,ParseClient * parseClient)143 inline void parse(const std::vector<uint8_t>& encoding, ParseClient* parseClient) {
144     return parse(encoding.data(), encoding.data() + encoding.size(), parseClient);
145 }
146 
147 /**
148  * A pure interface that callers of the streaming parse functions must implement.
149  */
150 class ParseClient {
151   public:
~ParseClient()152     virtual ~ParseClient() {}
153 
154     /**
155      * Called when an item is found.  The Item pointer points to the found item; use type() and
156      * the appropriate as*() method to examine the value.  hdrBegin points to the first byte of the
157      * header, valueBegin points to the first byte of the value and end points one past the end of
158      * the item.  In the case of header-only items, such as integers, and compound items (ARRAY,
159      * MAP or SEMANTIC) whose end has not yet been found, valueBegin and end are equal and point to
160      * the byte past the header.
161      *
162      * Note that for compound types (ARRAY, MAP, and SEMANTIC), the Item will have no content.  For
163      * Map and Array items, the size() method will return a correct value, but the index operators
164      * are unsafe, and the object cannot be safely compared with another Array/Map.
165      *
166      * The method returns a ParseClient*.  In most cases "return this;" will be the right answer,
167      * but a different ParseClient may be returned, which the parser will begin using. If the method
168      * returns nullptr, parsing will be aborted immediately.
169      */
170     virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
171                               const uint8_t* valueBegin, const uint8_t* end) = 0;
172 
173     /**
174      * Called when the end of a compound item (MAP or ARRAY) is found.  The item argument will be
175      * the same one passed to the item() call -- and may be empty if item() moved its value out.
176      * hdrBegin, valueBegin and end point to the beginning of the item header, the beginning of the
177      * first contained value, and one past the end of the last contained value, respectively.
178      *
179      * Note that the Item will have no content.
180      *
181      * As with item(), itemEnd() can change the ParseClient by returning a different one, or end the
182      * parsing by returning nullptr;
183      */
184     virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
185                                  const uint8_t* valueBegin, const uint8_t* end) = 0;
186 
187     /**
188      * Called when parsing encounters an error.  position is set to the first unparsed byte (one
189      * past the last successfully-parsed byte) and errorMessage contains an message explaining what
190      * sort of error occurred.
191      */
192     virtual void error(const uint8_t* position, const std::string& errorMessage) = 0;
193 };
194 
195 }  // namespace cppbor
196