1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#ifndef ENGINE_SHARED_JSONWRITER_H
4#define ENGINE_SHARED_JSONWRITER_H
5
6#include <base/types.h>
7
8#include <stack>
9#include <string>
10
11/**
12 * JSON writer with abstract writing function.
13 */
14class CJsonWriter
15{
16 enum EJsonStateKind
17 {
18 STATE_OBJECT,
19 STATE_ARRAY,
20 STATE_ATTRIBUTE,
21 };
22
23 struct SState
24 {
25 EJsonStateKind m_Kind;
26 bool m_Empty = true;
27
28 SState(EJsonStateKind Kind) :
29 m_Kind(Kind)
30 {
31 }
32 };
33
34 std::stack<SState> m_States;
35 int m_Indentation;
36
37 bool CanWriteDatatype();
38 void WriteInternalEscaped(const char *pStr);
39 void WriteIndent(bool EndElement);
40 void PushState(EJsonStateKind NewState);
41 SState *TopState();
42 EJsonStateKind PopState();
43 void CompleteDataType();
44
45protected:
46 // String must be zero-terminated when Length is -1.
47 virtual void WriteInternal(const char *pStr, int Length = -1) = 0;
48
49public:
50 CJsonWriter();
51 virtual ~CJsonWriter() = default;
52
53 // The root is created by beginning the first datatype (object, array, value).
54 // The writer must not be used after ending the root, which must be unique.
55
56 // Begin writing a new object
57 void BeginObject();
58 // End current object
59 void EndObject();
60
61 // Begin writing a new array
62 void BeginArray();
63 // End current array
64 void EndArray();
65
66 // Write attribute with the given name inside the current object.
67 // Names inside one object should be unique, but this is not checked here.
68 // Must be used to begin writing anything inside objects and only there.
69 // Must be followed by a datatype for the attribute value.
70 void WriteAttribute(const char *pName);
71
72 // Functions for writing value literals:
73 // - As array values in arrays.
74 // - As attribute values after beginning an attribute inside an object.
75 // - As root value (only once).
76 void WriteStrValue(const char *pValue);
77 void WriteIntValue(int Value);
78 void WriteBoolValue(bool Value);
79 void WriteNullValue();
80};
81
82/**
83 * Writes JSON to a file.
84 */
85class CJsonFileWriter : public CJsonWriter
86{
87 IOHANDLE m_IO;
88
89protected:
90 void WriteInternal(const char *pStr, int Length = -1) override;
91
92public:
93 /**
94 * Create a new writer object without writing anything to the file yet.
95 * The file will automatically be closed by the destructor.
96 */
97 CJsonFileWriter(IOHANDLE IO);
98 ~CJsonFileWriter();
99};
100
101/**
102 * Writes JSON to an std::string.
103 */
104class CJsonStringWriter : public CJsonWriter
105{
106 std::string m_OutputString;
107 bool m_RetrievedOutput = false;
108
109protected:
110 void WriteInternal(const char *pStr, int Length = -1) override;
111
112public:
113 CJsonStringWriter() = default;
114 ~CJsonStringWriter() = default;
115 std::string &&GetOutputString();
116};
117
118#endif
119