prettywriter.h 5.2 KB

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