migrate from dynamic::Value to dv::value & total erase namespace 'dynamic'

This commit is contained in:
MihailRis
2024-09-18 23:31:18 +03:00
parent d3ba4b2e3e
commit 34d2e6d400
69 changed files with 1247 additions and 2248 deletions
+46 -58
View File
@@ -2,38 +2,38 @@
#include <stdexcept>
#include "data/dynamic.hpp"
#include "data/dv.hpp"
#include "byte_utils.hpp"
#include "gzip.hpp"
#include "util/Buffer.hpp"
using namespace json;
using namespace dynamic;
static void to_binary(ByteBuilder& builder, const Value& value) {
switch (static_cast<Type>(value.index())) {
case Type::none:
static void to_binary(ByteBuilder& builder, const dv::value& value) {
switch (value.getType()) {
case dv::value_type::none:
throw std::runtime_error("none value is not implemented");
case Type::map: {
const auto bytes = to_binary(std::get<Map_sptr>(value).get());
case dv::value_type::object: {
const auto bytes = json::to_binary(value);
builder.put(bytes.data(), bytes.size());
break;
}
case Type::list:
case dv::value_type::list:
builder.put(BJSON_TYPE_LIST);
for (const auto& element : std::get<List_sptr>(value)->values) {
for (const auto& element : value) {
to_binary(builder, element);
}
builder.put(BJSON_END);
break;
case Type::bytes: {
const auto& bytes = std::get<ByteBuffer_sptr>(value).get();
case dv::value_type::bytes: {
const auto& bytes = value.asBytes();
builder.put(BJSON_TYPE_BYTES);
builder.putInt32(bytes->size());
builder.put(bytes->data(), bytes->size());
builder.putInt32(bytes.size());
builder.put(bytes.data(), bytes.size());
break;
}
case Type::integer: {
auto val = std::get<integer_t>(value);
case dv::value_type::integer: {
auto val = value.asInteger();
if (val >= 0 && val <= 255) {
builder.put(BJSON_TYPE_BYTE);
builder.put(val);
@@ -49,26 +49,23 @@ static void to_binary(ByteBuilder& builder, const Value& value) {
}
break;
}
case Type::number:
case dv::value_type::number:
builder.put(BJSON_TYPE_NUMBER);
builder.putFloat64(std::get<number_t>(value));
builder.putFloat64(value.asNumber());
break;
case Type::boolean:
builder.put(BJSON_TYPE_FALSE + std::get<bool>(value));
case dv::value_type::boolean:
builder.put(BJSON_TYPE_FALSE + value.asBoolean());
break;
case Type::string:
case dv::value_type::string:
builder.put(BJSON_TYPE_STRING);
builder.put(std::get<std::string>(value));
builder.put(value.asString());
break;
}
}
static std::unique_ptr<List> array_from_binary(ByteReader& reader);
static std::unique_ptr<Map> object_from_binary(ByteReader& reader);
std::vector<ubyte> json::to_binary(const Map* obj, bool compress) {
std::vector<ubyte> json::to_binary(const dv::value& object, bool compress) {
if (compress) {
auto bytes = to_binary(obj, false);
auto bytes = to_binary(object, false);
return gzip::compress(bytes.data(), bytes.size());
}
ByteBuilder builder;
@@ -78,9 +75,9 @@ std::vector<ubyte> json::to_binary(const Map* obj, bool compress) {
builder.putInt32(0);
// writing entries
for (auto& entry : obj->values) {
builder.putCStr(entry.first.c_str());
to_binary(builder, entry.second);
for (const auto& [key, value] : object.asObject()) {
builder.putCStr(key.c_str());
to_binary(builder, value);
}
// terminating byte
builder.put(BJSON_END);
@@ -90,27 +87,23 @@ std::vector<ubyte> json::to_binary(const Map* obj, bool compress) {
return builder.build();
}
std::vector<ubyte> json::to_binary(const Value& value, bool compress) {
if (auto map = std::get_if<Map_sptr>(&value)) {
return to_binary(map->get(), compress);
}
throw std::runtime_error("map is only supported as the root element");
}
static dv::value list_from_binary(ByteReader& reader);
static dv::value object_from_binary(ByteReader& reader);
static Value value_from_binary(ByteReader& reader) {
static dv::value value_from_binary(ByteReader& reader) {
ubyte typecode = reader.get();
switch (typecode) {
case BJSON_TYPE_DOCUMENT:
reader.getInt32();
return Map_sptr(object_from_binary(reader).release());
return object_from_binary(reader);
case BJSON_TYPE_LIST:
return List_sptr(array_from_binary(reader).release());
return list_from_binary(reader);
case BJSON_TYPE_BYTE:
return static_cast<integer_t>(reader.get());
return reader.get();
case BJSON_TYPE_INT16:
return static_cast<integer_t>(reader.getInt16());
return reader.getInt16();
case BJSON_TYPE_INT32:
return static_cast<integer_t>(reader.getInt32());
return reader.getInt32();
case BJSON_TYPE_INT64:
return reader.getInt64();
case BJSON_TYPE_NUMBER:
@@ -121,7 +114,7 @@ static Value value_from_binary(ByteReader& reader) {
case BJSON_TYPE_STRING:
return reader.getString();
case BJSON_TYPE_NULL:
return NONE;
return dv::none;
case BJSON_TYPE_BYTES: {
int32_t size = reader.getInt32();
if (size < 0) {
@@ -132,7 +125,8 @@ static Value value_from_binary(ByteReader& reader) {
throw std::runtime_error(
"buffer_size > remaining_size "+std::to_string(size));
}
auto bytes = std::make_shared<ByteBuffer>(reader.pointer(), size);
auto bytes = std::make_shared<util::Buffer<ubyte>>(
reader.pointer(), size);
reader.skip(size);
return bytes;
}
@@ -141,26 +135,26 @@ static Value value_from_binary(ByteReader& reader) {
"type support not implemented for <"+std::to_string(typecode)+">");
}
static std::unique_ptr<List> array_from_binary(ByteReader& reader) {
auto array = std::make_unique<List>();
static dv::value list_from_binary(ByteReader& reader) {
auto list = dv::list();
while (reader.peek() != BJSON_END) {
array->put(value_from_binary(reader));
list.add(value_from_binary(reader));
}
reader.get();
return array;
return list;
}
static std::unique_ptr<Map> object_from_binary(ByteReader& reader) {
auto obj = std::make_unique<Map>();
static dv::value object_from_binary(ByteReader& reader) {
auto obj = dv::object();
while (reader.peek() != BJSON_END) {
const char* key = reader.getCString();
obj->put(key, value_from_binary(reader));
obj[key] = value_from_binary(reader);
}
reader.get();
return obj;
}
std::shared_ptr<Map> json::from_binary(const ubyte* src, size_t size) {
dv::value json::from_binary(const ubyte* src, size_t size) {
if (size < 2) {
throw std::runtime_error("bytes length is less than 2");
}
@@ -170,12 +164,6 @@ std::shared_ptr<Map> json::from_binary(const ubyte* src, size_t size) {
return from_binary(data.data(), data.size());
} else {
ByteReader reader(src, size);
Value value = value_from_binary(reader);
if (auto map = std::get_if<Map_sptr>(&value)) {
return *map;
} else {
throw std::runtime_error("root value is not an object");
}
return value_from_binary(reader);
}
}
+3 -14
View File
@@ -4,11 +4,8 @@
#include <vector>
#include "data/dv.hpp"
#include "data/dynamic_fwd.hpp"
namespace dynamic {
class Map;
}
#include "typedefs.hpp"
namespace json {
inline constexpr int BJSON_END = 0x0;
@@ -26,15 +23,7 @@ namespace json {
inline constexpr int BJSON_TYPE_NULL = 0xC;
inline constexpr int BJSON_TYPE_CDOCUMENT = 0x1F;
std::vector<ubyte> to_binaryDV(const dv::value& obj, bool compress = false);
std::vector<ubyte> to_binary(const dv::value& obj, bool compress = false);
dv::value from_binaryDV(const ubyte* src, size_t size);
std::vector<ubyte> to_binary(
const dynamic::Map* obj, bool compress = false
);
std::vector<ubyte> to_binary(
const dynamic::Value& obj, bool compress = false
);
std::shared_ptr<dynamic::Map> from_binary(const ubyte* src, size_t size);
dv::value from_binary(const ubyte* src, size_t size);
}
-168
View File
@@ -1,168 +0,0 @@
#include "binary_json.hpp"
#include <stdexcept>
#include "data/dv.hpp"
#include "byte_utils.hpp"
#include "gzip.hpp"
using namespace json;
static void to_binary(ByteBuilder& builder, const dv::value& value) {
switch (value.getType()) {
case dv::value_type::none:
throw std::runtime_error("none value is not implemented");
case dv::value_type::object: {
const auto bytes = json::to_binaryDV(value);
builder.put(bytes.data(), bytes.size());
break;
}
case dv::value_type::list:
builder.put(BJSON_TYPE_LIST);
for (const auto& element : value) {
to_binary(builder, element);
}
builder.put(BJSON_END);
break;
case dv::value_type::bytes: {
const auto& bytes = value.asBytes();
builder.put(BJSON_TYPE_BYTES);
builder.putInt32(bytes.size());
builder.put(bytes.data(), bytes.size());
break;
}
case dv::value_type::integer: {
auto val = value.asInteger();
if (val >= 0 && val <= 255) {
builder.put(BJSON_TYPE_BYTE);
builder.put(val);
} else if (val >= INT16_MIN && val <= INT16_MAX) {
builder.put(BJSON_TYPE_INT16);
builder.putInt16(val);
} else if (val >= INT32_MIN && val <= INT32_MAX) {
builder.put(BJSON_TYPE_INT32);
builder.putInt32(val);
} else {
builder.put(BJSON_TYPE_INT64);
builder.putInt64(val);
}
break;
}
case dv::value_type::number:
builder.put(BJSON_TYPE_NUMBER);
builder.putFloat64(value.asNumber());
break;
case dv::value_type::boolean:
builder.put(BJSON_TYPE_FALSE + value.asBoolean());
break;
case dv::value_type::string:
builder.put(BJSON_TYPE_STRING);
builder.put(value.asString());
break;
}
}
std::vector<ubyte> json::to_binaryDV(const dv::value& object, bool compress) {
if (compress) {
auto bytes = to_binaryDV(object, false);
return gzip::compress(bytes.data(), bytes.size());
}
ByteBuilder builder;
// type byte
builder.put(BJSON_TYPE_DOCUMENT);
// document size
builder.putInt32(0);
// writing entries
for (const auto& [key, value] : object.asObject()) {
builder.putCStr(key.c_str());
to_binary(builder, value);
}
// terminating byte
builder.put(BJSON_END);
// updating document size
builder.setInt32(1, builder.size());
return builder.build();
}
static dv::value list_from_binary(ByteReader& reader);
static dv::value object_from_binary(ByteReader& reader);
static dv::value value_from_binary(ByteReader& reader) {
ubyte typecode = reader.get();
switch (typecode) {
case BJSON_TYPE_DOCUMENT:
reader.getInt32();
return object_from_binary(reader);
case BJSON_TYPE_LIST:
return list_from_binary(reader);
case BJSON_TYPE_BYTE:
return reader.get();
case BJSON_TYPE_INT16:
return reader.getInt16();
case BJSON_TYPE_INT32:
return reader.getInt32();
case BJSON_TYPE_INT64:
return reader.getInt64();
case BJSON_TYPE_NUMBER:
return reader.getFloat64();
case BJSON_TYPE_FALSE:
case BJSON_TYPE_TRUE:
return (typecode - BJSON_TYPE_FALSE) != 0;
case BJSON_TYPE_STRING:
return reader.getString();
case BJSON_TYPE_NULL:
return dv::none;
case BJSON_TYPE_BYTES: {
int32_t size = reader.getInt32();
if (size < 0) {
throw std::runtime_error(
"invalid byte-buffer size "+std::to_string(size));
}
if (size > reader.remaining()) {
throw std::runtime_error(
"buffer_size > remaining_size "+std::to_string(size));
}
auto bytes = std::make_shared<util::Buffer<ubyte>>(
reader.pointer(), size);
reader.skip(size);
return bytes;
}
}
throw std::runtime_error(
"type support not implemented for <"+std::to_string(typecode)+">");
}
static dv::value list_from_binary(ByteReader& reader) {
auto list = dv::list();
while (reader.peek() != BJSON_END) {
list.add(value_from_binary(reader));
}
reader.get();
return list;
}
static dv::value object_from_binary(ByteReader& reader) {
auto obj = dv::object();
while (reader.peek() != BJSON_END) {
const char* key = reader.getCString();
obj[key] = value_from_binary(reader);
}
reader.get();
return obj;
}
dv::value json::from_binaryDV(const ubyte* src, size_t size) {
if (size < 2) {
throw std::runtime_error("bytes length is less than 2");
}
if (src[0] == gzip::MAGIC[0] && src[1] == gzip::MAGIC[1]) {
// reading compressed document
auto data = gzip::decompress(src, size);
return from_binaryDV(data.data(), data.size());
} else {
ByteReader reader(src, size);
return value_from_binary(reader);
}
}
+2 -2
View File
@@ -258,7 +258,7 @@ int64_t BasicParser::parseSimpleInt(int base) {
return value;
}
dynamic::Value BasicParser::parseNumber() {
dv::value BasicParser::parseNumber() {
switch (peek()) {
case '-':
skip(1);
@@ -271,7 +271,7 @@ dynamic::Value BasicParser::parseNumber() {
}
}
dynamic::Value BasicParser::parseNumber(int sign) {
dv::value BasicParser::parseNumber(int sign) {
char c = peek();
int base = 10;
if (c == '0' && pos + 1 < source.length() &&
+3 -3
View File
@@ -3,7 +3,7 @@
#include <stdexcept>
#include <string>
#include "data/dynamic.hpp"
#include "data/dv.hpp"
#include "typedefs.hpp"
inline int is_box(int c) {
@@ -90,8 +90,8 @@ protected:
void reset();
int64_t parseSimpleInt(int base);
dynamic::Value parseNumber(int sign);
dynamic::Value parseNumber();
dv::value parseNumber(int sign);
dv::value parseNumber();
std::string parseString(char chr, bool closeRequired = true);
parsing_error error(const std::string& message);
+12 -271
View File
@@ -6,29 +6,17 @@
#include <memory>
#include <sstream>
#include "data/dynamic.hpp"
#include "util/stringutil.hpp"
#include "commons.hpp"
using namespace json;
using namespace dynamic;
class Parser : BasicParser {
std::unique_ptr<dynamic::List> parseList();
std::unique_ptr<dynamic::Map> parseObject();
dynamic::Value parseValue();
public:
Parser(std::string_view filename, std::string_view source);
std::unique_ptr<dynamic::Map> parse();
};
class ParserDV : BasicParser {
dv::value parseList();
dv::value parseObject();
dv::value parseValue();
public:
ParserDV(std::string_view filename, std::string_view source);
Parser(std::string_view filename, std::string_view source);
dv::value parse();
};
@@ -46,22 +34,6 @@ inline void newline(
}
}
void stringifyObj(
const Map* obj,
std::stringstream& ss,
int indent,
const std::string& indentstr,
bool nice
);
void stringifyArr(
const List* list,
std::stringstream& ss,
int indent,
const std::string& indentstr,
bool nice
);
void stringifyObj(
const dv::value& obj,
std::stringstream& ss,
@@ -78,34 +50,6 @@ void stringifyList(
bool nice
);
void stringifyValue(
const Value& value,
std::stringstream& ss,
int indent,
const std::string& indentstr,
bool nice
) {
if (auto map = std::get_if<Map_sptr>(&value)) {
stringifyObj(map->get(), ss, indent, indentstr, nice);
} else if (auto listptr = std::get_if<List_sptr>(&value)) {
stringifyArr(listptr->get(), ss, indent, indentstr, nice);
} else if (auto bytesptr = std::get_if<ByteBuffer_sptr>(&value)) {
auto bytes = bytesptr->get();
ss << "\"" << util::base64_encode(bytes->data(), bytes->size());
ss << "\"";
} else if (auto flag = std::get_if<bool>(&value)) {
ss << (*flag ? "true" : "false");
} else if (auto num = std::get_if<number_t>(&value)) {
ss << std::setprecision(15) << *num;
} else if (auto num = std::get_if<integer_t>(&value)) {
ss << *num;
} else if (auto str = std::get_if<std::string>(&value)) {
ss << util::escape(*str);
} else {
ss << "null";
}
}
void stringifyValue(
const dv::value& value,
std::stringstream& ss,
@@ -146,74 +90,6 @@ void stringifyValue(
}
}
void stringifyArr(
const List* list,
std::stringstream& ss,
int indent,
const std::string& indentstr,
bool nice
) {
if (list == nullptr) {
ss << "nullptr";
return;
}
if (list->values.empty()) {
ss << "[]";
return;
}
ss << "[";
for (size_t i = 0; i < list->size(); i++) {
if (i > 0 || nice) {
newline(ss, nice, indent, indentstr);
}
const Value& value = list->values[i];
stringifyValue(value, ss, indent + 1, indentstr, nice);
if (i + 1 < list->size()) {
ss << ',';
}
}
if (nice) {
newline(ss, true, indent - 1, indentstr);
}
ss << ']';
}
void stringifyObj(
const Map* obj,
std::stringstream& ss,
int indent,
const std::string& indentstr,
bool nice
) {
if (obj == nullptr) {
ss << "nullptr";
return;
}
if (obj->values.empty()) {
ss << "{}";
return;
}
ss << "{";
size_t index = 0;
for (auto& entry : obj->values) {
const std::string& key = entry.first;
if (index > 0 || nice) {
newline(ss, nice, indent, indentstr);
}
const Value& value = entry.second;
ss << util::escape(key) << ": ";
stringifyValue(value, ss, indent + 1, indentstr, nice);
index++;
if (index < obj->values.size()) {
ss << ',';
}
}
if (nice) {
newline(ss, true, indent - 1, indentstr);
}
ss << '}';
}
void stringifyList(
const dv::value& list,
std::stringstream& ss,
@@ -273,30 +149,6 @@ void stringifyObj(
}
std::string json::stringify(
const Map* obj, bool nice, const std::string& indent
) {
std::stringstream ss;
stringifyObj(obj, ss, 1, indent, nice);
return ss.str();
}
std::string json::stringify(
const dynamic::List* arr, bool nice, const std::string& indent
) {
std::stringstream ss;
stringifyArr(arr, ss, 1, indent, nice);
return ss.str();
}
std::string json::stringify(
const dynamic::Value& value, bool nice, const std::string& indent
) {
std::stringstream ss;
stringifyValue(value, ss, 1, indent, nice);
return ss.str();
}
std::string json::stringifyDV(
const dv::value& value, bool nice, const std::string& indent
) {
std::stringstream ss;
@@ -308,7 +160,7 @@ Parser::Parser(std::string_view filename, std::string_view source)
: BasicParser(filename, source) {
}
std::unique_ptr<Map> Parser::parse() {
dv::value Parser::parse() {
char next = peek();
if (next != '{') {
throw error("'{' expected");
@@ -316,118 +168,7 @@ std::unique_ptr<Map> Parser::parse() {
return parseObject();
}
std::unique_ptr<Map> Parser::parseObject() {
expect('{');
auto obj = std::make_unique<Map>();
auto& map = obj->values;
while (peek() != '}') {
if (peek() == '#') {
skipLine();
continue;
}
std::string key = parseName();
char next = peek();
if (next != ':') {
throw error("':' expected");
}
pos++;
map.insert(std::make_pair(key, parseValue()));
next = peek();
if (next == ',') {
pos++;
} else if (next == '}') {
break;
} else {
throw error("',' expected");
}
}
pos++;
return obj;
}
std::unique_ptr<List> Parser::parseList() {
expect('[');
auto arr = std::make_unique<List>();
auto& values = arr->values;
while (peek() != ']') {
if (peek() == '#') {
skipLine();
continue;
}
values.push_back(parseValue());
char next = peek();
if (next == ',') {
pos++;
} else if (next == ']') {
break;
} else {
throw error("',' expected");
}
}
pos++;
return arr;
}
Value Parser::parseValue() {
char next = peek();
if (next == '-' || next == '+' || is_digit(next)) {
auto numeric = parseNumber();
if (std::holds_alternative<integer_t>(numeric)) {
return std::get<integer_t>(numeric);
}
return std::get<number_t>(numeric);
}
if (is_identifier_start(next)) {
std::string literal = parseName();
if (literal == "true") {
return true;
} else if (literal == "false") {
return false;
} else if (literal == "inf") {
return INFINITY;
} else if (literal == "nan") {
return NAN;
}
throw error("invalid literal ");
}
if (next == '{') {
return Map_sptr(parseObject().release());
}
if (next == '[') {
return List_sptr(parseList().release());
}
if (next == '"' || next == '\'') {
pos++;
return parseString(next);
}
throw error("unexpected character '" + std::string({next}) + "'");
}
dynamic::Map_sptr json::parse(
std::string_view filename, std::string_view source
) {
Parser parser(filename, source);
return parser.parse();
}
dynamic::Map_sptr json::parse(std::string_view source) {
return parse("<string>", source);
}
ParserDV::ParserDV(std::string_view filename, std::string_view source)
: BasicParser(filename, source) {
}
dv::value ParserDV::parse() {
char next = peek();
if (next != '{') {
throw error("'{' expected");
}
return parseObject();
}
dv::value ParserDV::parseObject() {
dv::value Parser::parseObject() {
expect('{');
auto object = dv::object();
while (peek() != '}') {
@@ -455,7 +196,7 @@ dv::value ParserDV::parseObject() {
return object;
}
dv::value ParserDV::parseList() {
dv::value Parser::parseList() {
expect('[');
auto list = dv::list();
while (peek() != ']') {
@@ -478,14 +219,14 @@ dv::value ParserDV::parseList() {
return list;
}
dv::value ParserDV::parseValue() {
dv::value Parser::parseValue() {
char next = peek();
if (next == '-' || next == '+' || is_digit(next)) {
auto numeric = parseNumber();
if (std::holds_alternative<integer_t>(numeric)) {
return std::get<integer_t>(numeric);
if (numeric.isInteger()) {
return numeric.asInteger();
}
return std::get<number_t>(numeric);
return numeric.asNumber();
}
if (is_identifier_start(next)) {
std::string literal = parseName();
@@ -513,13 +254,13 @@ dv::value ParserDV::parseValue() {
throw error("unexpected character '" + std::string({next}) + "'");
}
dv::value json::parseDV(
dv::value json::parse(
std::string_view filename, std::string_view source
) {
ParserDV parser(filename, source);
Parser parser(filename, source);
return parser.parse();
}
dv::value json::parseDV(std::string_view source) {
return parseDV("<string>", source);
dv::value json::parse(std::string_view source) {
return parse("<string>", source);
}
+2 -18
View File
@@ -2,31 +2,15 @@
#include <string>
#include "data/dynamic.hpp"
#include "data/dv.hpp"
#include "typedefs.hpp"
#include "binary_json.hpp"
namespace json {
dynamic::Map_sptr parse(std::string_view filename, std::string_view source);
dynamic::Map_sptr parse(std::string_view source);
dv::value parseDV(std::string_view filename, std::string_view source);
dv::value parseDV(std::string_view source);
dv::value parse(std::string_view filename, std::string_view source);
dv::value parse(std::string_view source);
std::string stringify(
const dynamic::Map* obj, bool nice, const std::string& indent
);
std::string stringify(
const dynamic::List* arr, bool nice, const std::string& indent
);
std::string stringify(
const dynamic::Value& value, bool nice, const std::string& indent
);
std::string stringifyDV(
const dv::value& value, bool nice, const std::string& indent=" "
);
}
+8 -8
View File
@@ -63,18 +63,18 @@ public:
}
auto cmd = parseName();
if (cmd == "v") {
float x = dynamic::as_number(parseNumber());
float y = dynamic::as_number(parseNumber());
float z = dynamic::as_number(parseNumber());
float x = parseNumber().asNumber();
float y = parseNumber().asNumber();
float z = parseNumber().asNumber();
coords.emplace_back(x, y, z);
} else if (cmd == "vt") {
float u = dynamic::as_number(parseNumber());
float v = dynamic::as_number(parseNumber());
float u = parseNumber().asNumber();
float v = parseNumber().asNumber();
uvs.emplace_back(u, v);
} else if (cmd == "vn") {
float x = dynamic::as_number(parseNumber());
float y = dynamic::as_number(parseNumber());
float z = dynamic::as_number(parseNumber());
float x = parseNumber().asNumber();
float y = parseNumber().asNumber();
float z = parseNumber().asNumber();
normals.emplace_back(x, y, z);
} else {
skipLine();
+36 -45
View File
@@ -6,7 +6,6 @@
#include <iomanip>
#include <sstream>
#include "data/dynamic.hpp"
#include "data/setting.hpp"
#include "files/settings_io.hpp"
#include "util/stringutil.hpp"
@@ -15,7 +14,7 @@
using namespace toml;
class TomlReader : BasicParser {
dynamic::Map_sptr root;
dv::value root;
void skipWhitespace() override {
BasicParser::skipWhitespace();
@@ -27,33 +26,33 @@ class TomlReader : BasicParser {
}
}
dynamic::Map& getSection(const std::string& section) {
dv::value& getSection(const std::string& section) {
if (section.empty()) {
return *root;
return root;
}
size_t offset = 0;
auto& rootMap = *root;
auto rootMap = &root;
do {
size_t index = section.find('.', offset);
if (index == std::string::npos) {
auto map = rootMap.map(section);
if (map == nullptr) {
return rootMap.putMap(section);
auto map = rootMap->at(section);
if (!map) {
return rootMap->object(section);
}
return *map;
}
auto subsection = section.substr(offset, index);
auto map = rootMap.map(subsection);
if (map == nullptr) {
rootMap = rootMap.putMap(subsection);
auto map = rootMap->at(subsection);
if (!map) {
rootMap = &rootMap->object(subsection);
} else {
rootMap = *map;
rootMap = &*map;
}
offset = index + 1;
} while (true);
}
void readSection(const std::string& section, dynamic::Map& map) {
void readSection(const std::string& section, dv::value& map) {
while (hasNext()) {
skipWhitespace();
if (!hasNext()) {
@@ -71,23 +70,23 @@ class TomlReader : BasicParser {
expect('=');
c = peek();
if (is_digit(c)) {
map.put(name, parseNumber(1));
map[name] = parseNumber(1);
} else if (c == '-' || c == '+') {
int sign = c == '-' ? -1 : 1;
pos++;
map.put(name, parseNumber(sign));
map[name] = parseNumber(sign);
} else if (is_identifier_start(c)) {
std::string identifier = parseName();
if (identifier == "true" || identifier == "false") {
map.put(name, identifier == "true");
map[name] = identifier == "true";
} else if (identifier == "inf") {
map.put(name, INFINITY);
map[name] = INFINITY;
} else if (identifier == "nan") {
map.put(name, NAN);
map[name] = NAN;
}
} else if (c == '"' || c == '\'') {
pos++;
map.put(name, parseString(c));
map[name] = parseString(c);
} else {
throw error("feature is not supported");
}
@@ -97,36 +96,28 @@ class TomlReader : BasicParser {
public:
TomlReader(std::string_view file, std::string_view source)
: BasicParser(file, source) {
root = dynamic::create_map();
root = dv::object();
}
dynamic::Map_sptr read() {
dv::value read() {
skipWhitespace();
if (!hasNext()) {
return root;
}
readSection("", *root);
readSection("", root);
return root;
}
};
dynamic::Map_sptr toml::parse(std::string_view file, std::string_view source) {
return TomlReader(file, source).read();
}
void toml::parse(
SettingsHandler& handler, std::string_view file, std::string_view source
) {
auto map = parse(file, source);
for (auto& entry : map->values) {
const auto& sectionName = entry.first;
auto sectionMap = std::get_if<dynamic::Map_sptr>(&entry.second);
if (sectionMap == nullptr) {
for (const auto& [sectionName, sectionMap] : map.asObject()) {
if (!sectionMap.isObject()) {
continue;
}
for (auto& sectionEntry : (*sectionMap)->values) {
const auto& name = sectionEntry.first;
auto& value = sectionEntry.second;
for (const auto& [name, value] : sectionMap.asObject()) {
auto fullname = sectionName + "." + name;
if (handler.has(fullname)) {
handler.setValue(fullname, value);
@@ -135,24 +126,24 @@ void toml::parse(
}
}
std::string toml::stringify(dynamic::Map& root, const std::string& name) {
dv::value toml::parse(std::string_view file, std::string_view source) {
return TomlReader(file, source).read();
}
std::string toml::stringify(const dv::value& root, const std::string& name) {
std::stringstream ss;
if (!name.empty()) {
ss << "[" << name << "]\n";
}
for (auto& entry : root.values) {
if (!std::holds_alternative<dynamic::Map_sptr>(entry.second)) {
ss << entry.first << " = ";
ss << entry.second << "\n";
for (const auto& [key, value] : root.asObject()) {
if (!value.isObject()) {
ss << key << " = " << value << "\n";
}
}
for (auto& entry : root.values) {
if (auto submap = std::get_if<dynamic::Map_sptr>(&entry.second)) {
ss << "\n"
<< toml::stringify(
**submap,
name.empty() ? entry.first : name + "." + entry.first
);
for (const auto& [key, value] : root.asObject()) {
if (value.isObject()) {
ss << "\n" << toml::stringify(value,
name.empty() ? key : name + "." + key);
}
}
return ss.str();
+4 -3
View File
@@ -2,14 +2,15 @@
#include <string>
#include "data/dynamic.hpp"
#include "data/dv.hpp"
class SettingsHandler;
namespace toml {
std::string stringify(SettingsHandler& handler);
std::string stringify(dynamic::Map& root, const std::string& name = "");
dynamic::Map_sptr parse(std::string_view file, std::string_view source);
std::string stringify(const dv::value& root, const std::string& name = "");
dv::value parse(std::string_view file, std::string_view source);
void parse(
SettingsHandler& handler, std::string_view file, std::string_view source