All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
prettywriter.h
1 // Copyright (C) 2011 Milo Yip
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE.
20 
21 #ifndef RAPIDJSON_PRETTYWRITER_H_
22 #define RAPIDJSON_PRETTYWRITER_H_
23 
24 #include "writer.h"
25 
26 #ifdef __GNUC__
27 RAPIDJSON_DIAG_PUSH
28 RAPIDJSON_DIAG_OFF(effc++)
29 #endif
30 
31 namespace rapidjson {
32 
33 //! Writer with indentation and spacing.
34 /*!
35  \tparam OutputStream Type of ouptut os.
36  \tparam SourceEncoding Encoding of source string.
37  \tparam TargetEncoding Encoding of output stream.
38  \tparam Allocator Type of allocator for allocating memory of stack.
39 */
40 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> >
41 class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, Allocator> {
42 public:
44  typedef typename Base::Ch Ch;
45 
46  //! Constructor
47  /*! \param os Output stream.
48  \param allocator User supplied allocator. If it is null, it will create a private one.
49  \param levelDepth Initial capacity of stack.
50  */
51  PrettyWriter(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
52  Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
53 
54  //! Set custom indentation.
55  /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
56  \param indentCharCount Number of indent characters for each indentation level.
57  \note The default indentation is 4 spaces.
58  */
59  PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
60  RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
61  indentChar_ = indentChar;
62  indentCharCount_ = indentCharCount;
63  return *this;
64  }
65 
66  /*! @name Implementation of Handler
67  \see Handler
68  */
69  //@{
70 
71  bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
72  bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
73  bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
74  bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
75  bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
76  bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
77  bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
78 
79  bool String(const Ch* str, SizeType length, bool copy = false) {
80  (void)copy;
81  PrettyPrefix(kStringType);
82  return Base::WriteString(str, length);
83  }
84 
85  bool StartObject() {
86  PrettyPrefix(kObjectType);
87  new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
88  return Base::WriteStartObject();
89  }
90 
91  bool EndObject(SizeType memberCount = 0) {
92  (void)memberCount;
93  RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
94  RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
95  bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
96 
97  if (!empty) {
98  Base::os_->Put('\n');
99  WriteIndent();
100  }
101  if (!Base::WriteEndObject())
102  return false;
103  if (Base::level_stack_.Empty()) // end of json text
104  Base::os_->Flush();
105  return true;
106  }
107 
108  bool StartArray() {
109  PrettyPrefix(kArrayType);
110  new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
111  return Base::WriteStartArray();
112  }
113 
114  bool EndArray(SizeType memberCount = 0) {
115  (void)memberCount;
116  RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
117  RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
118  bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
119 
120  if (!empty) {
121  Base::os_->Put('\n');
122  WriteIndent();
123  }
124  if (!Base::WriteEndArray())
125  return false;
126  if (Base::level_stack_.Empty()) // end of json text
127  Base::os_->Flush();
128  return true;
129  }
130 
131  //@}
132 
133  /*! @name Convenience extensions */
134  //@{
135 
136  //! Simpler but slower overload.
137  bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
138 
139  //@}
140 protected:
141  void PrettyPrefix(Type type) {
142  (void)type;
143  if (Base::level_stack_.GetSize() != 0) { // this value is not at root
144  typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
145 
146  if (level->inArray) {
147  if (level->valueCount > 0) {
148  Base::os_->Put(','); // add comma if it is not the first element in array
149  Base::os_->Put('\n');
150  }
151  else
152  Base::os_->Put('\n');
153  WriteIndent();
154  }
155  else { // in object
156  if (level->valueCount > 0) {
157  if (level->valueCount % 2 == 0) {
158  Base::os_->Put(',');
159  Base::os_->Put('\n');
160  }
161  else {
162  Base::os_->Put(':');
163  Base::os_->Put(' ');
164  }
165  }
166  else
167  Base::os_->Put('\n');
168 
169  if (level->valueCount % 2 == 0)
170  WriteIndent();
171  }
172  if (!level->inArray && level->valueCount % 2 == 0)
173  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
174  level->valueCount++;
175  }
176  else {
177  RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root.
178  Base::hasRoot_ = true;
179  }
180  }
181 
182  void WriteIndent() {
183  size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
184  PutN(*Base::os_, indentChar_, count);
185  }
186 
187  Ch indentChar_;
188  unsigned indentCharCount_;
189 
190 private:
191  // Prohibit copy constructor & assignment operator.
192  PrettyWriter(const PrettyWriter&);
193  PrettyWriter& operator=(const PrettyWriter&);
194 };
195 
196 } // namespace rapidjson
197 
198 #ifdef __GNUC__
199 RAPIDJSON_DIAG_POP
200 #endif
201 
202 #endif // RAPIDJSON_RAPIDJSON_H_
true
Definition: rapidjson.h:423
unsigned SizeType
Use 32-bit array/string indices even for 64-bit platform, instead of using size_t.
Definition: rapidjson.h:162
false
Definition: rapidjson.h:422
Writer with indentation and spacing.
Definition: prettywriter.h:41
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:175
Type
Type of JSON value.
Definition: rapidjson.h:420
object
Definition: rapidjson.h:424
bool String(const Ch *str)
Simpler but slower overload.
Definition: prettywriter.h:137
array
Definition: rapidjson.h:425
void PutN(FileWriteStream &stream, char c, size_t n)
Implement specialized version of PutN() with memset() for better performance.
Definition: filewritestream.h:91
JSON writer.
Definition: writer.h:56
null
Definition: rapidjson.h:421
string
Definition: rapidjson.h:426
Concept for allocating, resizing and freeing memory block.
PrettyWriter(OutputStream &os, Allocator *allocator=0, size_t levelDepth=Base::kDefaultLevelDepth)
Constructor.
Definition: prettywriter.h:51
PrettyWriter & SetIndent(Ch indentChar, unsigned indentCharCount)
Set custom indentation.
Definition: prettywriter.h:59
number
Definition: rapidjson.h:427