--- /dev/null
+/*
+ * 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 <vist/json/value.hpp>
+
+#include <string>
+#include <vector>
+
+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 <typename Type>
+ void push(const Type& data)
+ {
+ auto value = std::make_shared<Value>();
+ *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<std::shared_ptr<Value>> buffer;
+};
+
+} // namespace json
+} // namespace vist
* - 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:
#pragma once
-#include <vist/json/value.hpp>
+#include <vist/json/array.hpp>
#include <vist/json/object.hpp>
+#include <vist/json/value.hpp>
#include <sstream>
#include <stdexcept>
return this->root.serialize();
}
- void push(const std::string& key, Json& child)
+ template <typename CompositeType>
+ void push(const std::string& key, CompositeType& child)
+ {
+ auto composite = std::make_shared<CompositeType>();
+ if constexpr (std::is_same_v<CompositeType, Array>)
+ composite->buffer = std::move(child.buffer);
+ else if constexpr (std::is_same_v<CompositeType, Object>)
+ composite->pairs = std::move(child.pairs);
+ else
+ static_assert(dependent_false<CompositeType>::value, "Only Composite type supported.");
+
+ this->root.pairs[key] = composite;
+ }
+
+ void push(const std::string& key, Array& child)
{
- auto object = std::make_shared<Object>();
- object->pairs = std::move(child.root.pairs);
- this->root.pairs[key] = object;
+ auto array = std::make_shared<Array>();
+ array->buffer = std::move(child.buffer);
+ this->root.pairs[key] = array;
}
- Json pop(const std::string& key)
+ template <typename CompositeType>
+ 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<Object>(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<CompositeType, Array> ||
+ std::is_same_v<CompositeType, Object>) {
+ if (auto downcast = std::dynamic_pointer_cast<CompositeType>(this->root.pairs[key]);
+ downcast == nullptr)
+ throw std::runtime_error("Mismatched type.");
+ else
+ return *downcast;
+ } else {
+ static_assert(dependent_false<CompositeType>::value, "Only Composite type supported.");
}
}
return ss.str();
}
+ template <typename Type>
+ void push(const std::string& key, const Type& data)
+ {
+ auto value = std::make_shared<Value>();
+ *value = data;
+ this->pairs[key] = std::move(value);
+ }
+
Value& operator[](const char* key)
{
if (!this->exist(key))
}
}
-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<int>(array.at(0)), 100);
+ EXPECT_EQ(static_cast<std::string>(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>("array");
+ EXPECT_EQ(json.size(), 1);
EXPECT_EQ(result.size(), 2);
+ EXPECT_EQ(static_cast<int>(result.at(0)), 100);
+ EXPECT_EQ(static_cast<std::string>(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<int>(object["int"]), 1);
+ EXPECT_EQ(static_cast<std::string>(object["string"]), "initial value");
+
+ Json json;
+ json.push("object", object);
+ EXPECT_EQ(json.size(), 1);
+
+ auto result = json.get<Object>("object");
EXPECT_EQ(static_cast<int>(result["int"]), 1);
EXPECT_EQ(static_cast<std::string>(result["string"]), "initial value");
}
// 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);