fxos: more BSON utilities

This commit is contained in:
Lephenixnoir 2023-09-23 19:07:31 +02:00
parent c0820b59f0
commit 6edbd1dba1
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
2 changed files with 68 additions and 4 deletions

View File

@ -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

View File

@ -28,6 +28,7 @@
//---
#include <fxos/util/bson.h>
#include <fxos/util/log.h>
#include <vector>
#include <cstring>
#include <cstdio>
@ -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<BSON *>(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<BSON *>(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;