eikhner

JSON_black_belt

Aug 25th, 2019
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // не рабочий пока вариант , с ошибками
  2. #include <cassert>
  3. #include <cmath>
  4. #include <stdexcept>
  5. #include <sstream>
  6. #include <stack>
  7. #include <string>
  8. #include <optional>
  9. #include <memory>
  10. #include <unordered_map>
  11. #include <variant>
  12.  
  13. #include "test_runner.h"
  14.  
  15. using namespace std;
  16.  
  17. void PrintJsonString(std::ostream &out, std::string_view str)
  18. {
  19.   string str_formatted(str);
  20.   for(size_t i = 0; i < str_formatted.length(); i++)
  21.   {
  22.     if(str[i] == '"' || str[i] == '\\')
  23.     {
  24.         str = str_formatted.insert(i,"\\");
  25.         i++;        
  26.     }    
  27.   }
  28.   out << str_formatted;
  29. }
  30.  
  31. class NoneContext
  32. {
  33.   public:
  34.   NoneContext(ostream& out,
  35.               bool render_start_symbol = true,
  36.               bool render_stop_symbol = true,
  37.               bool render_null_value = true){};
  38. };
  39.  
  40. template<typename Ancestor>
  41. class ArrayContext;
  42.  
  43. template<typename Ancestor>
  44. class ObjectKeyContext;
  45.  
  46. template<typename Ancestor>
  47. class ObjectValueContext;
  48.  
  49. class AbstractContext
  50. {
  51.   public:
  52.     AbstractContext(ostream& out,
  53.                     bool render_start_symbol = true,
  54.                     bool render_stop_symbol = true,
  55.                     bool render_null_value = true) :
  56.                     out_(out),
  57.                     render_start_symbol_(render_start_symbol),
  58.                     render_stop_symbol_(render_stop_symbol),
  59.                     render_null_value_(render_null_value){}
  60.        
  61.     void WriteNumber(int64_t);
  62.     void WriteString(std::string_view);
  63.     void WriteBoolean(bool);
  64.     void WriteNull();
  65.  
  66.   protected:
  67.     void InsertDelimeter_();
  68.     ostream& out_;
  69.     bool render_start_symbol_;
  70.     bool render_stop_symbol_;
  71.     bool render_null_value_;
  72.  
  73. };
  74.  
  75. template<typename Ancestor>
  76. class ArrayContext : public AbstractContext
  77. {
  78.   public:
  79.     ArrayContext(std::ostream &out,
  80.                  bool render_start_symbol = true,
  81.                  bool render_stop_symbol = true,
  82.                  bool render_null_value = true);
  83.     ~ArrayContext();
  84.  
  85.     ArrayContext<Ancestor>& Number(int64_t);
  86.     ArrayContext<Ancestor>& String(std::string_view);
  87.     ArrayContext<Ancestor>& Boolean(bool);
  88.     ArrayContext<Ancestor>& Null();
  89.    
  90.     ArrayContext<ArrayContext<Ancestor>> BeginArray();
  91.     Ancestor EndArray();
  92.     ObjectKeyContext<ArrayContext<Ancestor>> BeginObject();
  93.  
  94. };
  95.  
  96. ArrayContext<NoneContext> PrintJsonArray(std::ostream &out)
  97. {
  98.   return ArrayContext<NoneContext>(out);
  99. }
  100.  
  101. template<typename Ancestor>
  102. ArrayContext<Ancestor>::ArrayContext(std::ostream &out,
  103.                                      bool render_start_symbol,
  104.                                      bool render_stop_symbol,
  105.                                      bool render_null_value)
  106.                                      : AbstractContext
  107.                                      (out,
  108.                                       render_start_symbol,
  109.                                       render_stop_symbol,
  110.                                       render_null_value)
  111. {
  112.   if(this->render_start_symbol_)
  113.     this->out_ << "[";
  114. }
  115.  
  116. template<typename Ancestor>
  117. ArrayContext<Ancestor>::~ArrayContext()
  118. {
  119.   if(this->render_stop_symbol_)
  120.     this->out_ << "]";
  121. }
  122.  
  123. template<typename Ancestor>
  124. ArrayContext<Ancestor>& ArrayContext<Ancestor>::Number(int64_t value)
  125. {
  126.   this->WriteNumber(value);
  127.   return *this;
  128. }  
  129.  
  130. template<typename Ancestor>
  131. ArrayContext<Ancestor>& ArrayContext<Ancestor>::String(string_view value)
  132. {
  133.   this->WriteString(value);
  134.   return *this;
  135. }
  136.  
  137. template<typename Ancestor>
  138. ArrayContext<Ancestor>& ArrayContext<Ancestor>::Boolean(bool value)
  139. {
  140.   this->WriteBoolean(value);
  141.   return *this;
  142. }
  143.  
  144. template<typename Ancestor>
  145. ArrayContext<Ancestor>& ArrayContext<Ancestor>::Null()
  146. {
  147.   this->WriteNull();
  148.   return *this;
  149. }
  150.  
  151. void AbstractContext::WriteNumber(int64_t number)
  152. {
  153.   InsertDelimeter_();
  154.   out_ << number;
  155. }
  156.  
  157. void AbstractContext::WriteString(std::string_view str)
  158. {
  159.   InsertDelimeter_();
  160.   out_ << '"';
  161.   PrintJsonString(out_, str);
  162.   out_ << '"';
  163. }
  164.  
  165. void AbstractContext::WriteBoolean(bool value)
  166. {
  167.   InsertDelimeter_();
  168.   value ? out_ << "true" : out_ << "false";
  169. }
  170.  
  171. void AbstractContext::WriteNull()
  172. {
  173.   InsertDelimeter_();
  174.   out_ << "null";
  175. }
  176.  
  177. void AbstractContext::InsertDelimeter_()
  178. {
  179.   if(this->render_start_symbol_)
  180.   {
  181.     this->render_start_symbol_ = false;
  182.   }
  183.   else
  184.   {
  185.     this->out_ << ',';
  186.   }
  187. }
  188.  
  189. template <typename Ancestor>
  190. ArrayContext<ArrayContext<Ancestor>> ArrayContext<Ancestor>::BeginArray()
  191. {
  192.   InsertDelimeter_();
  193.   return ArrayContext<ArrayContext<Ancestor>>(out_);
  194. }
  195.  
  196. template <typename Ancestor>
  197. Ancestor ArrayContext<Ancestor>::EndArray()
  198. {
  199.   if(render_stop_symbol_)
  200.     out_ << ']';
  201.   render_stop_symbol_ = false;
  202.   return Ancestor(out_, false, false, false);
  203. }
  204.  
  205. template <typename Ancestor>
  206. ObjectKeyContext<ArrayContext<Ancestor>> ArrayContext<Ancestor>::BeginObject()
  207. {
  208.   InsertDelimeter_();
  209.   return ObjectKeyContext<ArrayContext<Ancestor>>(out_);
  210. }
  211.  
  212. template<typename Ancestor>
  213. class ObjectKeyContext : public AbstractContext
  214. {
  215.   public:
  216.     ObjectKeyContext(std::ostream &out,
  217.                      bool render_start_symbol = true,
  218.                      bool render_stop_symbol = true,
  219.                      bool render_null_value = true);
  220.     ~ObjectKeyContext();
  221.     Ancestor EndObject();
  222.     ObjectValueContext<Ancestor> Key(std::string_view key);
  223. };
  224.  
  225. ObjectKeyContext<NoneContext> PrintJsonObject(std::ostream &out)
  226. {
  227.   return ObjectKeyContext<NoneContext>(out);
  228. }
  229.  
  230. template<typename Ancestor>
  231. ObjectKeyContext<Ancestor>::ObjectKeyContext(std::ostream &out,
  232.                                              bool render_start_symbol,
  233.                                              bool render_stop_symbol,
  234.                                              bool render_null_value)
  235.                                              : AbstractContext
  236.                                              (out,
  237.                                               render_start_symbol,
  238.                                               render_stop_symbol,
  239.                                               render_null_value)
  240. {
  241.   if(this->render_start_symbol_)
  242.     this->out_ << "{";
  243. }
  244.  
  245. template<typename Ancestor>
  246. ObjectValueContext<Ancestor> ObjectKeyContext<Ancestor>::Key(std::string_view key)
  247. {
  248.   this->InsertDelimeter_();
  249.   this->out_ << '"';
  250.   PrintJsonString(this->out_, key);
  251.   this->out_ << '"';
  252.   return ObjectValueContext<Ancestor>(this->out_);
  253. }
  254.  
  255. template<typename Ancestor>
  256. ObjectKeyContext<Ancestor>::~ObjectKeyContext()
  257. {
  258.   if(!this->render_stop_symbol_ && this->render_null_value_)
  259.     this->out_ << "null}";
  260.   if(this->render_stop_symbol_)
  261.     this->out_ << "}";
  262. }
  263.  
  264. template <typename Ancestor>
  265. Ancestor ObjectKeyContext<Ancestor>::EndObject()
  266. {
  267.   this->render_stop_symbol_ = false;
  268.   this->render_null_value_ = false;
  269.   return Ancestor(out_, false, false, false);
  270. }
  271.  
  272. template<typename Ancestor>
  273. class ObjectValueContext : public AbstractContext
  274. {
  275.   public:
  276.     ObjectValueContext(std::ostream &out,
  277.                        bool render_start_symbol = true,
  278.                        bool render_stop_symbol = true,
  279.                        bool render_null_value = true);
  280.  
  281.     ~ObjectValueContext();
  282.     ObjectKeyContext<Ancestor> Number(int64_t);
  283.     ObjectKeyContext<Ancestor> String(std::string_view);
  284.     ObjectKeyContext<Ancestor> Boolean(bool);
  285.     ObjectKeyContext<Ancestor> Null();
  286.  
  287.     ArrayContext<ObjectKeyContext<Ancestor>> BeginArray();
  288.     ObjectKeyContext<ObjectKeyContext<Ancestor>> BeginObject();
  289.  
  290. };
  291.  
  292. template<typename Ancestor>
  293. ObjectValueContext<Ancestor>::ObjectValueContext(std::ostream &out,
  294.                                                  bool render_start_symbol,
  295.                                                  bool render_stop_symbol,
  296.                                                  bool render_null_value)
  297.                                                  : AbstractContext
  298.                                                  (out,
  299.                                                   render_start_symbol,
  300.                                                   render_stop_symbol,
  301.                                                   render_null_value)
  302. {
  303.   if(this->render_start_symbol_)
  304.     this->out_ << ":";
  305. }
  306.  
  307. template<typename Ancestor>
  308. ObjectValueContext<Ancestor>::~ObjectValueContext()
  309. {
  310. }
  311.  
  312. template<typename Ancestor>
  313. ObjectKeyContext<Ancestor> ObjectValueContext<Ancestor>::Number(int64_t value)
  314. {
  315.   this->WriteNumber(value);
  316.   return ObjectKeyContext<Ancestor>(this->out_, false, false, false);
  317. }
  318.  
  319. template<typename Ancestor>
  320. ObjectKeyContext<Ancestor> ObjectValueContext<Ancestor>::String(string_view value)
  321. {
  322.   this->WriteString(value);
  323.   return ObjectKeyContext<Ancestor>(this->out_, false, false, false);
  324. }
  325.  
  326. template<typename Ancestor>
  327. ObjectKeyContext<Ancestor> ObjectValueContext<Ancestor>::Boolean(bool value)
  328. {
  329.   this->WriteBoolean(value);
  330.   return ObjectKeyContext<Ancestor>(this->out_, false, false, false);
  331. }
  332.  
  333. template<typename Ancestor>
  334. ObjectKeyContext<Ancestor> ObjectValueContext<Ancestor>::Null()
  335. {
  336.   this->WriteNull();
  337.   return ObjectKeyContext<Ancestor>(this->out_, false, false, false);
  338. }
  339.  
  340. template <typename Ancestor>
  341. ArrayContext<ObjectKeyContext<Ancestor>> ObjectValueContext<Ancestor>::BeginArray()
  342. {
  343.   InsertDelimeter_();
  344.   return ArrayContext<ObjectKeyContext<Ancestor>>(out_);
  345. }
  346.  
  347. template <typename Ancestor>
  348. ObjectKeyContext<ObjectKeyContext<Ancestor>> ObjectValueContext<Ancestor>::BeginObject()
  349. {
  350.   InsertDelimeter_();
  351.   return ObjectKeyContext<ObjectKeyContext<Ancestor>>(out_, true, false);
  352. }
  353.  
  354. //------------------------------------------- TESTING SECTION -------------------------------------------//
  355.  
  356. void TestPrintJsonString()
  357. {
  358.   std::ostringstream output;
  359.   PrintJsonString(output, "Hello, \"world\"");
  360.   ASSERT_EQUAL(output.str(), "Hello, \\\"world\\\"");
  361. }
  362.  
  363. void TestArray()
  364. {
  365.   std::ostringstream output;
  366.  
  367.   {
  368.     auto json = PrintJsonArray(output);
  369.     json
  370.         .Number(5)
  371.         .Number(6)
  372.         .BeginArray()
  373.           .Number(7)
  374.           .EndArray()
  375.         .Number(8)
  376.         .String("bingo!")
  377.         .EndArray();
  378.   }
  379.  
  380.   ASSERT_EQUAL(output.str(), R"([5,6,[7],8,"bingo!"])");
  381. }
  382.  
  383. void TestArrayWOEnd()
  384. {
  385.   std::ostringstream output;
  386.  
  387.   {
  388.     auto json = PrintJsonArray(output);
  389.     json
  390.         .Number(5)
  391.         .Number(6)
  392.         .BeginArray()
  393.           .Number(7);
  394.   }
  395.  
  396.   ASSERT_EQUAL(output.str(), R"([5,6,[7]])");
  397. }
  398.  
  399. void TestObject()
  400. {
  401.   std::ostringstream output;
  402.  
  403.   {
  404.     auto json = PrintJsonObject(output);
  405.     json
  406.         .Key("id1")
  407.         .Number(1234)
  408.         .Key("id2")
  409.         .Boolean(false)
  410.         .Key("")
  411.         .Null()
  412.         .Key("\"")
  413.         .String("\\");
  414.   }
  415.  
  416.   ASSERT_EQUAL(output.str(), R"({"id1":1234,"id2":false,"":null,"\"":"\\"})");
  417. }
  418.  
  419. void TestAutoClose()
  420. {
  421.  std::ostringstream output;
  422.  
  423.  {
  424.    auto json = PrintJsonArray(output);
  425.    json.BeginArray().BeginObject();
  426.  }
  427.  
  428.  ASSERT_EQUAL(output.str(), R"([[{}]])");
  429. }
  430.  
  431. void TetsEx1()
  432. {
  433.  std::ostringstream output;
  434.  {
  435.    auto json = PrintJsonArray(output);
  436.    json
  437.      .Null()
  438.      .String("Hello")
  439.      .Number(123)
  440.      .Boolean(false)
  441.      .EndArray();
  442.  }
  443.  ASSERT_EQUAL(output.str(), R"([null,"Hello",123,false])");
  444. }
  445.  
  446. void TetsEx2()
  447. {
  448.  std::ostringstream output;
  449.  {
  450.    auto json = PrintJsonArray(output);
  451.    json
  452.      .String("Hello")
  453.      .BeginArray()
  454.      .String("World");
  455.  }
  456.  ASSERT_EQUAL(output.str(), R"(["Hello",["World"]])");
  457. }
  458.  
  459. void TetsEx3()
  460. {
  461.  std::ostringstream output;
  462.  {
  463.    auto json = PrintJsonObject(output);
  464.    json
  465.      .Key("foo")
  466.      .BeginArray()
  467.      .String("Hello")
  468.      .EndArray()
  469.      .Key("foo")  // повторяющиеся ключи допускаются
  470.      .BeginObject()
  471.      .Key("foo");
  472.  }
  473.  ASSERT_EQUAL(output.str(), R"({"foo":["Hello"],"foo":{"foo":null}})");
  474. }
  475.  
  476. void TestEndObject_1()
  477. {
  478.  std::ostringstream output;
  479.  
  480.  {
  481.    auto json = PrintJsonArray(output);
  482.    json
  483.      .BeginObject()
  484.        .Key("as")
  485.        .Null()
  486.      .EndObject()
  487.      .BeginObject();
  488.  }
  489.  
  490.  ASSERT_EQUAL(output.str(), R"([{"as":null,{}}])");
  491. }
  492.  
  493. void TestEndObject_2()
  494. {
  495.  std::ostringstream output;
  496.  
  497.  {
  498.    auto json = PrintJsonArray(output);
  499.    json
  500.      .BeginObject()
  501.        .Key("as")
  502.        .BeginObject()
  503.        .EndObject()
  504.        .Key("as")
  505.        .Null()
  506.      .EndObject()
  507.      .BeginObject();
  508.  }
  509.  
  510.  ASSERT_EQUAL(output.str(), R"([{"as":null,{}}])");
  511. }
  512.  
  513. int main()
  514. {
  515.  TestRunner tr;
  516.  RUN_TEST(tr, TestPrintJsonString);
  517.  RUN_TEST(tr, TestArray);
  518.  RUN_TEST(tr, TestArrayWOEnd);
  519.  RUN_TEST(tr, TestObject);
  520.  RUN_TEST(tr, TestAutoClose);
  521.  RUN_TEST(tr, TetsEx1);
  522.  RUN_TEST(tr, TetsEx2);
  523.  RUN_TEST(tr, TetsEx3);
  524.  RUN_TEST(tr, TestEndObject_1);
  525.  
  526.  PrintJsonArray(std::cout)
  527.  .Null()
  528.  .String("Hello")
  529.  .Number(123)
  530.  .Boolean(false)
  531.  .BeginObject()
  532.    .Key("A")
  533.    .BeginArray()
  534.      .Null()
  535.      .String("Hello")
  536.      .Number(123)
  537.    .EndArray();
  538.  
  539.  return 0;
  540. }
Add Comment
Please, Sign In to add comment