prettywriter.h
1 #ifndef RAPIDJSON_PRETTYWRITER_H_
2 #define RAPIDJSON_PRETTYWRITER_H_
3 
4 #include "writer.h"
5 
6 #ifdef __GNUC__
7 RAPIDJSON_DIAG_PUSH
8 RAPIDJSON_DIAG_OFF(effc++)
9 #endif
10 
11 namespace rapidjson {
12 
13 //! Writer with indentation and spacing.
14 /*!
15  \tparam OutputStream Type of ouptut os.
16  \tparam SourceEncoding Encoding of source string.
17  \tparam TargetEncoding Encoding of output stream.
18  \tparam Allocator Type of allocator for allocating memory of stack.
19 */
20 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> >
21 class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, Allocator> {
22 public:
24  typedef typename Base::Ch Ch;
25 
26  //! Constructor
27  /*! \param os Output stream.
28  \param allocator User supplied allocator. If it is null, it will create a private one.
29  \param levelDepth Initial capacity of stack.
30  */
31  PrettyWriter(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
32  Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
33 
34  //! Overridden for fluent API, see \ref Writer::SetDoublePrecision()
36 
37  //! Set custom indentation.
38  /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
39  \param indentCharCount Number of indent characters for each indentation level.
40  \note The default indentation is 4 spaces.
41  */
42  PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
43  RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
44  indentChar_ = indentChar;
45  indentCharCount_ = indentCharCount;
46  return *this;
47  }
48 
49  /*! @name Implementation of Handler
50  \see Handler
51  */
52  //@{
53 
54  bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
55  bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
56  bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
57  bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
58  bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
59  bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
60  bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
61 
62  bool String(const Ch* str, SizeType length, bool copy = false) {
63  (void)copy;
64  PrettyPrefix(kStringType);
65  return Base::WriteString(str, length);
66  }
67 
68  bool StartObject() {
69  PrettyPrefix(kObjectType);
70  new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
71  return Base::WriteStartObject();
72  }
73 
74  bool EndObject(SizeType memberCount = 0) {
75  (void)memberCount;
76  RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
77  RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
78  bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
79 
80  if (!empty) {
81  Base::os_->Put('\n');
82  WriteIndent();
83  }
84  if (!Base::WriteEndObject())
85  return false;
86  if (Base::level_stack_.Empty()) // end of json text
87  Base::os_->Flush();
88  return true;
89  }
90 
91  bool StartArray() {
92  PrettyPrefix(kArrayType);
93  new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
94  return Base::WriteStartArray();
95  }
96 
97  bool EndArray(SizeType memberCount = 0) {
98  (void)memberCount;
99  RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
100  RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
101  bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
102 
103  if (!empty) {
104  Base::os_->Put('\n');
105  WriteIndent();
106  }
107  if (!Base::WriteEndArray())
108  return false;
109  if (Base::level_stack_.Empty()) // end of json text
110  Base::os_->Flush();
111  return true;
112  }
113 
114  //@}
115 
116  /*! @name Convenience extensions */
117  //@{
118 
119  //! Simpler but slower overload.
120  bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
121 
122  //! Overridden for fluent API, see \ref Writer::Double()
123  bool Double(double d, int precision) {
124  int oldPrecision = Base::GetDoublePrecision();
125  SetDoublePrecision(precision);
126  bool ret = Double(d);
127  SetDoublePrecision(oldPrecision);
128  return ret;
129  }
130 
131  //@}
132 protected:
133  void PrettyPrefix(Type type) {
134  (void)type;
135  if (Base::level_stack_.GetSize() != 0) { // this value is not at root
136  typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
137 
138  if (level->inArray) {
139  if (level->valueCount > 0) {
140  Base::os_->Put(','); // add comma if it is not the first element in array
141  Base::os_->Put('\n');
142  }
143  else
144  Base::os_->Put('\n');
145  WriteIndent();
146  }
147  else { // in object
148  if (level->valueCount > 0) {
149  if (level->valueCount % 2 == 0) {
150  Base::os_->Put(',');
151  Base::os_->Put('\n');
152  }
153  else {
154  Base::os_->Put(':');
155  Base::os_->Put(' ');
156  }
157  }
158  else
159  Base::os_->Put('\n');
160 
161  if (level->valueCount % 2 == 0)
162  WriteIndent();
163  }
164  if (!level->inArray && level->valueCount % 2 == 0)
165  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
166  level->valueCount++;
167  }
168  else {
169  RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType);
170  RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root.
171  Base::hasRoot_ = true;
172  }
173  }
174 
175  void WriteIndent() {
176  size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
177  PutN(*Base::os_, indentChar_, count);
178  }
179 
180  Ch indentChar_;
181  unsigned indentCharCount_;
182 
183 private:
184  // Prohibit copy constructor & assignment operator.
185  PrettyWriter(const PrettyWriter&);
186  PrettyWriter& operator=(const PrettyWriter&);
187 };
188 
189 } // namespace rapidjson
190 
191 #ifdef __GNUC__
192 RAPIDJSON_DIAG_POP
193 #endif
194 
195 #endif // RAPIDJSON_RAPIDJSON_H_
true
Definition: rapidjson.h:394
PrettyWriter & SetDoublePrecision(int p)
Overridden for fluent API, see Writer::SetDoublePrecision()
Definition: prettywriter.h:35
bool Double(double d, int precision)
Overridden for fluent API, see Writer::Double()
Definition: prettywriter.h:123
unsigned SizeType
Use 32-bit array/string indices even for 64-bit platform, instead of using size_t.
Definition: rapidjson.h:133
false
Definition: rapidjson.h:393
Writer with indentation and spacing.
Definition: prettywriter.h:21
Writer & SetDoublePrecision(int p=kDefaultDoublePrecision)
Set the number of significant digits for double values.
Definition: writer.h:92
int GetDoublePrecision() const
Definition: writer.h:99
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:146
Type
Type of JSON value.
Definition: rapidjson.h:391
object
Definition: rapidjson.h:395
bool String(const Ch *str)
Simpler but slower overload.
Definition: prettywriter.h:120
array
Definition: rapidjson.h:396
void PutN(FileWriteStream &stream, char c, size_t n)
Implement specialized version of PutN() with memset() for better performance.
Definition: filewritestream.h:71
JSON writer.
Definition: writer.h:36
main RapidJSON namespace
Definition: allocators.h:6
null
Definition: rapidjson.h:392
bool WriteDouble(double d)
Definition: writer.h:255
string
Definition: rapidjson.h:397
Concept for allocating, resizing and freeing memory block.
PrettyWriter(OutputStream &os, Allocator *allocator=0, size_t levelDepth=Base::kDefaultLevelDepth)
Constructor.
Definition: prettywriter.h:31
PrettyWriter & SetIndent(Ch indentChar, unsigned indentCharCount)
Set custom indentation.
Definition: prettywriter.h:42
number
Definition: rapidjson.h:398