aboutsummaryrefslogtreecommitdiff
path: root/src/cppbor_parse.cpp
diff options
context:
space:
mode:
authorAndrei Homescu <ah@immunant.com>2021-02-12 22:47:05 -0800
committerAndrei Homescu <ah@immunant.com>2021-03-11 15:37:43 -0800
commit4d171a791a4e44ae1b061f122282d0448dc612b3 (patch)
tree783985d5fa72db3f8f992149c9a263fbebb13f65 /src/cppbor_parse.cpp
parentad80fb83f579372e142e97cba8ea9bddd8362814 (diff)
downloadlibcppbor-4d171a791a4e44ae1b061f122282d0448dc612b3.tar.gz
Add view items for zero-copy parsing of CBOR strings
This CL adds two new ViewTstr and ViewBstr Item types that hold strings as string_view and basic_string_view<uint8_t> types instead of std::string or std::vector<uint8_t>, respectively. This allows for zero-copy parsing of CBOR (mainly strings), which is useful in low-memory environments like the apploader where CBOR data can contain large bstr values. Bug: 115420908 Test: cppbor_host_test_external Change-Id: I69322f0de258e3583cbd842ce240398504a1973f
Diffstat (limited to 'src/cppbor_parse.cpp')
-rw-r--r--src/cppbor_parse.cpp43
1 files changed, 32 insertions, 11 deletions
diff --git a/src/cppbor_parse.cpp b/src/cppbor_parse.cpp
index 42d74fb..5cf76b2 100644
--- a/src/cppbor_parse.cpp
+++ b/src/cppbor_parse.cpp
@@ -54,7 +54,7 @@ std::tuple<bool, uint64_t, const uint8_t*> parseLength(const uint8_t* pos, const
}
std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
- ParseClient* parseClient);
+ bool emitViews, ParseClient* parseClient);
std::tuple<const uint8_t*, ParseClient*> handleUint(uint64_t value, const uint8_t* hdrBegin,
const uint8_t* hdrEnd,
@@ -162,6 +162,7 @@ class IncompleteSemanticTag : public SemanticTag, public IncompleteItem {
std::tuple<const uint8_t*, ParseClient*> handleEntries(size_t entryCount, const uint8_t* hdrBegin,
const uint8_t* pos, const uint8_t* end,
const std::string& typeName,
+ bool emitViews,
ParseClient* parseClient) {
while (entryCount > 0) {
--entryCount;
@@ -169,7 +170,7 @@ std::tuple<const uint8_t*, ParseClient*> handleEntries(size_t entryCount, const
parseClient->error(hdrBegin, "Not enough entries for " + typeName + ".");
return {hdrBegin, nullptr /* end parsing */};
}
- std::tie(pos, parseClient) = parseRecursively(pos, end, parseClient);
+ std::tie(pos, parseClient) = parseRecursively(pos, end, emitViews, parseClient);
if (!parseClient) return {hdrBegin, nullptr};
}
return {pos, parseClient};
@@ -178,21 +179,21 @@ std::tuple<const uint8_t*, ParseClient*> handleEntries(size_t entryCount, const
std::tuple<const uint8_t*, ParseClient*> handleCompound(
std::unique_ptr<Item> item, uint64_t entryCount, const uint8_t* hdrBegin,
const uint8_t* valueBegin, const uint8_t* end, const std::string& typeName,
- ParseClient* parseClient) {
+ bool emitViews, ParseClient* parseClient) {
parseClient =
parseClient->item(item, hdrBegin, valueBegin, valueBegin /* don't know the end yet */);
if (!parseClient) return {hdrBegin, nullptr};
const uint8_t* pos;
std::tie(pos, parseClient) =
- handleEntries(entryCount, hdrBegin, valueBegin, end, typeName, parseClient);
+ handleEntries(entryCount, hdrBegin, valueBegin, end, typeName, emitViews, parseClient);
if (!parseClient) return {hdrBegin, nullptr};
return {pos, parseClient->itemEnd(item, hdrBegin, valueBegin, pos)};
}
std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
- ParseClient* parseClient) {
+ bool emitViews, ParseClient* parseClient) {
const uint8_t* pos = begin;
MajorType type = static_cast<MajorType>(*pos & 0xE0);
@@ -237,22 +238,30 @@ std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin,
return handleNint(addlData, begin, pos, parseClient);
case BSTR:
- return handleString<Bstr>(addlData, begin, pos, end, "byte string", parseClient);
+ if (emitViews) {
+ return handleString<ViewBstr>(addlData, begin, pos, end, "byte string", parseClient);
+ } else {
+ return handleString<Bstr>(addlData, begin, pos, end, "byte string", parseClient);
+ }
case TSTR:
- return handleString<Tstr>(addlData, begin, pos, end, "text string", parseClient);
+ if (emitViews) {
+ return handleString<ViewTstr>(addlData, begin, pos, end, "text string", parseClient);
+ } else {
+ return handleString<Tstr>(addlData, begin, pos, end, "text string", parseClient);
+ }
case ARRAY:
return handleCompound(std::make_unique<IncompleteArray>(addlData), addlData, begin, pos,
- end, "array", parseClient);
+ end, "array", emitViews, parseClient);
case MAP:
return handleCompound(std::make_unique<IncompleteMap>(addlData), addlData * 2, begin,
- pos, end, "map", parseClient);
+ pos, end, "map", emitViews, parseClient);
case SEMANTIC:
return handleCompound(std::make_unique<IncompleteSemanticTag>(addlData), 1, begin, pos,
- end, "semantic", parseClient);
+ end, "semantic", emitViews, parseClient);
case SIMPLE:
switch (addlData) {
@@ -346,7 +355,7 @@ class FullParseClient : public ParseClient {
} // anonymous namespace
void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient) {
- parseRecursively(begin, end, parseClient);
+ parseRecursively(begin, end, false, parseClient);
}
std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
@@ -357,4 +366,16 @@ parse(const uint8_t* begin, const uint8_t* end) {
return parseClient.parseResult();
}
+void parseWithViews(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient) {
+ parseRecursively(begin, end, true, parseClient);
+}
+
+std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
+ std::string /* errMsg */>
+parseWithViews(const uint8_t* begin, const uint8_t* end) {
+ FullParseClient parseClient;
+ parseWithViews(begin, end, &parseClient);
+ return parseClient.parseResult();
+}
+
} // namespace cppbor