From 6edbd1dba1586b5ef6ae7ff08333c17452697ede Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sat, 23 Sep 2023 19:07:31 +0200 Subject: [PATCH] fxos: more BSON utilities --- include/fxos/util/bson.h | 20 +++++++++++++--- lib/util/bson.cpp | 52 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/include/fxos/util/bson.h b/include/fxos/util/bson.h index 59a0275..0f27dda 100644 --- a/include/fxos/util/bson.h +++ b/include/fxos/util/bson.h @@ -6,8 +6,8 @@ //---------------------------------------------------------------------------// // fxos/util/bson: Binary serialization (BSON format) // -// This header implementats a subset of the BSON format [1], which fxos uses -// to save project and configuration files. The few aspects of note of this +// This header implements a subset of the BSON format [1], which fxos uses to +// save project and configuration files. The few aspects of note of this // implementation are: // // - Values and fields are immutable with RAII semantics. The only type of @@ -84,6 +84,12 @@ struct BSON recursive context for the error, which helps with analysis. */ static BSON parseDocumentFromFile(FILE *fp, bool *error, bool log); + /* Load a file. The file should be a document. If a `expectedType` is + provided, the document should have a field "*" with that value. Return + a Null value in case of error. */ + static BSON loadDocumentFromFile(std::string path, bool log, bool mustExist, + char const *expectedType = nullptr); + /* Constructors */ static BSON mkDouble(double d) @@ -140,6 +146,8 @@ struct BSON in the heap. */ static BSON mkDocumentFromFieldArray(BSONField *fields, size_t count); + /* Construct an array with count null values (which can be assigned). */ + static BSON mkArray(size_t count); /* Construct an array by moving every value from the array without taking ownership of the array. */ static BSON mkArrayFromValues(BSON *values, size_t count); @@ -153,9 +161,10 @@ struct BSON region, which must be in the heap. */ static BSON mkBinaryMove(int subtype, u8 *data, size_t size); + /* Construct a string by copying the input. */ + static BSON mkString(std::string const &str); /* Construct a string by copying the input. */ static BSON mkStringCopy(char const *str, int len = -1); - static BSON mkStringCopy(std::string const &str); /* Construct a string by taking ownership of the provided buffer, which must be NUL-terminated and in the heap. */ static BSON mkStringMove(char *str); @@ -255,6 +264,11 @@ struct BSON char const *getStringReadOnly() const; /* Get a copy of the NUL-terminated string, malloc() allocated */ char *getStringCopy() const; + /* Get a copy of the NUL-terminated string */ + std::string getString() const + { + return std::string(getStringReadOnly()); + } /* Document/array size */ uint size() const diff --git a/lib/util/bson.cpp b/lib/util/bson.cpp index e668349..7ea3f3e 100644 --- a/lib/util/bson.cpp +++ b/lib/util/bson.cpp @@ -28,6 +28,7 @@ //--- #include +#include #include #include #include @@ -445,6 +446,43 @@ BSON BSON::parseDocumentFromFile(FILE *fp, bool *error, bool log) return v; } +BSON BSON::loadDocumentFromFile( + std::string path, bool log, bool mustExist, char const *expectedType) +{ + FILE *fp = fopen(path.c_str(), "r"); + if(!fp) { + if(mustExist && log) + FxOS_log(ERR, "Cannot read '%s': %m", path.c_str()); + return mkNull(); + } + + bool e; + BSON v = parseDocumentFromFile(fp, &e, log); + fclose(fp); + if(!e) { + if(log) + FxOS_log(ERR, "Failed to parse '%s'", path.c_str()); + return mkNull(); + } + + if(!v.isDocument()) { + if(log) + FxOS_log(ERR, "Contents of '%s' is not a document", path.c_str()); + return mkNull(); + } + + if(expectedType + && !(v.hasField("*") && v["*"].isString() + && v["*"].getString() == std::string(expectedType))) { + if(log) + FxOS_log(ERR, "Contents of '%s' do not have expected type %s", + path.c_str(), expectedType); + return mkNull(); + } + + return v; +} + #undef LOG BSON BSON::mkDocument( @@ -486,6 +524,18 @@ BSON BSON::mkDocumentFromFieldArray(BSONField *fields, size_t count) return v; } +BSON BSON::mkArray(size_t count) +{ + BSON *values = static_cast(malloc(count * sizeof *values)); + if(!values) + throw std::bad_alloc {}; + + for(uint i = 0; i < count; i++) + values[i] = mkNull(); + + return mkArrayFromValueArray(values, count); +} + BSON BSON::mkArrayFromValues(BSON *values_ro, size_t count) { BSON *values = static_cast(malloc(count * sizeof *values)); @@ -546,7 +596,7 @@ BSON BSON::mkStringCopy(char const *str, int len) return v; } -BSON BSON::mkStringCopy(std::string const &str) +BSON BSON::mkString(std::string const &str) { BSON v; v.m_type = Type::String;