rapidjson A fast JSON parser/generator for C++ with both SAX/DOM style API

- Main Page
- Related Pages
- Classes
- Files

- File List

All Classes Functions Variables Typedefs Pages
prettywriter.h
1 #ifndef RAPIDJSON_PRETTYWRITER_H_
2 #define RAPIDJSON_PRETTYWRITER_H_
3
4 #include "writer.h"
5
6 namespace rapidjson {
7
8 //! Writer with indentation and spacing.
9 /*!
10 \tparam Stream Type of ouptut stream.
11 \tparam Encoding Encoding of both source strings and output.
12 \tparam Allocator Type of allocator for allocating memory of stack.
13 */
14 template<typename Stream, typename Encoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> >
15 class PrettyWriter : public Writer<Stream, Encoding, Allocator> {
16 public:
17 typedef Writer<Stream, Encoding, Allocator> Base;
18 typedef typename Base::Ch Ch;
19
20 //! Constructor
21 /*! \param stream Output stream.
22 \param allocator User supplied allocator. If it is null, it will create a private one.
23 \param levelDepth Initial capacity of
24 */
25 PrettyWriter(Stream& stream, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
26 Base(stream, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
27
28 //! Set custom indentation.
29 /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\t', '\n', '\r').
30 \param indentCharCount Number of indent characters for each indentation level.
31 \note The default indentation is 4 spaces.
32 */
33 PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
34 RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
35 indentChar_ = indentChar;
36 indentCharCount_ = indentCharCount;
37 return *this;
38 }
39
40 //@name Implementation of Handler.
41 //@{
42
43 PrettyWriter& Null() { PrettyPrefix(kNullType); Base::WriteNull(); return *this; }
44 PrettyWriter& Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); Base::WriteBool(b); return *this; }
45 PrettyWriter& Int(int i) { PrettyPrefix(kNumberType); Base::WriteInt(i); return *this; }
46 PrettyWriter& Uint(unsigned u) { PrettyPrefix(kNumberType); Base::WriteUint(u); return *this; }
47 PrettyWriter& Int64(int64_t i64) { PrettyPrefix(kNumberType); Base::WriteInt64(i64); return *this; }
48 PrettyWriter& Uint64(uint64_t u64) { PrettyPrefix(kNumberType); Base::WriteUint64(u64); return *this; }
49 PrettyWriter& Double(double d) { PrettyPrefix(kNumberType); Base::WriteDouble(d); return *this; }
50
51 PrettyWriter& String(const Ch* str, SizeType length, bool copy = false) {
52 (void)copy;
53 PrettyPrefix(kStringType);
54 Base::WriteString(str, length);
55 return *this;
56 }
57
58 PrettyWriter& StartObject() {
59 PrettyPrefix(kObjectType);
60 new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
61 Base::WriteStartObject();
62 return *this;
63 }
64
65 PrettyWriter& EndObject(SizeType memberCount = 0) {
66 (void)memberCount;
67 RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
68 RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
69 bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
70
71 if (!empty) {
72 Base::stream_.Put('\n');
73 WriteIndent();
74 }
75 Base::WriteEndObject();
76 return *this;
77 }
78
79 PrettyWriter& StartArray() {
80 PrettyPrefix(kArrayType);
81 new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
82 Base::WriteStartArray();
83 return *this;
84 }
85
86 PrettyWriter& EndArray(SizeType memberCount = 0) {
87 (void)memberCount;
88 RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
89 RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
90 bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
91
92 if (!empty) {
93 Base::stream_.Put('\n');
94 WriteIndent();
95 }
96 Base::WriteEndArray();
97 return *this;
98 }
99
100 //@}
101
102 //! Simpler but slower overload.
103 PrettyWriter& String(const Ch* str) { return String(str, internal::StrLen(str)); }
104
105 protected:
106 void PrettyPrefix(Type type) {
107 (void)type;
108 if (Base::level_stack_.GetSize() != 0) { // this value is not at root
109 typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
110
111 if (level->inArray) {
112 if (level->valueCount > 0) {
113 Base::stream_.Put(','); // add comma if it is not the first element in array
114 Base::stream_.Put('\n');
115 }
116 else
117 Base::stream_.Put('\n');
118 WriteIndent();
119 }
120 else { // in object
121 if (level->valueCount > 0) {
122 if (level->valueCount % 2 == 0) {
123 Base::stream_.Put(',');
124 Base::stream_.Put('\n');
125 }
126 else {
127 Base::stream_.Put(':');
128 Base::stream_.Put(' ');
129 }
130 }
131 else
132 Base::stream_.Put('\n');
133
134 if (level->valueCount % 2 == 0)
135 WriteIndent();
136 }
137 if (!level->inArray && level->valueCount % 2 == 0)
138 RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
139 level->valueCount++;
140 }
141 else
142 RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType);
143 }
144
145 void WriteIndent() {
146 size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
147 PutN(Base::stream_, indentChar_, count);
148 }
149
150 Ch indentChar_;
151 unsigned indentCharCount_;
152 };
153
154 } // namespace rapidjson
155
156 #endif // RAPIDJSON_RAPIDJSON_H_