dynamic::Value simplified

This commit is contained in:
MihailRis
2024-05-07 18:39:12 +03:00
parent 8e83a07094
commit a4c21984d5
26 changed files with 230 additions and 297 deletions
+26 -41
View File
@@ -9,24 +9,24 @@
using namespace json;
using namespace dynamic;
static void to_binary(ByteBuilder& builder, const Value* value) {
switch (static_cast<valtype>(value->value.index())) {
static void to_binary(ByteBuilder& builder, const Value& value) {
switch (static_cast<valtype>(value.index())) {
case valtype::none:
throw std::runtime_error("none value is not implemented");
case valtype::map: {
std::vector<ubyte> bytes = to_binary(std::get<Map*>(value->value));
auto bytes = to_binary(std::get<Map_sptr>(value).get());
builder.put(bytes.data(), bytes.size());
break;
}
case valtype::list:
builder.put(BJSON_TYPE_LIST);
for (auto& element : std::get<List*>(value->value)->values) {
to_binary(builder, element.get());
for (auto& element : std::get<List_sptr>(value)->values) {
to_binary(builder, element);
}
builder.put(BJSON_END);
break;
case valtype::integer: {
auto val = std::get<integer_t>(value->value);
auto val = std::get<integer_t>(value);
if (val >= 0 && val <= 255) {
builder.put(BJSON_TYPE_BYTE);
builder.put(val);
@@ -44,14 +44,14 @@ static void to_binary(ByteBuilder& builder, const Value* value) {
}
case valtype::number:
builder.put(BJSON_TYPE_NUMBER);
builder.putFloat64(std::get<number_t>(value->value));
builder.putFloat64(std::get<number_t>(value));
break;
case valtype::boolean:
builder.put(BJSON_TYPE_FALSE + std::get<bool>(value->value));
builder.put(BJSON_TYPE_FALSE + std::get<bool>(value));
break;
case valtype::string:
builder.put(BJSON_TYPE_STRING);
builder.put(std::get<std::string>(value->value));
builder.put(std::get<std::string>(value));
break;
}
}
@@ -73,7 +73,7 @@ std::vector<ubyte> json::to_binary(const Map* obj, bool compress) {
// writing entries
for (auto& entry : obj->values) {
builder.putCStr(entry.first.c_str());
to_binary(builder, entry.second.get());
to_binary(builder, entry.second);
}
// terminating byte
builder.put(BJSON_END);
@@ -83,52 +83,40 @@ std::vector<ubyte> json::to_binary(const Map* obj, bool compress) {
return builder.build();
}
static std::unique_ptr<Value> value_from_binary(ByteReader& reader) {
static Value value_from_binary(ByteReader& reader) {
ubyte typecode = reader.get();
valvalue val;
switch (typecode) {
case BJSON_TYPE_DOCUMENT:
reader.getInt32();
val = object_from_binary(reader).release();
break;
return Map_sptr(object_from_binary(reader).release());
case BJSON_TYPE_LIST:
val = array_from_binary(reader).release();
break;
return List_sptr(array_from_binary(reader).release());
case BJSON_TYPE_BYTE:
val = static_cast<integer_t>(reader.get());
break;
return static_cast<integer_t>(reader.get());
case BJSON_TYPE_INT16:
val = static_cast<integer_t>(reader.getInt16());
break;
return static_cast<integer_t>(reader.getInt16());
case BJSON_TYPE_INT32:
val = static_cast<integer_t>(reader.getInt32());
break;
return static_cast<integer_t>(reader.getInt32());
case BJSON_TYPE_INT64:
val = reader.getInt64();
break;
return reader.getInt64();
case BJSON_TYPE_NUMBER:
val = reader.getFloat64();
break;
return reader.getFloat64();
case BJSON_TYPE_FALSE:
case BJSON_TYPE_TRUE:
val = (typecode - BJSON_TYPE_FALSE) != 0;
break;
return (typecode - BJSON_TYPE_FALSE) != 0;
case BJSON_TYPE_STRING:
val = reader.getString();
break;
return reader.getString();
default:
throw std::runtime_error(
"type "+std::to_string(typecode)+" is not supported"
);
}
return std::make_unique<Value>(val);
}
static std::unique_ptr<List> array_from_binary(ByteReader& reader) {
auto array = std::make_unique<List>();
auto& items = array->values;
while (reader.peek() != BJSON_END) {
items.push_back(value_from_binary(reader));
array->put(value_from_binary(reader));
}
reader.get();
return array;
@@ -136,16 +124,15 @@ static std::unique_ptr<List> array_from_binary(ByteReader& reader) {
static std::unique_ptr<Map> object_from_binary(ByteReader& reader) {
auto obj = std::make_unique<Map>();
auto& map = obj->values;
while (reader.peek() != BJSON_END) {
const char* key = reader.getCString();
map.insert(std::make_pair(key, value_from_binary(reader)));
obj->put(key, value_from_binary(reader));
}
reader.get();
return obj;
}
std::unique_ptr<Map> json::from_binary(const ubyte* src, size_t size) {
std::shared_ptr<Map> json::from_binary(const ubyte* src, size_t size) {
if (size < 2) {
throw std::runtime_error("bytes length is less than 2");
}
@@ -155,12 +142,10 @@ std::unique_ptr<Map> json::from_binary(const ubyte* src, size_t size) {
return from_binary(data.data(), data.size());
} else {
ByteReader reader(src, size);
std::unique_ptr<Value> value (value_from_binary(reader));
Value value = value_from_binary(reader);
if (Map* const* map = std::get_if<Map*>(&value->value)) {
std::unique_ptr<Map> obj (*map);
value->value = (Map*)nullptr;
return obj;
if (auto map = std::get_if<Map_sptr>(&value)) {
return *map;
} else {
throw std::runtime_error("root value is not an object");
}
+1 -1
View File
@@ -27,7 +27,7 @@ namespace json {
const int BJSON_TYPE_CDOCUMENT = 0x1F;
extern std::vector<ubyte> to_binary(const dynamic::Map* obj, bool compress=false);
extern std::unique_ptr<dynamic::Map> from_binary(const ubyte* src, size_t size);
extern std::shared_ptr<dynamic::Map> from_binary(const ubyte* src, size_t size);
}
#endif // CODERS_BINARY_JSON_HPP_
+23 -29
View File
@@ -27,7 +27,7 @@ inline void newline(
}
void stringify(
const Value* value,
const Value& value,
std::stringstream& ss,
int indent,
const std::string& indentstr,
@@ -43,16 +43,16 @@ void stringifyObj(
);
void stringify(
const Value* value,
const Value& value,
std::stringstream& ss,
int indent,
const std::string& indentstr,
bool nice
) {
if (auto map = std::get_if<Map*>(&value->value)) {
stringifyObj(*map, ss, indent, indentstr, 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*>(&value->value)) {
else if (auto listptr = std::get_if<List_sptr>(&value)) {
auto list = *listptr;
if (list->size() == 0) {
ss << "[]";
@@ -60,7 +60,7 @@ void stringify(
}
ss << '[';
for (uint i = 0; i < list->size(); i++) {
Value* value = list->get(i);
Value& value = list->get(i);
if (i > 0 || nice) {
newline(ss, nice, indent, indentstr);
}
@@ -73,13 +73,13 @@ void stringify(
newline(ss, true, indent - 1, indentstr);
}
ss << ']';
} else if (auto flag = std::get_if<bool>(&value->value)) {
} else if (auto flag = std::get_if<bool>(&value)) {
ss << (*flag ? "true" : "false");
} else if (auto num = std::get_if<number_t>(&value->value)) {
} 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->value)) {
} else if (auto num = std::get_if<integer_t>(&value)) {
ss << *num;
} else if (auto str = std::get_if<std::string>(&value->value)) {
} else if (auto str = std::get_if<std::string>(&value)) {
ss << util::escape(*str);
}
}
@@ -102,7 +102,7 @@ void stringifyObj(
if (index > 0 || nice) {
newline(ss, nice, indent, indentstr);
}
Value* value = entry.second.get();
const Value& value = entry.second;
ss << util::escape(key) << ": ";
stringify(value, ss, indent+1, indentstr, nice);
index++;
@@ -191,53 +191,47 @@ std::unique_ptr<List> Parser::parseList() {
return arr;
}
std::unique_ptr<Value> Parser::parseValue() {
Value Parser::parseValue() {
char next = peek();
dynamic::valvalue val;
if (next == '-' || next == '+') {
pos++;
number_u num;
if (parseNumber(next == '-' ? -1 : 1, num)) {
val = std::get<integer_t>(num);
return std::get<integer_t>(num);
} else {
val = std::get<number_t>(num);
return std::get<number_t>(num);
}
return std::make_unique<Value>(val);
}
if (is_identifier_start(next)) {
std::string literal = parseName();
if (literal == "true") {
return dynamic::value_of(true);
return true;
} else if (literal == "false") {
return dynamic::value_of(false);
return false;
} else if (literal == "inf") {
return dynamic::value_of(INFINITY);
return INFINITY;
} else if (literal == "nan") {
return dynamic::value_of(NAN);
return NAN;
}
throw error("invalid literal ");
}
if (next == '{') {
val = parseObject().release();
return std::make_unique<Value>(val);
return Map_sptr(parseObject().release());
}
if (next == '[') {
val = parseList().release();
return std::make_unique<Value>(val);
return List_sptr(parseList().release());
}
if (is_digit(next)) {
number_u num;
if (parseNumber(1, num)) {
val = std::get<integer_t>(num);
return std::get<integer_t>(num);
} else {
val = std::get<number_t>(num);
return std::get<number_t>(num);
}
return std::make_unique<Value>(val);
}
if (next == '"' || next == '\'') {
pos++;
val = parseString(next);
return std::make_unique<Value>(val);
return parseString(next);
}
throw error("unexpected character '"+std::string({next})+"'");
}
+2 -7
View File
@@ -4,6 +4,7 @@
#include "commons.hpp"
#include "binary_json.hpp"
#include "../data/dynamic.hpp"
#include "../typedefs.hpp"
#include <vector>
@@ -12,17 +13,11 @@
#include <stdexcept>
#include <unordered_map>
namespace dynamic {
class Map;
class List;
class Value;
}
namespace json {
class Parser : public BasicParser {
std::unique_ptr<dynamic::List> parseList();
std::unique_ptr<dynamic::Map> parseObject();
std::unique_ptr<dynamic::Value> parseValue();
dynamic::Value parseValue();
public:
Parser(const std::string& filename, const std::string& source);