Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // не рабочий пока вариант , с ошибками
- #include <cassert>
- #include <cmath>
- #include <stdexcept>
- #include <sstream>
- #include <stack>
- #include <string>
- #include <optional>
- #include <memory>
- #include <unordered_map>
- #include <variant>
- #include "test_runner.h"
- using namespace std;
- void PrintJsonString(std::ostream &out, std::string_view str)
- {
- string str_formatted(str);
- for(size_t i = 0; i < str_formatted.length(); i++)
- {
- if(str[i] == '"' || str[i] == '\\')
- {
- str = str_formatted.insert(i,"\\");
- i++;
- }
- }
- out << str_formatted;
- }
- class NoneContext
- {
- public:
- NoneContext(ostream& out,
- bool render_start_symbol = true,
- bool render_stop_symbol = true,
- bool render_null_value = true){};
- };
- template<typename Ancestor>
- class ArrayContext;
- template<typename Ancestor>
- class ObjectKeyContext;
- template<typename Ancestor>
- class ObjectValueContext;
- class AbstractContext
- {
- public:
- AbstractContext(ostream& out,
- bool render_start_symbol = true,
- bool render_stop_symbol = true,
- bool render_null_value = true) :
- out_(out),
- render_start_symbol_(render_start_symbol),
- render_stop_symbol_(render_stop_symbol),
- render_null_value_(render_null_value){}
- void WriteNumber(int64_t);
- void WriteString(std::string_view);
- void WriteBoolean(bool);
- void WriteNull();
- protected:
- void InsertDelimeter_();
- ostream& out_;
- bool render_start_symbol_;
- bool render_stop_symbol_;
- bool render_null_value_;
- };
- template<typename Ancestor>
- class ArrayContext : public AbstractContext
- {
- public:
- ArrayContext(std::ostream &out,
- bool render_start_symbol = true,
- bool render_stop_symbol = true,
- bool render_null_value = true);
- ~ArrayContext();
- ArrayContext<Ancestor>& Number(int64_t);
- ArrayContext<Ancestor>& String(std::string_view);
- ArrayContext<Ancestor>& Boolean(bool);
- ArrayContext<Ancestor>& Null();
- ArrayContext<ArrayContext<Ancestor>> BeginArray();
- Ancestor EndArray();
- ObjectKeyContext<ArrayContext<Ancestor>> BeginObject();
- };
- ArrayContext<NoneContext> PrintJsonArray(std::ostream &out)
- {
- return ArrayContext<NoneContext>(out);
- }
- template<typename Ancestor>
- ArrayContext<Ancestor>::ArrayContext(std::ostream &out,
- bool render_start_symbol,
- bool render_stop_symbol,
- bool render_null_value)
- : AbstractContext
- (out,
- render_start_symbol,
- render_stop_symbol,
- render_null_value)
- {
- if(this->render_start_symbol_)
- this->out_ << "[";
- }
- template<typename Ancestor>
- ArrayContext<Ancestor>::~ArrayContext()
- {
- if(this->render_stop_symbol_)
- this->out_ << "]";
- }
- template<typename Ancestor>
- ArrayContext<Ancestor>& ArrayContext<Ancestor>::Number(int64_t value)
- {
- this->WriteNumber(value);
- return *this;
- }
- template<typename Ancestor>
- ArrayContext<Ancestor>& ArrayContext<Ancestor>::String(string_view value)
- {
- this->WriteString(value);
- return *this;
- }
- template<typename Ancestor>
- ArrayContext<Ancestor>& ArrayContext<Ancestor>::Boolean(bool value)
- {
- this->WriteBoolean(value);
- return *this;
- }
- template<typename Ancestor>
- ArrayContext<Ancestor>& ArrayContext<Ancestor>::Null()
- {
- this->WriteNull();
- return *this;
- }
- void AbstractContext::WriteNumber(int64_t number)
- {
- InsertDelimeter_();
- out_ << number;
- }
- void AbstractContext::WriteString(std::string_view str)
- {
- InsertDelimeter_();
- out_ << '"';
- PrintJsonString(out_, str);
- out_ << '"';
- }
- void AbstractContext::WriteBoolean(bool value)
- {
- InsertDelimeter_();
- value ? out_ << "true" : out_ << "false";
- }
- void AbstractContext::WriteNull()
- {
- InsertDelimeter_();
- out_ << "null";
- }
- void AbstractContext::InsertDelimeter_()
- {
- if(this->render_start_symbol_)
- {
- this->render_start_symbol_ = false;
- }
- else
- {
- this->out_ << ',';
- }
- }
- template <typename Ancestor>
- ArrayContext<ArrayContext<Ancestor>> ArrayContext<Ancestor>::BeginArray()
- {
- InsertDelimeter_();
- return ArrayContext<ArrayContext<Ancestor>>(out_);
- }
- template <typename Ancestor>
- Ancestor ArrayContext<Ancestor>::EndArray()
- {
- if(render_stop_symbol_)
- out_ << ']';
- render_stop_symbol_ = false;
- return Ancestor(out_, false, false, false);
- }
- template <typename Ancestor>
- ObjectKeyContext<ArrayContext<Ancestor>> ArrayContext<Ancestor>::BeginObject()
- {
- InsertDelimeter_();
- return ObjectKeyContext<ArrayContext<Ancestor>>(out_);
- }
- template<typename Ancestor>
- class ObjectKeyContext : public AbstractContext
- {
- public:
- ObjectKeyContext(std::ostream &out,
- bool render_start_symbol = true,
- bool render_stop_symbol = true,
- bool render_null_value = true);
- ~ObjectKeyContext();
- Ancestor EndObject();
- ObjectValueContext<Ancestor> Key(std::string_view key);
- };
- ObjectKeyContext<NoneContext> PrintJsonObject(std::ostream &out)
- {
- return ObjectKeyContext<NoneContext>(out);
- }
- template<typename Ancestor>
- ObjectKeyContext<Ancestor>::ObjectKeyContext(std::ostream &out,
- bool render_start_symbol,
- bool render_stop_symbol,
- bool render_null_value)
- : AbstractContext
- (out,
- render_start_symbol,
- render_stop_symbol,
- render_null_value)
- {
- if(this->render_start_symbol_)
- this->out_ << "{";
- }
- template<typename Ancestor>
- ObjectValueContext<Ancestor> ObjectKeyContext<Ancestor>::Key(std::string_view key)
- {
- this->InsertDelimeter_();
- this->out_ << '"';
- PrintJsonString(this->out_, key);
- this->out_ << '"';
- return ObjectValueContext<Ancestor>(this->out_);
- }
- template<typename Ancestor>
- ObjectKeyContext<Ancestor>::~ObjectKeyContext()
- {
- if(!this->render_stop_symbol_ && this->render_null_value_)
- this->out_ << "null}";
- if(this->render_stop_symbol_)
- this->out_ << "}";
- }
- template <typename Ancestor>
- Ancestor ObjectKeyContext<Ancestor>::EndObject()
- {
- this->render_stop_symbol_ = false;
- this->render_null_value_ = false;
- return Ancestor(out_, false, false, false);
- }
- template<typename Ancestor>
- class ObjectValueContext : public AbstractContext
- {
- public:
- ObjectValueContext(std::ostream &out,
- bool render_start_symbol = true,
- bool render_stop_symbol = true,
- bool render_null_value = true);
- ~ObjectValueContext();
- ObjectKeyContext<Ancestor> Number(int64_t);
- ObjectKeyContext<Ancestor> String(std::string_view);
- ObjectKeyContext<Ancestor> Boolean(bool);
- ObjectKeyContext<Ancestor> Null();
- ArrayContext<ObjectKeyContext<Ancestor>> BeginArray();
- ObjectKeyContext<ObjectKeyContext<Ancestor>> BeginObject();
- };
- template<typename Ancestor>
- ObjectValueContext<Ancestor>::ObjectValueContext(std::ostream &out,
- bool render_start_symbol,
- bool render_stop_symbol,
- bool render_null_value)
- : AbstractContext
- (out,
- render_start_symbol,
- render_stop_symbol,
- render_null_value)
- {
- if(this->render_start_symbol_)
- this->out_ << ":";
- }
- template<typename Ancestor>
- ObjectValueContext<Ancestor>::~ObjectValueContext()
- {
- }
- template<typename Ancestor>
- ObjectKeyContext<Ancestor> ObjectValueContext<Ancestor>::Number(int64_t value)
- {
- this->WriteNumber(value);
- return ObjectKeyContext<Ancestor>(this->out_, false, false, false);
- }
- template<typename Ancestor>
- ObjectKeyContext<Ancestor> ObjectValueContext<Ancestor>::String(string_view value)
- {
- this->WriteString(value);
- return ObjectKeyContext<Ancestor>(this->out_, false, false, false);
- }
- template<typename Ancestor>
- ObjectKeyContext<Ancestor> ObjectValueContext<Ancestor>::Boolean(bool value)
- {
- this->WriteBoolean(value);
- return ObjectKeyContext<Ancestor>(this->out_, false, false, false);
- }
- template<typename Ancestor>
- ObjectKeyContext<Ancestor> ObjectValueContext<Ancestor>::Null()
- {
- this->WriteNull();
- return ObjectKeyContext<Ancestor>(this->out_, false, false, false);
- }
- template <typename Ancestor>
- ArrayContext<ObjectKeyContext<Ancestor>> ObjectValueContext<Ancestor>::BeginArray()
- {
- InsertDelimeter_();
- return ArrayContext<ObjectKeyContext<Ancestor>>(out_);
- }
- template <typename Ancestor>
- ObjectKeyContext<ObjectKeyContext<Ancestor>> ObjectValueContext<Ancestor>::BeginObject()
- {
- InsertDelimeter_();
- return ObjectKeyContext<ObjectKeyContext<Ancestor>>(out_, true, false);
- }
- //------------------------------------------- TESTING SECTION -------------------------------------------//
- void TestPrintJsonString()
- {
- std::ostringstream output;
- PrintJsonString(output, "Hello, \"world\"");
- ASSERT_EQUAL(output.str(), "Hello, \\\"world\\\"");
- }
- void TestArray()
- {
- std::ostringstream output;
- {
- auto json = PrintJsonArray(output);
- json
- .Number(5)
- .Number(6)
- .BeginArray()
- .Number(7)
- .EndArray()
- .Number(8)
- .String("bingo!")
- .EndArray();
- }
- ASSERT_EQUAL(output.str(), R"([5,6,[7],8,"bingo!"])");
- }
- void TestArrayWOEnd()
- {
- std::ostringstream output;
- {
- auto json = PrintJsonArray(output);
- json
- .Number(5)
- .Number(6)
- .BeginArray()
- .Number(7);
- }
- ASSERT_EQUAL(output.str(), R"([5,6,[7]])");
- }
- void TestObject()
- {
- std::ostringstream output;
- {
- auto json = PrintJsonObject(output);
- json
- .Key("id1")
- .Number(1234)
- .Key("id2")
- .Boolean(false)
- .Key("")
- .Null()
- .Key("\"")
- .String("\\");
- }
- ASSERT_EQUAL(output.str(), R"({"id1":1234,"id2":false,"":null,"\"":"\\"})");
- }
- void TestAutoClose()
- {
- std::ostringstream output;
- {
- auto json = PrintJsonArray(output);
- json.BeginArray().BeginObject();
- }
- ASSERT_EQUAL(output.str(), R"([[{}]])");
- }
- void TetsEx1()
- {
- std::ostringstream output;
- {
- auto json = PrintJsonArray(output);
- json
- .Null()
- .String("Hello")
- .Number(123)
- .Boolean(false)
- .EndArray();
- }
- ASSERT_EQUAL(output.str(), R"([null,"Hello",123,false])");
- }
- void TetsEx2()
- {
- std::ostringstream output;
- {
- auto json = PrintJsonArray(output);
- json
- .String("Hello")
- .BeginArray()
- .String("World");
- }
- ASSERT_EQUAL(output.str(), R"(["Hello",["World"]])");
- }
- void TetsEx3()
- {
- std::ostringstream output;
- {
- auto json = PrintJsonObject(output);
- json
- .Key("foo")
- .BeginArray()
- .String("Hello")
- .EndArray()
- .Key("foo") // повторяющиеся ключи допускаются
- .BeginObject()
- .Key("foo");
- }
- ASSERT_EQUAL(output.str(), R"({"foo":["Hello"],"foo":{"foo":null}})");
- }
- void TestEndObject_1()
- {
- std::ostringstream output;
- {
- auto json = PrintJsonArray(output);
- json
- .BeginObject()
- .Key("as")
- .Null()
- .EndObject()
- .BeginObject();
- }
- ASSERT_EQUAL(output.str(), R"([{"as":null,{}}])");
- }
- void TestEndObject_2()
- {
- std::ostringstream output;
- {
- auto json = PrintJsonArray(output);
- json
- .BeginObject()
- .Key("as")
- .BeginObject()
- .EndObject()
- .Key("as")
- .Null()
- .EndObject()
- .BeginObject();
- }
- ASSERT_EQUAL(output.str(), R"([{"as":null,{}}])");
- }
- int main()
- {
- TestRunner tr;
- RUN_TEST(tr, TestPrintJsonString);
- RUN_TEST(tr, TestArray);
- RUN_TEST(tr, TestArrayWOEnd);
- RUN_TEST(tr, TestObject);
- RUN_TEST(tr, TestAutoClose);
- RUN_TEST(tr, TetsEx1);
- RUN_TEST(tr, TetsEx2);
- RUN_TEST(tr, TetsEx3);
- RUN_TEST(tr, TestEndObject_1);
- PrintJsonArray(std::cout)
- .Null()
- .String("Hello")
- .Number(123)
- .Boolean(false)
- .BeginObject()
- .Key("A")
- .BeginArray()
- .Null()
- .String("Hello")
- .Number(123)
- .EndArray();
- return 0;
- }
Add Comment
Please, Sign In to add comment