rj_schema 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (299) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +18 -0
  3. data/ext/rj_schema/extconf.rb +7 -0
  4. data/ext/rj_schema/rapidjson/CHANGELOG.md +158 -0
  5. data/ext/rj_schema/rapidjson/CMakeLists.txt +221 -0
  6. data/ext/rj_schema/rapidjson/CMakeModules/FindGTestSrc.cmake +30 -0
  7. data/ext/rj_schema/rapidjson/RapidJSON.pc.in +7 -0
  8. data/ext/rj_schema/rapidjson/RapidJSONConfig.cmake.in +15 -0
  9. data/ext/rj_schema/rapidjson/RapidJSONConfigVersion.cmake.in +10 -0
  10. data/ext/rj_schema/rapidjson/appveyor.yml +41 -0
  11. data/ext/rj_schema/rapidjson/bin/data/glossary.json +22 -0
  12. data/ext/rj_schema/rapidjson/bin/data/menu.json +27 -0
  13. data/ext/rj_schema/rapidjson/bin/data/readme.txt +1 -0
  14. data/ext/rj_schema/rapidjson/bin/data/sample.json +3315 -0
  15. data/ext/rj_schema/rapidjson/bin/data/webapp.json +88 -0
  16. data/ext/rj_schema/rapidjson/bin/data/widget.json +26 -0
  17. data/ext/rj_schema/rapidjson/bin/draft-04/schema +150 -0
  18. data/ext/rj_schema/rapidjson/bin/encodings/utf16be.json +0 -0
  19. data/ext/rj_schema/rapidjson/bin/encodings/utf16bebom.json +0 -0
  20. data/ext/rj_schema/rapidjson/bin/encodings/utf16le.json +0 -0
  21. data/ext/rj_schema/rapidjson/bin/encodings/utf16lebom.json +0 -0
  22. data/ext/rj_schema/rapidjson/bin/encodings/utf32be.json +0 -0
  23. data/ext/rj_schema/rapidjson/bin/encodings/utf32bebom.json +0 -0
  24. data/ext/rj_schema/rapidjson/bin/encodings/utf32le.json +0 -0
  25. data/ext/rj_schema/rapidjson/bin/encodings/utf32lebom.json +0 -0
  26. data/ext/rj_schema/rapidjson/bin/encodings/utf8.json +7 -0
  27. data/ext/rj_schema/rapidjson/bin/encodings/utf8bom.json +7 -0
  28. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail1.json +1 -0
  29. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail10.json +1 -0
  30. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail11.json +1 -0
  31. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail12.json +1 -0
  32. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail13.json +1 -0
  33. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail14.json +1 -0
  34. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail15.json +1 -0
  35. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail16.json +1 -0
  36. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail17.json +1 -0
  37. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail18.json +1 -0
  38. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail19.json +1 -0
  39. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail2.json +1 -0
  40. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail20.json +1 -0
  41. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail21.json +1 -0
  42. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail22.json +1 -0
  43. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail23.json +1 -0
  44. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail24.json +1 -0
  45. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail25.json +1 -0
  46. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail26.json +1 -0
  47. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail27.json +2 -0
  48. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail28.json +2 -0
  49. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail29.json +1 -0
  50. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail3.json +1 -0
  51. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail30.json +1 -0
  52. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail31.json +1 -0
  53. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail32.json +1 -0
  54. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail33.json +1 -0
  55. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail4.json +1 -0
  56. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail5.json +1 -0
  57. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail6.json +1 -0
  58. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail7.json +1 -0
  59. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail8.json +1 -0
  60. data/ext/rj_schema/rapidjson/bin/jsonchecker/fail9.json +1 -0
  61. data/ext/rj_schema/rapidjson/bin/jsonchecker/pass1.json +58 -0
  62. data/ext/rj_schema/rapidjson/bin/jsonchecker/pass2.json +1 -0
  63. data/ext/rj_schema/rapidjson/bin/jsonchecker/pass3.json +6 -0
  64. data/ext/rj_schema/rapidjson/bin/jsonchecker/readme.txt +3 -0
  65. data/ext/rj_schema/rapidjson/bin/jsonschema/LICENSE +19 -0
  66. data/ext/rj_schema/rapidjson/bin/jsonschema/README.md +148 -0
  67. data/ext/rj_schema/rapidjson/bin/jsonschema/bin/jsonschema_suite +283 -0
  68. data/ext/rj_schema/rapidjson/bin/jsonschema/remotes/folder/folderInteger.json +3 -0
  69. data/ext/rj_schema/rapidjson/bin/jsonschema/remotes/integer.json +3 -0
  70. data/ext/rj_schema/rapidjson/bin/jsonschema/remotes/subSchemas.json +8 -0
  71. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/additionalItems.json +82 -0
  72. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/additionalProperties.json +88 -0
  73. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/default.json +49 -0
  74. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/dependencies.json +108 -0
  75. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/disallow.json +80 -0
  76. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/divisibleBy.json +60 -0
  77. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/enum.json +71 -0
  78. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/extends.json +94 -0
  79. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/items.json +46 -0
  80. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/maxItems.json +28 -0
  81. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/maxLength.json +33 -0
  82. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/maximum.json +42 -0
  83. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/minItems.json +28 -0
  84. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/minLength.json +33 -0
  85. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/minimum.json +42 -0
  86. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/optional/bignum.json +107 -0
  87. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/optional/format.json +222 -0
  88. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/optional/jsregex.json +18 -0
  89. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/optional/zeroTerminatedFloats.json +15 -0
  90. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/pattern.json +34 -0
  91. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/patternProperties.json +110 -0
  92. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/properties.json +92 -0
  93. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/ref.json +159 -0
  94. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/refRemote.json +74 -0
  95. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/required.json +53 -0
  96. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/type.json +474 -0
  97. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft3/uniqueItems.json +79 -0
  98. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/additionalItems.json +82 -0
  99. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/additionalProperties.json +88 -0
  100. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/allOf.json +112 -0
  101. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/anyOf.json +68 -0
  102. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/default.json +49 -0
  103. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/definitions.json +32 -0
  104. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/dependencies.json +113 -0
  105. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/enum.json +72 -0
  106. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/items.json +46 -0
  107. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/maxItems.json +28 -0
  108. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/maxLength.json +33 -0
  109. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/maxProperties.json +28 -0
  110. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/maximum.json +42 -0
  111. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/minItems.json +28 -0
  112. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/minLength.json +33 -0
  113. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/minProperties.json +28 -0
  114. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/minimum.json +42 -0
  115. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/multipleOf.json +60 -0
  116. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/not.json +96 -0
  117. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/oneOf.json +68 -0
  118. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/optional/bignum.json +107 -0
  119. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/optional/format.json +148 -0
  120. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/optional/zeroTerminatedFloats.json +15 -0
  121. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/pattern.json +34 -0
  122. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/patternProperties.json +110 -0
  123. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/properties.json +92 -0
  124. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/ref.json +159 -0
  125. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/refRemote.json +74 -0
  126. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/required.json +39 -0
  127. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/type.json +330 -0
  128. data/ext/rj_schema/rapidjson/bin/jsonschema/tests/draft4/uniqueItems.json +79 -0
  129. data/ext/rj_schema/rapidjson/bin/jsonschema/tox.ini +8 -0
  130. data/ext/rj_schema/rapidjson/bin/types/booleans.json +102 -0
  131. data/ext/rj_schema/rapidjson/bin/types/floats.json +102 -0
  132. data/ext/rj_schema/rapidjson/bin/types/guids.json +102 -0
  133. data/ext/rj_schema/rapidjson/bin/types/integers.json +102 -0
  134. data/ext/rj_schema/rapidjson/bin/types/mixed.json +592 -0
  135. data/ext/rj_schema/rapidjson/bin/types/nulls.json +102 -0
  136. data/ext/rj_schema/rapidjson/bin/types/paragraphs.json +102 -0
  137. data/ext/rj_schema/rapidjson/bin/types/readme.txt +1 -0
  138. data/ext/rj_schema/rapidjson/contrib/natvis/LICENSE +45 -0
  139. data/ext/rj_schema/rapidjson/contrib/natvis/README.md +7 -0
  140. data/ext/rj_schema/rapidjson/contrib/natvis/rapidjson.natvis +38 -0
  141. data/ext/rj_schema/rapidjson/doc/CMakeLists.txt +27 -0
  142. data/ext/rj_schema/rapidjson/doc/Doxyfile.in +2369 -0
  143. data/ext/rj_schema/rapidjson/doc/Doxyfile.zh-cn.in +2369 -0
  144. data/ext/rj_schema/rapidjson/doc/diagram/architecture.dot +50 -0
  145. data/ext/rj_schema/rapidjson/doc/diagram/architecture.png +0 -0
  146. data/ext/rj_schema/rapidjson/doc/diagram/insituparsing.dot +65 -0
  147. data/ext/rj_schema/rapidjson/doc/diagram/insituparsing.png +0 -0
  148. data/ext/rj_schema/rapidjson/doc/diagram/iterative-parser-states-diagram.dot +62 -0
  149. data/ext/rj_schema/rapidjson/doc/diagram/iterative-parser-states-diagram.png +0 -0
  150. data/ext/rj_schema/rapidjson/doc/diagram/makefile +8 -0
  151. data/ext/rj_schema/rapidjson/doc/diagram/move1.dot +47 -0
  152. data/ext/rj_schema/rapidjson/doc/diagram/move1.png +0 -0
  153. data/ext/rj_schema/rapidjson/doc/diagram/move2.dot +62 -0
  154. data/ext/rj_schema/rapidjson/doc/diagram/move2.png +0 -0
  155. data/ext/rj_schema/rapidjson/doc/diagram/move3.dot +60 -0
  156. data/ext/rj_schema/rapidjson/doc/diagram/move3.png +0 -0
  157. data/ext/rj_schema/rapidjson/doc/diagram/normalparsing.dot +56 -0
  158. data/ext/rj_schema/rapidjson/doc/diagram/normalparsing.png +0 -0
  159. data/ext/rj_schema/rapidjson/doc/diagram/simpledom.dot +54 -0
  160. data/ext/rj_schema/rapidjson/doc/diagram/simpledom.png +0 -0
  161. data/ext/rj_schema/rapidjson/doc/diagram/tutorial.dot +58 -0
  162. data/ext/rj_schema/rapidjson/doc/diagram/tutorial.png +0 -0
  163. data/ext/rj_schema/rapidjson/doc/diagram/utilityclass.dot +73 -0
  164. data/ext/rj_schema/rapidjson/doc/diagram/utilityclass.png +0 -0
  165. data/ext/rj_schema/rapidjson/doc/dom.md +280 -0
  166. data/ext/rj_schema/rapidjson/doc/dom.zh-cn.md +284 -0
  167. data/ext/rj_schema/rapidjson/doc/encoding.md +146 -0
  168. data/ext/rj_schema/rapidjson/doc/encoding.zh-cn.md +152 -0
  169. data/ext/rj_schema/rapidjson/doc/faq.md +289 -0
  170. data/ext/rj_schema/rapidjson/doc/faq.zh-cn.md +290 -0
  171. data/ext/rj_schema/rapidjson/doc/features.md +104 -0
  172. data/ext/rj_schema/rapidjson/doc/features.zh-cn.md +103 -0
  173. data/ext/rj_schema/rapidjson/doc/internals.md +368 -0
  174. data/ext/rj_schema/rapidjson/doc/internals.zh-cn.md +363 -0
  175. data/ext/rj_schema/rapidjson/doc/logo/rapidjson.png +0 -0
  176. data/ext/rj_schema/rapidjson/doc/logo/rapidjson.svg +119 -0
  177. data/ext/rj_schema/rapidjson/doc/misc/DoxygenLayout.xml +194 -0
  178. data/ext/rj_schema/rapidjson/doc/misc/doxygenextra.css +274 -0
  179. data/ext/rj_schema/rapidjson/doc/misc/footer.html +11 -0
  180. data/ext/rj_schema/rapidjson/doc/misc/header.html +24 -0
  181. data/ext/rj_schema/rapidjson/doc/npm.md +31 -0
  182. data/ext/rj_schema/rapidjson/doc/performance.md +26 -0
  183. data/ext/rj_schema/rapidjson/doc/performance.zh-cn.md +26 -0
  184. data/ext/rj_schema/rapidjson/doc/pointer.md +234 -0
  185. data/ext/rj_schema/rapidjson/doc/pointer.zh-cn.md +234 -0
  186. data/ext/rj_schema/rapidjson/doc/sax.md +509 -0
  187. data/ext/rj_schema/rapidjson/doc/sax.zh-cn.md +487 -0
  188. data/ext/rj_schema/rapidjson/doc/schema.md +505 -0
  189. data/ext/rj_schema/rapidjson/doc/schema.zh-cn.md +237 -0
  190. data/ext/rj_schema/rapidjson/doc/stream.md +426 -0
  191. data/ext/rj_schema/rapidjson/doc/stream.zh-cn.md +426 -0
  192. data/ext/rj_schema/rapidjson/doc/tutorial.md +536 -0
  193. data/ext/rj_schema/rapidjson/doc/tutorial.zh-cn.md +534 -0
  194. data/ext/rj_schema/rapidjson/docker/debian/Dockerfile +8 -0
  195. data/ext/rj_schema/rapidjson/example/CMakeLists.txt +45 -0
  196. data/ext/rj_schema/rapidjson/example/archiver/archiver.cpp +292 -0
  197. data/ext/rj_schema/rapidjson/example/archiver/archiver.h +145 -0
  198. data/ext/rj_schema/rapidjson/example/archiver/archivertest.cpp +287 -0
  199. data/ext/rj_schema/rapidjson/example/capitalize/capitalize.cpp +67 -0
  200. data/ext/rj_schema/rapidjson/example/condense/condense.cpp +32 -0
  201. data/ext/rj_schema/rapidjson/example/filterkey/filterkey.cpp +135 -0
  202. data/ext/rj_schema/rapidjson/example/filterkeydom/filterkeydom.cpp +170 -0
  203. data/ext/rj_schema/rapidjson/example/jsonx/jsonx.cpp +207 -0
  204. data/ext/rj_schema/rapidjson/example/lookaheadparser/lookaheadparser.cpp +350 -0
  205. data/ext/rj_schema/rapidjson/example/messagereader/messagereader.cpp +105 -0
  206. data/ext/rj_schema/rapidjson/example/parsebyparts/parsebyparts.cpp +176 -0
  207. data/ext/rj_schema/rapidjson/example/pretty/pretty.cpp +30 -0
  208. data/ext/rj_schema/rapidjson/example/prettyauto/prettyauto.cpp +56 -0
  209. data/ext/rj_schema/rapidjson/example/schemavalidator/schemavalidator.cpp +78 -0
  210. data/ext/rj_schema/rapidjson/example/serialize/serialize.cpp +173 -0
  211. data/ext/rj_schema/rapidjson/example/simpledom/simpledom.cpp +29 -0
  212. data/ext/rj_schema/rapidjson/example/simplepullreader/simplepullreader.cpp +53 -0
  213. data/ext/rj_schema/rapidjson/example/simplereader/simplereader.cpp +42 -0
  214. data/ext/rj_schema/rapidjson/example/simplewriter/simplewriter.cpp +36 -0
  215. data/ext/rj_schema/rapidjson/example/tutorial/tutorial.cpp +151 -0
  216. data/ext/rj_schema/rapidjson/include/rapidjson/allocators.h +271 -0
  217. data/ext/rj_schema/rapidjson/include/rapidjson/cursorstreamwrapper.h +78 -0
  218. data/ext/rj_schema/rapidjson/include/rapidjson/document.h +2630 -0
  219. data/ext/rj_schema/rapidjson/include/rapidjson/encodedstream.h +299 -0
  220. data/ext/rj_schema/rapidjson/include/rapidjson/encodings.h +716 -0
  221. data/ext/rj_schema/rapidjson/include/rapidjson/error/en.h +74 -0
  222. data/ext/rj_schema/rapidjson/include/rapidjson/error/error.h +161 -0
  223. data/ext/rj_schema/rapidjson/include/rapidjson/filereadstream.h +99 -0
  224. data/ext/rj_schema/rapidjson/include/rapidjson/filewritestream.h +104 -0
  225. data/ext/rj_schema/rapidjson/include/rapidjson/fwd.h +151 -0
  226. data/ext/rj_schema/rapidjson/include/rapidjson/internal/biginteger.h +290 -0
  227. data/ext/rj_schema/rapidjson/include/rapidjson/internal/diyfp.h +258 -0
  228. data/ext/rj_schema/rapidjson/include/rapidjson/internal/dtoa.h +245 -0
  229. data/ext/rj_schema/rapidjson/include/rapidjson/internal/ieee754.h +78 -0
  230. data/ext/rj_schema/rapidjson/include/rapidjson/internal/itoa.h +304 -0
  231. data/ext/rj_schema/rapidjson/include/rapidjson/internal/meta.h +181 -0
  232. data/ext/rj_schema/rapidjson/include/rapidjson/internal/pow10.h +55 -0
  233. data/ext/rj_schema/rapidjson/include/rapidjson/internal/regex.h +734 -0
  234. data/ext/rj_schema/rapidjson/include/rapidjson/internal/stack.h +231 -0
  235. data/ext/rj_schema/rapidjson/include/rapidjson/internal/strfunc.h +69 -0
  236. data/ext/rj_schema/rapidjson/include/rapidjson/internal/strtod.h +269 -0
  237. data/ext/rj_schema/rapidjson/include/rapidjson/internal/swap.h +46 -0
  238. data/ext/rj_schema/rapidjson/include/rapidjson/istreamwrapper.h +115 -0
  239. data/ext/rj_schema/rapidjson/include/rapidjson/memorybuffer.h +70 -0
  240. data/ext/rj_schema/rapidjson/include/rapidjson/memorystream.h +71 -0
  241. data/ext/rj_schema/rapidjson/include/rapidjson/msinttypes/inttypes.h +316 -0
  242. data/ext/rj_schema/rapidjson/include/rapidjson/msinttypes/stdint.h +300 -0
  243. data/ext/rj_schema/rapidjson/include/rapidjson/ostreamwrapper.h +81 -0
  244. data/ext/rj_schema/rapidjson/include/rapidjson/pointer.h +1363 -0
  245. data/ext/rj_schema/rapidjson/include/rapidjson/prettywriter.h +277 -0
  246. data/ext/rj_schema/rapidjson/include/rapidjson/rapidjson.h +628 -0
  247. data/ext/rj_schema/rapidjson/include/rapidjson/reader.h +2222 -0
  248. data/ext/rj_schema/rapidjson/include/rapidjson/schema.h +2479 -0
  249. data/ext/rj_schema/rapidjson/include/rapidjson/stream.h +223 -0
  250. data/ext/rj_schema/rapidjson/include/rapidjson/stringbuffer.h +121 -0
  251. data/ext/rj_schema/rapidjson/include/rapidjson/writer.h +716 -0
  252. data/ext/rj_schema/rapidjson/include_dirs.js +2 -0
  253. data/ext/rj_schema/rapidjson/library.json +15 -0
  254. data/ext/rj_schema/rapidjson/license.txt +57 -0
  255. data/ext/rj_schema/rapidjson/package.json +24 -0
  256. data/ext/rj_schema/rapidjson/rapidjson.autopkg +77 -0
  257. data/ext/rj_schema/rapidjson/readme.md +160 -0
  258. data/ext/rj_schema/rapidjson/readme.zh-cn.md +152 -0
  259. data/ext/rj_schema/rapidjson/test/CMakeLists.txt +20 -0
  260. data/ext/rj_schema/rapidjson/test/perftest/CMakeLists.txt +28 -0
  261. data/ext/rj_schema/rapidjson/test/perftest/misctest.cpp +974 -0
  262. data/ext/rj_schema/rapidjson/test/perftest/perftest.cpp +24 -0
  263. data/ext/rj_schema/rapidjson/test/perftest/perftest.h +185 -0
  264. data/ext/rj_schema/rapidjson/test/perftest/platformtest.cpp +166 -0
  265. data/ext/rj_schema/rapidjson/test/perftest/rapidjsontest.cpp +472 -0
  266. data/ext/rj_schema/rapidjson/test/perftest/schematest.cpp +216 -0
  267. data/ext/rj_schema/rapidjson/test/unittest/CMakeLists.txt +92 -0
  268. data/ext/rj_schema/rapidjson/test/unittest/allocatorstest.cpp +102 -0
  269. data/ext/rj_schema/rapidjson/test/unittest/bigintegertest.cpp +133 -0
  270. data/ext/rj_schema/rapidjson/test/unittest/cursorstreamwrappertest.cpp +115 -0
  271. data/ext/rj_schema/rapidjson/test/unittest/documenttest.cpp +672 -0
  272. data/ext/rj_schema/rapidjson/test/unittest/dtoatest.cpp +98 -0
  273. data/ext/rj_schema/rapidjson/test/unittest/encodedstreamtest.cpp +313 -0
  274. data/ext/rj_schema/rapidjson/test/unittest/encodingstest.cpp +451 -0
  275. data/ext/rj_schema/rapidjson/test/unittest/filestreamtest.cpp +112 -0
  276. data/ext/rj_schema/rapidjson/test/unittest/fwdtest.cpp +230 -0
  277. data/ext/rj_schema/rapidjson/test/unittest/istreamwrappertest.cpp +181 -0
  278. data/ext/rj_schema/rapidjson/test/unittest/itoatest.cpp +160 -0
  279. data/ext/rj_schema/rapidjson/test/unittest/jsoncheckertest.cpp +143 -0
  280. data/ext/rj_schema/rapidjson/test/unittest/namespacetest.cpp +70 -0
  281. data/ext/rj_schema/rapidjson/test/unittest/ostreamwrappertest.cpp +92 -0
  282. data/ext/rj_schema/rapidjson/test/unittest/pointertest.cpp +1529 -0
  283. data/ext/rj_schema/rapidjson/test/unittest/prettywritertest.cpp +344 -0
  284. data/ext/rj_schema/rapidjson/test/unittest/readertest.cpp +1895 -0
  285. data/ext/rj_schema/rapidjson/test/unittest/regextest.cpp +638 -0
  286. data/ext/rj_schema/rapidjson/test/unittest/schematest.cpp +2009 -0
  287. data/ext/rj_schema/rapidjson/test/unittest/simdtest.cpp +219 -0
  288. data/ext/rj_schema/rapidjson/test/unittest/strfunctest.cpp +30 -0
  289. data/ext/rj_schema/rapidjson/test/unittest/stringbuffertest.cpp +192 -0
  290. data/ext/rj_schema/rapidjson/test/unittest/strtodtest.cpp +132 -0
  291. data/ext/rj_schema/rapidjson/test/unittest/unittest.cpp +51 -0
  292. data/ext/rj_schema/rapidjson/test/unittest/unittest.h +140 -0
  293. data/ext/rj_schema/rapidjson/test/unittest/valuetest.cpp +1829 -0
  294. data/ext/rj_schema/rapidjson/test/unittest/writertest.cpp +598 -0
  295. data/ext/rj_schema/rapidjson/test/valgrind.supp +17 -0
  296. data/ext/rj_schema/rapidjson/travis-doxygen.sh +121 -0
  297. data/ext/rj_schema/rj_schema.cpp +136 -0
  298. data/lib/rj_schema.rb +7 -0
  299. metadata +371 -0
@@ -0,0 +1,426 @@
1
+ # 流
2
+
3
+ 在 RapidJSON 中,`rapidjson::Stream` 是用於读写 JSON 的概念(概念是指 C++ 的 concept)。在这里我们先介绍如何使用 RapidJSON 提供的各种流。然后再看看如何自行定义流。
4
+
5
+ [TOC]
6
+
7
+ # 内存流 {#MemoryStreams}
8
+
9
+ 内存流把 JSON 存储在内存之中。
10
+
11
+ ## StringStream(输入){#StringStream}
12
+
13
+ `StringStream` 是最基本的输入流,它表示一个完整的、只读的、存储于内存的 JSON。它在 `rapidjson/rapidjson.h` 中定义。
14
+
15
+ ~~~~~~~~~~cpp
16
+ #include "rapidjson/document.h" // 会包含 "rapidjson/rapidjson.h"
17
+
18
+ using namespace rapidjson;
19
+
20
+ // ...
21
+ const char json[] = "[1, 2, 3, 4]";
22
+ StringStream s(json);
23
+
24
+ Document d;
25
+ d.ParseStream(s);
26
+ ~~~~~~~~~~
27
+
28
+ 由于这是非常常用的用法,RapidJSON 提供 `Document::Parse(const char*)` 去做完全相同的事情:
29
+
30
+ ~~~~~~~~~~cpp
31
+ // ...
32
+ const char json[] = "[1, 2, 3, 4]";
33
+ Document d;
34
+ d.Parse(json);
35
+ ~~~~~~~~~~
36
+
37
+ 需要注意,`StringStream` 是 `GenericStringStream<UTF8<> >` 的 typedef,使用者可用其他编码类去代表流所使用的字符集。
38
+
39
+ ## StringBuffer(输出){#StringBuffer}
40
+
41
+ `StringBuffer` 是一个简单的输出流。它分配一个内存缓冲区,供写入整个 JSON。可使用 `GetString()` 来获取该缓冲区。
42
+
43
+ ~~~~~~~~~~cpp
44
+ #include "rapidjson/stringbuffer.h"
45
+
46
+ StringBuffer buffer;
47
+ Writer<StringBuffer> writer(buffer);
48
+ d.Accept(writer);
49
+
50
+ const char* output = buffer.GetString();
51
+ ~~~~~~~~~~
52
+
53
+ 当缓冲区满溢,它将自动增加容量。缺省容量是 256 个字符(UTF8 是 256 字节,UTF16 是 512 字节等)。使用者能自行提供分配器及初始容量。
54
+
55
+ ~~~~~~~~~~cpp
56
+ StringBuffer buffer1(0, 1024); // 使用它的分配器,初始大小 = 1024
57
+ StringBuffer buffer2(allocator, 1024);
58
+ ~~~~~~~~~~
59
+
60
+ 如无设置分配器,`StringBuffer` 会自行实例化一个内部分配器。
61
+
62
+ 相似地,`StringBuffer` 是 `GenericStringBuffer<UTF8<> >` 的 typedef。
63
+
64
+ # 文件流 {#FileStreams}
65
+
66
+ 当要从文件解析一个 JSON,你可以把整个 JSON 读入内存并使用上述的 `StringStream`。
67
+
68
+ 然而,若 JSON 很大,或是内存有限,你可以改用 `FileReadStream`。它只会从文件读取一部分至缓冲区,然后让那部分被解析。若缓冲区的字符都被读完,它会再从文件读取下一部分。
69
+
70
+ ## FileReadStream(输入) {#FileReadStream}
71
+
72
+ `FileReadStream` 通过 `FILE` 指针读取文件。使用者需要提供一个缓冲区。
73
+
74
+ ~~~~~~~~~~cpp
75
+ #include "rapidjson/filereadstream.h"
76
+ #include <cstdio>
77
+
78
+ using namespace rapidjson;
79
+
80
+ FILE* fp = fopen("big.json", "rb"); // 非 Windows 平台使用 "r"
81
+
82
+ char readBuffer[65536];
83
+ FileReadStream is(fp, readBuffer, sizeof(readBuffer));
84
+
85
+ Document d;
86
+ d.ParseStream(is);
87
+
88
+ fclose(fp);
89
+ ~~~~~~~~~~
90
+
91
+ 与 `StringStreams` 不一样,`FileReadStream` 是一个字节流。它不处理编码。若文件并非 UTF-8 编码,可以把字节流用 `EncodedInputStream` 包装。我们很快会讨论这个问题。
92
+
93
+ 除了读取文件,使用者也可以使用 `FileReadStream` 来读取 `stdin`。
94
+
95
+ ## FileWriteStream(输出){#FileWriteStream}
96
+
97
+ `FileWriteStream` 是一个含缓冲功能的输出流。它的用法与 `FileReadStream` 非常相似。
98
+
99
+ ~~~~~~~~~~cpp
100
+ #include "rapidjson/filewritestream.h"
101
+ #include <cstdio>
102
+
103
+ using namespace rapidjson;
104
+
105
+ Document d;
106
+ d.Parse(json);
107
+ // ...
108
+
109
+ FILE* fp = fopen("output.json", "wb"); // 非 Windows 平台使用 "w"
110
+
111
+ char writeBuffer[65536];
112
+ FileWriteStream os(fp, writeBuffer, sizeof(writeBuffer));
113
+
114
+ Writer<FileWriteStream> writer(os);
115
+ d.Accept(writer);
116
+
117
+ fclose(fp);
118
+ ~~~~~~~~~~
119
+
120
+ 它也可以把输出导向 `stdout`。
121
+
122
+ # iostream 包装类 {#iostreamWrapper}
123
+
124
+ 基于用户的要求,RapidJSON 提供了正式的 `std::basic_istream` 和 `std::basic_ostream` 包装类。然而,请注意其性能会大大低于以上的其他流。
125
+
126
+ ## IStreamWrapper {#IStreamWrapper}
127
+
128
+ `IStreamWrapper` 把任何继承自 `std::istream` 的类(如 `std::istringstream`、`std::stringstream`、`std::ifstream`、`std::fstream`)包装成 RapidJSON 的输入流。
129
+
130
+ ~~~cpp
131
+ #include <rapidjson/document.h>
132
+ #include <rapidjson/istreamwrapper.h>
133
+ #include <fstream>
134
+
135
+ using namespace rapidjson;
136
+ using namespace std;
137
+
138
+ ifstream ifs("test.json");
139
+ IStreamWrapper isw(ifs);
140
+
141
+ Document d;
142
+ d.ParseStream(isw);
143
+ ~~~
144
+
145
+ 对于继承自 `std::wistream` 的类,则使用 `WIStreamWrapper`。
146
+
147
+ ## OStreamWrapper {#OStreamWrapper}
148
+
149
+ 相似地,`OStreamWrapper` 把任何继承自 `std::ostream` 的类(如 `std::ostringstream`、`std::stringstream`、`std::ofstream`、`std::fstream`)包装成 RapidJSON 的输出流。
150
+
151
+ ~~~cpp
152
+ #include <rapidjson/document.h>
153
+ #include <rapidjson/ostreamwrapper.h>
154
+ #include <rapidjson/writer.h>
155
+ #include <fstream>
156
+
157
+ using namespace rapidjson;
158
+ using namespace std;
159
+
160
+ Document d;
161
+ d.Parse(json);
162
+
163
+ // ...
164
+
165
+ ofstream ofs("output.json");
166
+ OStreamWrapper osw(ofs);
167
+
168
+ Writer<OStreamWrapper> writer(osw);
169
+ d.Accept(writer);
170
+ ~~~
171
+
172
+ 对于继承自 `std::wistream` 的类,则使用 `WIStreamWrapper`。
173
+
174
+ # 编码流 {#EncodedStreams}
175
+
176
+ 编码流(encoded streams)本身不存储 JSON,它们是通过包装字节流来提供基本的编码/解码功能。
177
+
178
+ 如上所述,我们可以直接读入 UTF-8 字节流。然而,UTF-16 及 UTF-32 有字节序(endian)问题。要正确地处理字节序,需要在读取时把字节转换成字符(如对 UTF-16 使用 `wchar_t`),以及在写入时把字符转换为字节。
179
+
180
+ 除此以外,我们也需要处理 [字节顺序标记(byte order mark, BOM)](http://en.wikipedia.org/wiki/Byte_order_mark)。当从一个字节流读取时,需要检测 BOM,或者仅仅是把存在的 BOM 消去。当把 JSON 写入字节流时,也可选择写入 BOM。
181
+
182
+ 若一个流的编码在编译期已知,你可使用 `EncodedInputStream` 及 `EncodedOutputStream`。若一个流可能存储 UTF-8、UTF-16LE、UTF-16BE、UTF-32LE、UTF-32BE 的 JSON,并且编码只能在运行时得知,你便可以使用 `AutoUTFInputStream` 及 `AutoUTFOutputStream`。这些流定义在 `rapidjson/encodedstream.h`。
183
+
184
+ 注意到,这些编码流可以施于文件以外的流。例如,你可以用编码流包装内存中的文件或自定义的字节流。
185
+
186
+ ## EncodedInputStream {#EncodedInputStream}
187
+
188
+ `EncodedInputStream` 含两个模板参数。第一个是 `Encoding` 类型,例如定义于 `rapidjson/encodings.h` 的 `UTF8`、`UTF16LE`。第二个参数是被包装的流的类型。
189
+
190
+ ~~~~~~~~~~cpp
191
+ #include "rapidjson/document.h"
192
+ #include "rapidjson/filereadstream.h" // FileReadStream
193
+ #include "rapidjson/encodedstream.h" // EncodedInputStream
194
+ #include <cstdio>
195
+
196
+ using namespace rapidjson;
197
+
198
+ FILE* fp = fopen("utf16le.json", "rb"); // 非 Windows 平台使用 "r"
199
+
200
+ char readBuffer[256];
201
+ FileReadStream bis(fp, readBuffer, sizeof(readBuffer));
202
+
203
+ EncodedInputStream<UTF16LE<>, FileReadStream> eis(bis); // 用 eis 包装 bis
204
+
205
+ Document d; // Document 为 GenericDocument<UTF8<> >
206
+ d.ParseStream<0, UTF16LE<> >(eis); // 把 UTF-16LE 文件解析至内存中的 UTF-8
207
+
208
+ fclose(fp);
209
+ ~~~~~~~~~~
210
+
211
+ ## EncodedOutputStream {#EncodedOutputStream}
212
+
213
+ `EncodedOutputStream` 也是相似的,但它的构造函数有一个 `bool putBOM` 参数,用于控制是否在输出字节流写入 BOM。
214
+
215
+ ~~~~~~~~~~cpp
216
+ #include "rapidjson/filewritestream.h" // FileWriteStream
217
+ #include "rapidjson/encodedstream.h" // EncodedOutputStream
218
+ #include <cstdio>
219
+
220
+ Document d; // Document 为 GenericDocument<UTF8<> >
221
+ // ...
222
+
223
+ FILE* fp = fopen("output_utf32le.json", "wb"); // 非 Windows 平台使用 "w"
224
+
225
+ char writeBuffer[256];
226
+ FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer));
227
+
228
+ typedef EncodedOutputStream<UTF32LE<>, FileWriteStream> OutputStream;
229
+ OutputStream eos(bos, true); // 写入 BOM
230
+
231
+ Writer<OutputStream, UTF32LE<>, UTF8<>> writer(eos);
232
+ d.Accept(writer); // 这里从内存的 UTF-8 生成 UTF32-LE 文件
233
+
234
+ fclose(fp);
235
+ ~~~~~~~~~~
236
+
237
+ ## AutoUTFInputStream {#AutoUTFInputStream}
238
+
239
+ 有时候,应用软件可能需要㲃理所有可支持的 JSON 编码。`AutoUTFInputStream` 会先使用 BOM 来检测编码。若 BOM 不存在,它便会使用合法 JSON 的特性来检测。若两种方法都失败,它就会倒退至构造函数提供的 UTF 类型。
240
+
241
+ 由于字符(编码单元/code unit)可能是 8 位、16 位或 32 位,`AutoUTFInputStream` 需要一个能至少储存 32 位的字符类型。我们可以使用 `unsigned` 作为模板参数:
242
+
243
+ ~~~~~~~~~~cpp
244
+ #include "rapidjson/document.h"
245
+ #include "rapidjson/filereadstream.h" // FileReadStream
246
+ #include "rapidjson/encodedstream.h" // AutoUTFInputStream
247
+ #include <cstdio>
248
+
249
+ using namespace rapidjson;
250
+
251
+ FILE* fp = fopen("any.json", "rb"); // 非 Windows 平台使用 "r"
252
+
253
+ char readBuffer[256];
254
+ FileReadStream bis(fp, readBuffer, sizeof(readBuffer));
255
+
256
+ AutoUTFInputStream<unsigned, FileReadStream> eis(bis); // 用 eis 包装 bis
257
+
258
+ Document d; // Document 为 GenericDocument<UTF8<> >
259
+ d.ParseStream<0, AutoUTF<unsigned> >(eis); // 把任何 UTF 编码的文件解析至内存中的 UTF-8
260
+
261
+ fclose(fp);
262
+ ~~~~~~~~~~
263
+
264
+ 当要指定流的编码,可使用上面例子中 `ParseStream()` 的参数 `AutoUTF<CharType>`。
265
+
266
+ 你可以使用 `UTFType GetType()` 去获取 UTF 类型,并且用 `HasBOM()` 检测输入流是否含有 BOM。
267
+
268
+ ## AutoUTFOutputStream {#AutoUTFOutputStream}
269
+
270
+ 相似地,要在运行时选择输出的编码,我们可使用 `AutoUTFOutputStream`。这个类本身并非「自动」。你需要在运行时指定 UTF 类型,以及是否写入 BOM。
271
+
272
+ ~~~~~~~~~~cpp
273
+ using namespace rapidjson;
274
+
275
+ void WriteJSONFile(FILE* fp, UTFType type, bool putBOM, const Document& d) {
276
+ char writeBuffer[256];
277
+ FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer));
278
+
279
+ typedef AutoUTFOutputStream<unsigned, FileWriteStream> OutputStream;
280
+ OutputStream eos(bos, type, putBOM);
281
+
282
+ Writer<OutputStream, UTF8<>, AutoUTF<> > writer;
283
+ d.Accept(writer);
284
+ }
285
+ ~~~~~~~~~~
286
+
287
+ `AutoUTFInputStream`/`AutoUTFOutputStream` 是比 `EncodedInputStream`/`EncodedOutputStream` 方便。但前者会产生一点运行期额外开销。
288
+
289
+ # 自定义流 {#CustomStream}
290
+
291
+ 除了内存/文件流,使用者可创建自行定义适配 RapidJSON API 的流类。例如,你可以创建网络流、从压缩文件读取的流等等。
292
+
293
+ RapidJSON 利用模板结合不同的类型。只要一个类包含所有所需的接口,就可以作为一个流。流的接合定义在 `rapidjson/rapidjson.h` 的注释里:
294
+
295
+ ~~~~~~~~~~cpp
296
+ concept Stream {
297
+ typename Ch; //!< 流的字符类型
298
+
299
+ //! 从流读取当前字符,不移动读取指针(read cursor)
300
+ Ch Peek() const;
301
+
302
+ //! 从流读取当前字符,移动读取指针至下一字符。
303
+ Ch Take();
304
+
305
+ //! 获取读取指针。
306
+ //! \return 从开始以来所读过的字符数量。
307
+ size_t Tell();
308
+
309
+ //! 从当前读取指针开始写入操作。
310
+ //! \return 返回开始写入的指针。
311
+ Ch* PutBegin();
312
+
313
+ //! 写入一个字符。
314
+ void Put(Ch c);
315
+
316
+ //! 清空缓冲区。
317
+ void Flush();
318
+
319
+ //! 完成写作操作。
320
+ //! \param begin PutBegin() 返回的开始写入指针。
321
+ //! \return 已写入的字符数量。
322
+ size_t PutEnd(Ch* begin);
323
+ }
324
+ ~~~~~~~~~~
325
+
326
+ 输入流必须实现 `Peek()`、`Take()` 及 `Tell()`。
327
+ 输出流必须实现 `Put()` 及 `Flush()`。
328
+ `PutBegin()` 及 `PutEnd()` 是特殊的接口,仅用于原位(*in situ*)解析。一般的流不需实现它们。然而,即使接口不需用于某些流,仍然需要提供空实现,否则会产生编译错误。
329
+
330
+ ## 例子:istream 的包装类 {#ExampleIStreamWrapper}
331
+
332
+ 以下的简单例子是 `std::istream` 的包装类,它只需现 3 个函数。
333
+
334
+ ~~~~~~~~~~cpp
335
+ class MyIStreamWrapper {
336
+ public:
337
+ typedef char Ch;
338
+
339
+ MyIStreamWrapper(std::istream& is) : is_(is) {
340
+ }
341
+
342
+ Ch Peek() const { // 1
343
+ int c = is_.peek();
344
+ return c == std::char_traits<char>::eof() ? '\0' : (Ch)c;
345
+ }
346
+
347
+ Ch Take() { // 2
348
+ int c = is_.get();
349
+ return c == std::char_traits<char>::eof() ? '\0' : (Ch)c;
350
+ }
351
+
352
+ size_t Tell() const { return (size_t)is_.tellg(); } // 3
353
+
354
+ Ch* PutBegin() { assert(false); return 0; }
355
+ void Put(Ch) { assert(false); }
356
+ void Flush() { assert(false); }
357
+ size_t PutEnd(Ch*) { assert(false); return 0; }
358
+
359
+ private:
360
+ MyIStreamWrapper(const MyIStreamWrapper&);
361
+ MyIStreamWrapper& operator=(const MyIStreamWrapper&);
362
+
363
+ std::istream& is_;
364
+ };
365
+ ~~~~~~~~~~
366
+
367
+ 使用者能用它来包装 `std::stringstream`、`std::ifstream` 的实例。
368
+
369
+ ~~~~~~~~~~cpp
370
+ const char* json = "[1,2,3,4]";
371
+ std::stringstream ss(json);
372
+ MyIStreamWrapper is(ss);
373
+
374
+ Document d;
375
+ d.ParseStream(is);
376
+ ~~~~~~~~~~
377
+
378
+ 但要注意,由于标准库的内部开销问,此实现的性能可能不如 RapidJSON 的内存/文件流。
379
+
380
+ ## 例子:ostream 的包装类 {#ExampleOStreamWrapper}
381
+
382
+ 以下的例子是 `std::istream` 的包装类,它只需实现 2 个函数。
383
+
384
+ ~~~~~~~~~~cpp
385
+ class MyOStreamWrapper {
386
+ public:
387
+ typedef char Ch;
388
+
389
+ OStreamWrapper(std::ostream& os) : os_(os) {
390
+ }
391
+
392
+ Ch Peek() const { assert(false); return '\0'; }
393
+ Ch Take() { assert(false); return '\0'; }
394
+ size_t Tell() const { }
395
+
396
+ Ch* PutBegin() { assert(false); return 0; }
397
+ void Put(Ch c) { os_.put(c); } // 1
398
+ void Flush() { os_.flush(); } // 2
399
+ size_t PutEnd(Ch*) { assert(false); return 0; }
400
+
401
+ private:
402
+ MyOStreamWrapper(const MyOStreamWrapper&);
403
+ MyOStreamWrapper& operator=(const MyOStreamWrapper&);
404
+
405
+ std::ostream& os_;
406
+ };
407
+ ~~~~~~~~~~
408
+
409
+ 使用者能用它来包装 `std::stringstream`、`std::ofstream` 的实例。
410
+
411
+ ~~~~~~~~~~cpp
412
+ Document d;
413
+ // ...
414
+
415
+ std::stringstream ss;
416
+ MyOStreamWrapper os(ss);
417
+
418
+ Writer<MyOStreamWrapper> writer(os);
419
+ d.Accept(writer);
420
+ ~~~~~~~~~~
421
+
422
+ 但要注意,由于标准库的内部开销问,此实现的性能可能不如 RapidJSON 的内存/文件流。
423
+
424
+ # 总结 {#Summary}
425
+
426
+ 本节描述了 RapidJSON 提供的各种流的类。内存流很简单。若 JSON 存储在文件中,文件流可减少 JSON 解析及生成所需的内存量。编码流在字节流和字符流之间作转换。最后,使用者可使用一个简单接口创建自定义的流。
@@ -0,0 +1,536 @@
1
+ # Tutorial
2
+
3
+ This tutorial introduces the basics of the Document Object Model(DOM) API.
4
+
5
+ As shown in [Usage at a glance](@ref index), JSON can be parsed into a DOM, and then the DOM can be queried and modified easily, and finally be converted back to JSON.
6
+
7
+ [TOC]
8
+
9
+ # Value & Document {#ValueDocument}
10
+
11
+ Each JSON value is stored in a type called `Value`. A `Document`, representing the DOM, contains the root `Value` of the DOM tree. All public types and functions of RapidJSON are defined in the `rapidjson` namespace.
12
+
13
+ # Query Value {#QueryValue}
14
+
15
+ In this section, we will use excerpt of `example/tutorial/tutorial.cpp`.
16
+
17
+ Assume we have the following JSON stored in a C string (`const char* json`):
18
+ ~~~~~~~~~~js
19
+ {
20
+ "hello": "world",
21
+ "t": true ,
22
+ "f": false,
23
+ "n": null,
24
+ "i": 123,
25
+ "pi": 3.1416,
26
+ "a": [1, 2, 3, 4]
27
+ }
28
+ ~~~~~~~~~~
29
+
30
+ Parse it into a `Document`:
31
+ ~~~~~~~~~~cpp
32
+ #include "rapidjson/document.h"
33
+
34
+ using namespace rapidjson;
35
+
36
+ // ...
37
+ Document document;
38
+ document.Parse(json);
39
+ ~~~~~~~~~~
40
+
41
+ The JSON is now parsed into `document` as a *DOM tree*:
42
+
43
+ ![DOM in the tutorial](diagram/tutorial.png)
44
+
45
+ Since the update to RFC 7159, the root of a conforming JSON document can be any JSON value. In earlier RFC 4627, only objects or arrays were allowed as root values. In this case, the root is an object.
46
+ ~~~~~~~~~~cpp
47
+ assert(document.IsObject());
48
+ ~~~~~~~~~~
49
+
50
+ Let's query whether a `"hello"` member exists in the root object. Since a `Value` can contain different types of value, we may need to verify its type and use suitable API to obtain the value. In this example, `"hello"` member associates with a JSON string.
51
+ ~~~~~~~~~~cpp
52
+ assert(document.HasMember("hello"));
53
+ assert(document["hello"].IsString());
54
+ printf("hello = %s\n", document["hello"].GetString());
55
+ ~~~~~~~~~~
56
+
57
+ ~~~~~~~~~~
58
+ hello = world
59
+ ~~~~~~~~~~
60
+
61
+ JSON true/false values are represented as `bool`.
62
+ ~~~~~~~~~~cpp
63
+ assert(document["t"].IsBool());
64
+ printf("t = %s\n", document["t"].GetBool() ? "true" : "false");
65
+ ~~~~~~~~~~
66
+
67
+ ~~~~~~~~~~
68
+ t = true
69
+ ~~~~~~~~~~
70
+
71
+ JSON null can be queried with `IsNull()`.
72
+ ~~~~~~~~~~cpp
73
+ printf("n = %s\n", document["n"].IsNull() ? "null" : "?");
74
+ ~~~~~~~~~~
75
+
76
+ ~~~~~~~~~~
77
+ n = null
78
+ ~~~~~~~~~~
79
+
80
+ JSON number type represents all numeric values. However, C++ needs more specific type for manipulation.
81
+
82
+ ~~~~~~~~~~cpp
83
+ assert(document["i"].IsNumber());
84
+
85
+ // In this case, IsUint()/IsInt64()/IsUInt64() also return true.
86
+ assert(document["i"].IsInt());
87
+ printf("i = %d\n", document["i"].GetInt());
88
+ // Alternative (int)document["i"]
89
+
90
+ assert(document["pi"].IsNumber());
91
+ assert(document["pi"].IsDouble());
92
+ printf("pi = %g\n", document["pi"].GetDouble());
93
+ ~~~~~~~~~~
94
+
95
+ ~~~~~~~~~~
96
+ i = 123
97
+ pi = 3.1416
98
+ ~~~~~~~~~~
99
+
100
+ JSON array contains a number of elements.
101
+ ~~~~~~~~~~cpp
102
+ // Using a reference for consecutive access is handy and faster.
103
+ const Value& a = document["a"];
104
+ assert(a.IsArray());
105
+ for (SizeType i = 0; i < a.Size(); i++) // Uses SizeType instead of size_t
106
+ printf("a[%d] = %d\n", i, a[i].GetInt());
107
+ ~~~~~~~~~~
108
+
109
+ ~~~~~~~~~~
110
+ a[0] = 1
111
+ a[1] = 2
112
+ a[2] = 3
113
+ a[3] = 4
114
+ ~~~~~~~~~~
115
+
116
+ Note that, RapidJSON does not automatically convert values between JSON types. If a value is a string, it is invalid to call `GetInt()`, for example. In debug mode it will fail an assertion. In release mode, the behavior is undefined.
117
+
118
+ In the following sections we discuss details about querying individual types.
119
+
120
+ ## Query Array {#QueryArray}
121
+
122
+ By default, `SizeType` is typedef of `unsigned`. In most systems, an array is limited to store up to 2^32-1 elements.
123
+
124
+ You may access the elements in an array by integer literal, for example, `a[0]`, `a[1]`, `a[2]`.
125
+
126
+ Array is similar to `std::vector`: instead of using indices, you may also use iterator to access all the elements.
127
+ ~~~~~~~~~~cpp
128
+ for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
129
+ printf("%d ", itr->GetInt());
130
+ ~~~~~~~~~~
131
+
132
+ And other familiar query functions:
133
+ * `SizeType Capacity() const`
134
+ * `bool Empty() const`
135
+
136
+ ### Range-based For Loop (New in v1.1.0)
137
+
138
+ When C++11 is enabled, you can use range-based for loop to access all elements in an array.
139
+
140
+ ~~~~~~~~~~cpp
141
+ for (auto& v : a.GetArray())
142
+ printf("%d ", v.GetInt());
143
+ ~~~~~~~~~~
144
+
145
+ ## Query Object {#QueryObject}
146
+
147
+ Similar to Array, we can access all object members by iterator:
148
+
149
+ ~~~~~~~~~~cpp
150
+ static const char* kTypeNames[] =
151
+ { "Null", "False", "True", "Object", "Array", "String", "Number" };
152
+
153
+ for (Value::ConstMemberIterator itr = document.MemberBegin();
154
+ itr != document.MemberEnd(); ++itr)
155
+ {
156
+ printf("Type of member %s is %s\n",
157
+ itr->name.GetString(), kTypeNames[itr->value.GetType()]);
158
+ }
159
+ ~~~~~~~~~~
160
+
161
+ ~~~~~~~~~~
162
+ Type of member hello is String
163
+ Type of member t is True
164
+ Type of member f is False
165
+ Type of member n is Null
166
+ Type of member i is Number
167
+ Type of member pi is Number
168
+ Type of member a is Array
169
+ ~~~~~~~~~~
170
+
171
+ Note that, when `operator[](const char*)` cannot find the member, it will fail an assertion.
172
+
173
+ If we are unsure whether a member exists, we need to call `HasMember()` before calling `operator[](const char*)`. However, this incurs two lookup. A better way is to call `FindMember()`, which can check the existence of member and obtain its value at once:
174
+
175
+ ~~~~~~~~~~cpp
176
+ Value::ConstMemberIterator itr = document.FindMember("hello");
177
+ if (itr != document.MemberEnd())
178
+ printf("%s\n", itr->value.GetString());
179
+ ~~~~~~~~~~
180
+
181
+ ### Range-based For Loop (New in v1.1.0)
182
+
183
+ When C++11 is enabled, you can use range-based for loop to access all members in an object.
184
+
185
+ ~~~~~~~~~~cpp
186
+ for (auto& m : document.GetObject())
187
+ printf("Type of member %s is %s\n",
188
+ m.name.GetString(), kTypeNames[m.value.GetType()]);
189
+ ~~~~~~~~~~
190
+
191
+ ## Querying Number {#QueryNumber}
192
+
193
+ JSON provides a single numerical type called Number. Number can be an integer or a real number. RFC 4627 says the range of Number is specified by the parser implementation.
194
+
195
+ As C++ provides several integer and floating point number types, the DOM tries to handle these with the widest possible range and good performance.
196
+
197
+ When a Number is parsed, it is stored in the DOM as one of the following types:
198
+
199
+ Type | Description
200
+ -----------|---------------------------------------
201
+ `unsigned` | 32-bit unsigned integer
202
+ `int` | 32-bit signed integer
203
+ `uint64_t` | 64-bit unsigned integer
204
+ `int64_t` | 64-bit signed integer
205
+ `double` | 64-bit double precision floating point
206
+
207
+ When querying a number, you can check whether the number can be obtained as the target type:
208
+
209
+ Checking | Obtaining
210
+ ------------------|---------------------
211
+ `bool IsNumber()` | N/A
212
+ `bool IsUint()` | `unsigned GetUint()`
213
+ `bool IsInt()` | `int GetInt()`
214
+ `bool IsUint64()` | `uint64_t GetUint64()`
215
+ `bool IsInt64()` | `int64_t GetInt64()`
216
+ `bool IsDouble()` | `double GetDouble()`
217
+
218
+ Note that, an integer value may be obtained in various ways without conversion. For example, A value `x` containing 123 will make `x.IsInt() == x.IsUint() == x.IsInt64() == x.IsUint64() == true`. But a value `y` containing -3000000000 will only make `x.IsInt64() == true`.
219
+
220
+ When obtaining the numeric values, `GetDouble()` will convert internal integer representation to a `double`. Note that, `int` and `unsigned` can be safely converted to `double`, but `int64_t` and `uint64_t` may lose precision (since mantissa of `double` is only 52-bits).
221
+
222
+ ## Query String {#QueryString}
223
+
224
+ In addition to `GetString()`, the `Value` class also contains `GetStringLength()`. Here explains why.
225
+
226
+ According to RFC 4627, JSON strings can contain Unicode character `U+0000`, which must be escaped as `"\u0000"`. The problem is that, C/C++ often uses null-terminated string, which treats ``\0'` as the terminator symbol.
227
+
228
+ To conform RFC 4627, RapidJSON supports string containing `U+0000`. If you need to handle this, you can use `GetStringLength()` to obtain the correct string length.
229
+
230
+ For example, after parsing a the following JSON to `Document d`:
231
+
232
+ ~~~~~~~~~~js
233
+ { "s" : "a\u0000b" }
234
+ ~~~~~~~~~~
235
+ The correct length of the value `"a\u0000b"` is 3. But `strlen()` returns 1.
236
+
237
+ `GetStringLength()` can also improve performance, as user may often need to call `strlen()` for allocating buffer.
238
+
239
+ Besides, `std::string` also support a constructor:
240
+
241
+ ~~~~~~~~~~cpp
242
+ string(const char* s, size_t count);
243
+ ~~~~~~~~~~
244
+
245
+ which accepts the length of string as parameter. This constructor supports storing null character within the string, and should also provide better performance.
246
+
247
+ ## Comparing values
248
+
249
+ You can use `==` and `!=` to compare values. Two values are equal if and only if they are have same type and contents. You can also compare values with primitive types. Here is an example.
250
+
251
+ ~~~~~~~~~~cpp
252
+ if (document["hello"] == document["n"]) /*...*/; // Compare values
253
+ if (document["hello"] == "world") /*...*/; // Compare value with literal string
254
+ if (document["i"] != 123) /*...*/; // Compare with integers
255
+ if (document["pi"] != 3.14) /*...*/; // Compare with double.
256
+ ~~~~~~~~~~
257
+
258
+ Array/object compares their elements/members in order. They are equal if and only if their whole subtrees are equal.
259
+
260
+ Note that, currently if an object contains duplicated named member, comparing equality with any object is always `false`.
261
+
262
+ # Create/Modify Values {#CreateModifyValues}
263
+
264
+ There are several ways to create values. After a DOM tree is created and/or modified, it can be saved as JSON again using `Writer`.
265
+
266
+ ## Change Value Type {#ChangeValueType}
267
+ When creating a Value or Document by default constructor, its type is Null. To change its type, call `SetXXX()` or assignment operator, for example:
268
+
269
+ ~~~~~~~~~~cpp
270
+ Document d; // Null
271
+ d.SetObject();
272
+
273
+ Value v; // Null
274
+ v.SetInt(10);
275
+ v = 10; // Shortcut, same as above
276
+ ~~~~~~~~~~
277
+
278
+ ### Overloaded Constructors
279
+ There are also overloaded constructors for several types:
280
+
281
+ ~~~~~~~~~~cpp
282
+ Value b(true); // calls Value(bool)
283
+ Value i(-123); // calls Value(int)
284
+ Value u(123u); // calls Value(unsigned)
285
+ Value d(1.5); // calls Value(double)
286
+ ~~~~~~~~~~
287
+
288
+ To create empty object or array, you may use `SetObject()`/`SetArray()` after default constructor, or using the `Value(Type)` in one shot:
289
+
290
+ ~~~~~~~~~~cpp
291
+ Value o(kObjectType);
292
+ Value a(kArrayType);
293
+ ~~~~~~~~~~
294
+
295
+ ## Move Semantics {#MoveSemantics}
296
+
297
+ A very special decision during design of RapidJSON is that, assignment of value does not copy the source value to destination value. Instead, the value from source is moved to the destination. For example,
298
+
299
+ ~~~~~~~~~~cpp
300
+ Value a(123);
301
+ Value b(456);
302
+ b = a; // a becomes a Null value, b becomes number 123.
303
+ ~~~~~~~~~~
304
+
305
+ ![Assignment with move semantics.](diagram/move1.png)
306
+
307
+ Why? What is the advantage of this semantics?
308
+
309
+ The simple answer is performance. For fixed size JSON types (Number, True, False, Null), copying them is fast and easy. However, For variable size JSON types (String, Array, Object), copying them will incur a lot of overheads. And these overheads are often unnoticed. Especially when we need to create temporary object, copy it to another variable, and then destruct it.
310
+
311
+ For example, if normal *copy* semantics was used:
312
+
313
+ ~~~~~~~~~~cpp
314
+ Document d;
315
+ Value o(kObjectType);
316
+ {
317
+ Value contacts(kArrayType);
318
+ // adding elements to contacts array.
319
+ // ...
320
+ o.AddMember("contacts", contacts, d.GetAllocator()); // deep clone contacts (may be with lots of allocations)
321
+ // destruct contacts.
322
+ }
323
+ ~~~~~~~~~~
324
+
325
+ ![Copy semantics makes a lots of copy operations.](diagram/move2.png)
326
+
327
+ The object `o` needs to allocate a buffer of same size as contacts, makes a deep clone of it, and then finally contacts is destructed. This will incur a lot of unnecessary allocations/deallocations and memory copying.
328
+
329
+ There are solutions to prevent actual copying these data, such as reference counting and garbage collection(GC).
330
+
331
+ To make RapidJSON simple and fast, we chose to use *move* semantics for assignment. It is similar to `std::auto_ptr` which transfer ownership during assignment. Move is much faster and simpler, it just destructs the original value, `memcpy()` the source to destination, and finally sets the source as Null type.
332
+
333
+ So, with move semantics, the above example becomes:
334
+
335
+ ~~~~~~~~~~cpp
336
+ Document d;
337
+ Value o(kObjectType);
338
+ {
339
+ Value contacts(kArrayType);
340
+ // adding elements to contacts array.
341
+ o.AddMember("contacts", contacts, d.GetAllocator()); // just memcpy() of contacts itself to the value of new member (16 bytes)
342
+ // contacts became Null here. Its destruction is trivial.
343
+ }
344
+ ~~~~~~~~~~
345
+
346
+ ![Move semantics makes no copying.](diagram/move3.png)
347
+
348
+ This is called move assignment operator in C++11. As RapidJSON supports C++03, it adopts move semantics using assignment operator, and all other modifying function like `AddMember()`, `PushBack()`.
349
+
350
+ ### Move semantics and temporary values {#TemporaryValues}
351
+
352
+ Sometimes, it is convenient to construct a Value in place, before passing it to one of the "moving" functions, like `PushBack()` or `AddMember()`. As temporary objects can't be converted to proper Value references, the convenience function `Move()` is available:
353
+
354
+ ~~~~~~~~~~cpp
355
+ Value a(kArrayType);
356
+ Document::AllocatorType& allocator = document.GetAllocator();
357
+ // a.PushBack(Value(42), allocator); // will not compile
358
+ a.PushBack(Value().SetInt(42), allocator); // fluent API
359
+ a.PushBack(Value(42).Move(), allocator); // same as above
360
+ ~~~~~~~~~~
361
+
362
+ ## Create String {#CreateString}
363
+ RapidJSON provides two strategies for storing string.
364
+
365
+ 1. copy-string: allocates a buffer, and then copy the source data into it.
366
+ 2. const-string: simply store a pointer of string.
367
+
368
+ Copy-string is always safe because it owns a copy of the data. Const-string can be used for storing a string literal, and for in-situ parsing which will be mentioned in the DOM section.
369
+
370
+ To make memory allocation customizable, RapidJSON requires users to pass an instance of allocator, whenever an operation may require allocation. This design is needed to prevent storing a allocator (or Document) pointer per Value.
371
+
372
+ Therefore, when we assign a copy-string, we call this overloaded `SetString()` with allocator:
373
+
374
+ ~~~~~~~~~~cpp
375
+ Document document;
376
+ Value author;
377
+ char buffer[10];
378
+ int len = sprintf(buffer, "%s %s", "Milo", "Yip"); // dynamically created string.
379
+ author.SetString(buffer, len, document.GetAllocator());
380
+ memset(buffer, 0, sizeof(buffer));
381
+ // author.GetString() still contains "Milo Yip" after buffer is destroyed
382
+ ~~~~~~~~~~
383
+
384
+ In this example, we get the allocator from a `Document` instance. This is a common idiom when using RapidJSON. But you may use other instances of allocator.
385
+
386
+ Besides, the above `SetString()` requires length. This can handle null characters within a string. There is another `SetString()` overloaded function without the length parameter. And it assumes the input is null-terminated and calls a `strlen()`-like function to obtain the length.
387
+
388
+ Finally, for a string literal or string with a safe life-cycle one can use the const-string version of `SetString()`, which lacks an allocator parameter. For string literals (or constant character arrays), simply passing the literal as parameter is safe and efficient:
389
+
390
+ ~~~~~~~~~~cpp
391
+ Value s;
392
+ s.SetString("rapidjson"); // can contain null character, length derived at compile time
393
+ s = "rapidjson"; // shortcut, same as above
394
+ ~~~~~~~~~~
395
+
396
+ For a character pointer, RapidJSON requires it to be marked as safe before using it without copying. This can be achieved by using the `StringRef` function:
397
+
398
+ ~~~~~~~~~cpp
399
+ const char * cstr = getenv("USER");
400
+ size_t cstr_len = ...; // in case length is available
401
+ Value s;
402
+ // s.SetString(cstr); // will not compile
403
+ s.SetString(StringRef(cstr)); // ok, assume safe lifetime, null-terminated
404
+ s = StringRef(cstr); // shortcut, same as above
405
+ s.SetString(StringRef(cstr,cstr_len)); // faster, can contain null character
406
+ s = StringRef(cstr,cstr_len); // shortcut, same as above
407
+
408
+ ~~~~~~~~~
409
+
410
+ ## Modify Array {#ModifyArray}
411
+ Value with array type provides an API similar to `std::vector`.
412
+
413
+ * `Clear()`
414
+ * `Reserve(SizeType, Allocator&)`
415
+ * `Value& PushBack(Value&, Allocator&)`
416
+ * `template <typename T> GenericValue& PushBack(T, Allocator&)`
417
+ * `Value& PopBack()`
418
+ * `ValueIterator Erase(ConstValueIterator pos)`
419
+ * `ValueIterator Erase(ConstValueIterator first, ConstValueIterator last)`
420
+
421
+ Note that, `Reserve(...)` and `PushBack(...)` may allocate memory for the array elements, therefore requiring an allocator.
422
+
423
+ Here is an example of `PushBack()`:
424
+
425
+ ~~~~~~~~~~cpp
426
+ Value a(kArrayType);
427
+ Document::AllocatorType& allocator = document.GetAllocator();
428
+
429
+ for (int i = 5; i <= 10; i++)
430
+ a.PushBack(i, allocator); // allocator is needed for potential realloc().
431
+
432
+ // Fluent interface
433
+ a.PushBack("Lua", allocator).PushBack("Mio", allocator);
434
+ ~~~~~~~~~~
435
+
436
+ This API differs from STL in that `PushBack()`/`PopBack()` return the array reference itself. This is called _fluent interface_.
437
+
438
+ If you want to add a non-constant string or a string without sufficient lifetime (see [Create String](#CreateString)) to the array, you need to create a string Value by using the copy-string API. To avoid the need for an intermediate variable, you can use a [temporary value](#TemporaryValues) in place:
439
+
440
+ ~~~~~~~~~~cpp
441
+ // in-place Value parameter
442
+ contact.PushBack(Value("copy", document.GetAllocator()).Move(), // copy string
443
+ document.GetAllocator());
444
+
445
+ // explicit parameters
446
+ Value val("key", document.GetAllocator()); // copy string
447
+ contact.PushBack(val, document.GetAllocator());
448
+ ~~~~~~~~~~
449
+
450
+ ## Modify Object {#ModifyObject}
451
+ The Object class is a collection of key-value pairs (members). Each key must be a string value. To modify an object, either add or remove members. The following API is for adding members:
452
+
453
+ * `Value& AddMember(Value&, Value&, Allocator& allocator)`
454
+ * `Value& AddMember(StringRefType, Value&, Allocator&)`
455
+ * `template <typename T> Value& AddMember(StringRefType, T value, Allocator&)`
456
+
457
+ Here is an example.
458
+
459
+ ~~~~~~~~~~cpp
460
+ Value contact(kObject);
461
+ contact.AddMember("name", "Milo", document.GetAllocator());
462
+ contact.AddMember("married", true, document.GetAllocator());
463
+ ~~~~~~~~~~
464
+
465
+ The name parameter with `StringRefType` is similar to the interface of the `SetString` function for string values. These overloads are used to avoid the need for copying the `name` string, since constant key names are very common in JSON objects.
466
+
467
+ If you need to create a name from a non-constant string or a string without sufficient lifetime (see [Create String](#CreateString)), you need to create a string Value by using the copy-string API. To avoid the need for an intermediate variable, you can use a [temporary value](#TemporaryValues) in place:
468
+
469
+ ~~~~~~~~~~cpp
470
+ // in-place Value parameter
471
+ contact.AddMember(Value("copy", document.GetAllocator()).Move(), // copy string
472
+ Value().Move(), // null value
473
+ document.GetAllocator());
474
+
475
+ // explicit parameters
476
+ Value key("key", document.GetAllocator()); // copy string name
477
+ Value val(42); // some value
478
+ contact.AddMember(key, val, document.GetAllocator());
479
+ ~~~~~~~~~~
480
+
481
+ For removing members, there are several choices:
482
+
483
+ * `bool RemoveMember(const Ch* name)`: Remove a member by search its name (linear time complexity).
484
+ * `bool RemoveMember(const Value& name)`: same as above but `name` is a Value.
485
+ * `MemberIterator RemoveMember(MemberIterator)`: Remove a member by iterator (_constant_ time complexity).
486
+ * `MemberIterator EraseMember(MemberIterator)`: similar to the above but it preserves order of members (linear time complexity).
487
+ * `MemberIterator EraseMember(MemberIterator first, MemberIterator last)`: remove a range of members, preserves order (linear time complexity).
488
+
489
+ `MemberIterator RemoveMember(MemberIterator)` uses a "move-last" trick to achieve constant time complexity. Basically the member at iterator is destructed, and then the last element is moved to that position. So the order of the remaining members are changed.
490
+
491
+ ## Deep Copy Value {#DeepCopyValue}
492
+ If we really need to copy a DOM tree, we can use two APIs for deep copy: constructor with allocator, and `CopyFrom()`.
493
+
494
+ ~~~~~~~~~~cpp
495
+ Document d;
496
+ Document::AllocatorType& a = d.GetAllocator();
497
+ Value v1("foo");
498
+ // Value v2(v1); // not allowed
499
+
500
+ Value v2(v1, a); // make a copy
501
+ assert(v1.IsString()); // v1 untouched
502
+ d.SetArray().PushBack(v1, a).PushBack(v2, a);
503
+ assert(v1.IsNull() && v2.IsNull()); // both moved to d
504
+
505
+ v2.CopyFrom(d, a); // copy whole document to v2
506
+ assert(d.IsArray() && d.Size() == 2); // d untouched
507
+ v1.SetObject().AddMember("array", v2, a);
508
+ d.PushBack(v1, a);
509
+ ~~~~~~~~~~
510
+
511
+ ## Swap Values {#SwapValues}
512
+
513
+ `Swap()` is also provided.
514
+
515
+ ~~~~~~~~~~cpp
516
+ Value a(123);
517
+ Value b("Hello");
518
+ a.Swap(b);
519
+ assert(a.IsString());
520
+ assert(b.IsInt());
521
+ ~~~~~~~~~~
522
+
523
+ Swapping two DOM trees is fast (constant time), despite the complexity of the trees.
524
+
525
+ # What's next {#WhatsNext}
526
+
527
+ This tutorial shows the basics of DOM tree query and manipulation. There are several important concepts in RapidJSON:
528
+
529
+ 1. [Streams](doc/stream.md) are channels for reading/writing JSON, which can be a in-memory string, or file stream, etc. User can also create their streams.
530
+ 2. [Encoding](doc/encoding.md) defines which character encoding is used in streams and memory. RapidJSON also provide Unicode conversion/validation internally.
531
+ 3. [DOM](doc/dom.md)'s basics are already covered in this tutorial. Uncover more advanced features such as *in situ* parsing, other parsing options and advanced usages.
532
+ 4. [SAX](doc/sax.md) is the foundation of parsing/generating facility in RapidJSON. Learn how to use `Reader`/`Writer` to implement even faster applications. Also try `PrettyWriter` to format the JSON.
533
+ 5. [Performance](doc/performance.md) shows some in-house and third-party benchmarks.
534
+ 6. [Internals](doc/internals.md) describes some internal designs and techniques of RapidJSON.
535
+
536
+ You may also refer to the [FAQ](doc/faq.md), API documentation, examples and unit tests.