View difference between Paste ID: bW63YqAX and jsgtq67B
SHOW: | | - or go back to the newest paste.
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
}