writer.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #ifndef RAPIDJSON_WRITER_H_
  2. #define RAPIDJSON_WRITER_H_
  3. #include "rapidjson.h"
  4. #include "internal/stack.h"
  5. #include "internal/strfunc.h"
  6. #include <cstdio> // snprintf() or _sprintf_s()
  7. #include <new> // placement new
  8. #ifdef _MSC_VER
  9. #pragma warning(push)
  10. #pragma warning(disable : 4127) // conditional expression is constant
  11. #endif
  12. namespace rapidjson {
  13. //! JSON writer
  14. /*! Writer implements the concept Handler.
  15. It generates JSON text by events to an output os.
  16. User may programmatically calls the functions of a writer to generate JSON text.
  17. On the other side, a writer can also be passed to objects that generates events,
  18. for example Reader::Parse() and Document::Accept().
  19. \tparam OutputStream Type of output stream.
  20. \tparam SourceEncoding Encoding of both source strings.
  21. \tparam TargetEncoding Encoding of and output stream.
  22. \implements Handler
  23. */
  24. template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> >
  25. class Writer {
  26. public:
  27. typedef typename SourceEncoding::Ch Ch;
  28. Writer(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
  29. os_(os), level_stack_(allocator, levelDepth * sizeof(Level)) {}
  30. //@name Implementation of Handler
  31. //@{
  32. Writer& Null() { Prefix(kNullType); WriteNull(); return *this; }
  33. Writer& Bool(bool b) { Prefix(b ? kTrueType : kFalseType); WriteBool(b); return *this; }
  34. Writer& Int(int i) { Prefix(kNumberType); WriteInt(i); return *this; }
  35. Writer& Uint(unsigned u) { Prefix(kNumberType); WriteUint(u); return *this; }
  36. Writer& Int64(int64_t i64) { Prefix(kNumberType); WriteInt64(i64); return *this; }
  37. Writer& Uint64(uint64_t u64) { Prefix(kNumberType); WriteUint64(u64); return *this; }
  38. Writer& Double(double d) { Prefix(kNumberType); WriteDouble(d); return *this; }
  39. Writer& String(const Ch* str, SizeType length, bool copy = false) {
  40. (void)copy;
  41. Prefix(kStringType);
  42. WriteString(str, length);
  43. return *this;
  44. }
  45. Writer& StartObject() {
  46. Prefix(kObjectType);
  47. new (level_stack_.template Push<Level>()) Level(false);
  48. WriteStartObject();
  49. return *this;
  50. }
  51. Writer& EndObject(SizeType memberCount = 0) {
  52. (void)memberCount;
  53. RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
  54. RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
  55. level_stack_.template Pop<Level>(1);
  56. WriteEndObject();
  57. if (level_stack_.Empty()) // end of json text
  58. os_.Flush();
  59. return *this;
  60. }
  61. Writer& StartArray() {
  62. Prefix(kArrayType);
  63. new (level_stack_.template Push<Level>()) Level(true);
  64. WriteStartArray();
  65. return *this;
  66. }
  67. Writer& EndArray(SizeType elementCount = 0) {
  68. (void)elementCount;
  69. RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
  70. RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
  71. level_stack_.template Pop<Level>(1);
  72. WriteEndArray();
  73. if (level_stack_.Empty()) // end of json text
  74. os_.Flush();
  75. return *this;
  76. }
  77. //@}
  78. //! Simpler but slower overload.
  79. Writer& String(const Ch* str) { return String(str, internal::StrLen(str)); }
  80. protected:
  81. //! Information for each nested level
  82. struct Level {
  83. Level(bool inArray_) : inArray(inArray_), valueCount(0) {}
  84. bool inArray; //!< true if in array, otherwise in object
  85. size_t valueCount; //!< number of values in this level
  86. };
  87. static const size_t kDefaultLevelDepth = 32;
  88. void WriteNull() {
  89. os_.Put('n'); os_.Put('u'); os_.Put('l'); os_.Put('l');
  90. }
  91. void WriteBool(bool b) {
  92. if (b) {
  93. os_.Put('t'); os_.Put('r'); os_.Put('u'); os_.Put('e');
  94. }
  95. else {
  96. os_.Put('f'); os_.Put('a'); os_.Put('l'); os_.Put('s'); os_.Put('e');
  97. }
  98. }
  99. void WriteInt(int i) {
  100. if (i < 0) {
  101. os_.Put('-');
  102. i = -i;
  103. }
  104. WriteUint((unsigned)i);
  105. }
  106. void WriteUint(unsigned u) {
  107. char buffer[10];
  108. char *p = buffer;
  109. do {
  110. *p++ = (u % 10) + '0';
  111. u /= 10;
  112. } while (u > 0);
  113. do {
  114. --p;
  115. os_.Put(*p);
  116. } while (p != buffer);
  117. }
  118. void WriteInt64(int64_t i64) {
  119. if (i64 < 0) {
  120. os_.Put('-');
  121. i64 = -i64;
  122. }
  123. WriteUint64((uint64_t)i64);
  124. }
  125. void WriteUint64(uint64_t u64) {
  126. char buffer[20];
  127. char *p = buffer;
  128. do {
  129. *p++ = char(u64 % 10) + '0';
  130. u64 /= 10;
  131. } while (u64 > 0);
  132. do {
  133. --p;
  134. os_.Put(*p);
  135. } while (p != buffer);
  136. }
  137. //! \todo Optimization with custom double-to-string converter.
  138. void WriteDouble(double d) {
  139. char buffer[100];
  140. #if _MSC_VER
  141. int ret = sprintf_s(buffer, sizeof(buffer), "%g", d);
  142. #else
  143. int ret = snprintf(buffer, sizeof(buffer), "%g", d);
  144. #endif
  145. RAPIDJSON_ASSERT(ret >= 1);
  146. for (int i = 0; i < ret; i++)
  147. os_.Put(buffer[i]);
  148. }
  149. void WriteString(const Ch* str, SizeType length) {
  150. static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  151. static const char escape[256] = {
  152. #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  153. //0 1 2 3 4 5 6 7 8 9 A B C D E F
  154. 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
  155. 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
  156. 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
  157. Z16, Z16, // 30~4F
  158. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
  159. Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
  160. #undef Z16
  161. };
  162. os_.Put('\"');
  163. GenericStringStream<SourceEncoding> is(str);
  164. while (is.Tell() < length) {
  165. const Ch c = is.Peek();
  166. if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
  167. is.Take();
  168. os_.Put('\\');
  169. os_.Put(escape[(unsigned char)c]);
  170. if (escape[(unsigned char)c] == 'u') {
  171. os_.Put('0');
  172. os_.Put('0');
  173. os_.Put(hexDigits[(unsigned char)c >> 4]);
  174. os_.Put(hexDigits[(unsigned char)c & 0xF]);
  175. }
  176. }
  177. else
  178. Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, os_);
  179. }
  180. os_.Put('\"');
  181. }
  182. void WriteStartObject() { os_.Put('{'); }
  183. void WriteEndObject() { os_.Put('}'); }
  184. void WriteStartArray() { os_.Put('['); }
  185. void WriteEndArray() { os_.Put(']'); }
  186. void Prefix(Type type) {
  187. (void)type;
  188. if (level_stack_.GetSize() != 0) { // this value is not at root
  189. Level* level = level_stack_.template Top<Level>();
  190. if (level->valueCount > 0) {
  191. if (level->inArray)
  192. os_.Put(','); // add comma if it is not the first element in array
  193. else // in object
  194. os_.Put((level->valueCount % 2 == 0) ? ',' : ':');
  195. }
  196. if (!level->inArray && level->valueCount % 2 == 0)
  197. RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
  198. level->valueCount++;
  199. }
  200. else
  201. RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType);
  202. }
  203. OutputStream& os_;
  204. internal::Stack<Allocator> level_stack_;
  205. private:
  206. // Prohibit assignment for VC C4512 warning
  207. Writer& operator=(const Writer& w);
  208. };
  209. } // namespace rapidjson
  210. #ifdef _MSC_VER
  211. #pragma warning(pop)
  212. #endif
  213. #endif // RAPIDJSON_RAPIDJSON_H_