From f00cd8919781c3c4b17690940b8aeb4fd56a97a5 Mon Sep 17 00:00:00 2001 From: Sangwan Kwon Date: Tue, 12 May 2020 17:26:43 +0900 Subject: [PATCH] Add Array type to JSON Signed-off-by: Sangwan Kwon --- src/vist/json/array.hpp | 80 ++++++++++++++++++++++++++++++++++++ src/vist/json/json.hpp | 47 ++++++++++++++------- src/vist/json/object.hpp | 8 ++++ src/vist/json/tests/json.cpp | 46 +++++++++++++++++---- 4 files changed, 157 insertions(+), 24 deletions(-) create mode 100644 src/vist/json/array.hpp diff --git a/src/vist/json/array.hpp b/src/vist/json/array.hpp new file mode 100644 index 0000000..7f7083a --- /dev/null +++ b/src/vist/json/array.hpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the language governing permissions and + * limitations under the License + */ + +#pragma once + +#include + +#include +#include + +namespace vist { +namespace json { + +struct Array : public Value { + std::size_t size() const noexcept + { + return this->buffer.size(); + } + + std::string serialize() const override + { + std::stringstream ss; + ss << "[ "; + + std::size_t i = 0; + for (const auto& value : buffer) { + ss << value->serialize(); + + if (i++ < buffer.size() - 1) + ss << ","; + + ss << " "; + } + ss << "]"; + + return ss.str(); + } + + template + void push(const Type& data) + { + auto value = std::make_shared(); + *value = data; + this->buffer.emplace_back(std::move(value)); + } + + Value& at(std::size_t index) + { + if (index > this->size()) + throw std::invalid_argument("Wrong index."); + + return *(this->buffer[index]); + } + + Value& operator[](std::size_t index) + { + if (index > this->size()) + throw std::invalid_argument("Wrong index."); + + return *(this->buffer[index]); + } + + std::vector> buffer; +}; + +} // namespace json +} // namespace vist diff --git a/src/vist/json/json.hpp b/src/vist/json/json.hpp index 74e3552..7e1990d 100644 --- a/src/vist/json/json.hpp +++ b/src/vist/json/json.hpp @@ -18,7 +18,7 @@ * - Applied design pattern: Composite pattern * - Component structure: Value * - Leaf structure: Int, String (To be added: Bool, Null) - * - Composite structure: Object (To be added: Array) + * - Composite structure: Array, Object */ /* * Usage: @@ -37,8 +37,9 @@ #pragma once -#include +#include #include +#include #include #include @@ -72,26 +73,42 @@ struct Json { return this->root.serialize(); } - void push(const std::string& key, Json& child) + template + void push(const std::string& key, CompositeType& child) + { + auto composite = std::make_shared(); + if constexpr (std::is_same_v) + composite->buffer = std::move(child.buffer); + else if constexpr (std::is_same_v) + composite->pairs = std::move(child.pairs); + else + static_assert(dependent_false::value, "Only Composite type supported."); + + this->root.pairs[key] = composite; + } + + void push(const std::string& key, Array& child) { - auto object = std::make_shared(); - object->pairs = std::move(child.root.pairs); - this->root.pairs[key] = object; + auto array = std::make_shared(); + array->buffer = std::move(child.buffer); + this->root.pairs[key] = array; } - Json pop(const std::string& key) + template + CompositeType& get(const std::string& key) { if (!this->root.exist(key)) throw std::runtime_error("Not exist key."); - if (auto downcast = std::dynamic_pointer_cast(this->root.pairs[key]); - downcast == nullptr) - throw std::runtime_error("Mismatched type."); - else { - Json json; - json.root.pairs = std::move(downcast->pairs); - this->root.pairs.erase(key); - return json; + if constexpr (std::is_same_v || + std::is_same_v) { + if (auto downcast = std::dynamic_pointer_cast(this->root.pairs[key]); + downcast == nullptr) + throw std::runtime_error("Mismatched type."); + else + return *downcast; + } else { + static_assert(dependent_false::value, "Only Composite type supported."); } } diff --git a/src/vist/json/object.hpp b/src/vist/json/object.hpp index f6c01c9..8542147 100644 --- a/src/vist/json/object.hpp +++ b/src/vist/json/object.hpp @@ -55,6 +55,14 @@ struct Object : public Value { return ss.str(); } + template + void push(const std::string& key, const Type& data) + { + auto value = std::make_shared(); + *value = data; + this->pairs[key] = std::move(value); + } + Value& operator[](const char* key) { if (!this->exist(key)) diff --git a/src/vist/json/tests/json.cpp b/src/vist/json/tests/json.cpp index e6821dc..6b120e0 100644 --- a/src/vist/json/tests/json.cpp +++ b/src/vist/json/tests/json.cpp @@ -79,19 +79,47 @@ TEST(JsonTests, string_type_mismatch) } } -TEST(JsonTests, object) +TEST(JsonTests, array) { - Json root, child; - child["int"] = 1; - child["string"] = "initial value"; + Array array; + array.push(100); + array.push("string"); + + EXPECT_EQ(array.size(), 2); + EXPECT_EQ(array.serialize(), "[ 100, \"string\" ]"); - root.push("child", child); - EXPECT_EQ(root.size(), 1); + EXPECT_EQ(static_cast(array.at(0)), 100); + EXPECT_EQ(static_cast(array.at(1)), "string"); + + Json json; + json.push("array", array); + EXPECT_EQ(json.size(), 1); - auto result = root.pop("child"); - EXPECT_EQ(root.size(), 0); + auto& result = json.get("array"); + EXPECT_EQ(json.size(), 1); EXPECT_EQ(result.size(), 2); + EXPECT_EQ(static_cast(result.at(0)), 100); + EXPECT_EQ(static_cast(result.at(1)), "string"); +} + +TEST(JsonTests, object) +{ + Object object; + object["int"] = 1; + object["string"] = "initial value"; + + EXPECT_EQ(object.size(), 2); + EXPECT_EQ(object.serialize(), "{ \"string\": \"initial value\", \"int\": 1 }"); + + EXPECT_EQ(static_cast(object["int"]), 1); + EXPECT_EQ(static_cast(object["string"]), "initial value"); + + Json json; + json.push("object", object); + EXPECT_EQ(json.size(), 1); + + auto result = json.get("object"); EXPECT_EQ(static_cast(result["int"]), 1); EXPECT_EQ(static_cast(result["string"]), "initial value"); } @@ -104,7 +132,7 @@ TEST(JsonTests, serialize) // expected: { "string": "root value", "int": 1 } EXPECT_EQ(json.serialize(), "{ \"string\": \"root value\", \"int\": 1 }"); - Json child; + Object child; child["int"] = 2; child["string"] = "child value"; json.push("child", child); -- 2.34.1