prettywriter.h

Engine/source/persistence/rapidjson/prettywriter.h

More...

Classes:

class

Writer with indentation and spacing.

Namespaces:

namespace

Detailed Description

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