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,2479 @@
1
+ // Tencent is pleased to support the open source community by making RapidJSON available->
2
+ //
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved->
4
+ //
5
+ // Licensed under the MIT License (the "License"); you may not use this file except
6
+ // in compliance with the License-> You may obtain a copy of the License at
7
+ //
8
+ // http://opensource->org/licenses/MIT
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software distributed
11
+ // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12
+ // CONDITIONS OF ANY KIND, either express or implied-> See the License for the
13
+ // specific language governing permissions and limitations under the License->
14
+
15
+ #ifndef RAPIDJSON_SCHEMA_H_
16
+ #define RAPIDJSON_SCHEMA_H_
17
+
18
+ #include "document.h"
19
+ #include "pointer.h"
20
+ #include "stringbuffer.h"
21
+ #include <cmath> // abs, floor
22
+
23
+ #if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX)
24
+ #define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1
25
+ #else
26
+ #define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0
27
+ #endif
28
+
29
+ #if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800))
30
+ #define RAPIDJSON_SCHEMA_USE_STDREGEX 1
31
+ #else
32
+ #define RAPIDJSON_SCHEMA_USE_STDREGEX 0
33
+ #endif
34
+
35
+ #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
36
+ #include "internal/regex.h"
37
+ #elif RAPIDJSON_SCHEMA_USE_STDREGEX
38
+ #include <regex>
39
+ #endif
40
+
41
+ #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX
42
+ #define RAPIDJSON_SCHEMA_HAS_REGEX 1
43
+ #else
44
+ #define RAPIDJSON_SCHEMA_HAS_REGEX 0
45
+ #endif
46
+
47
+ #ifndef RAPIDJSON_SCHEMA_VERBOSE
48
+ #define RAPIDJSON_SCHEMA_VERBOSE 0
49
+ #endif
50
+
51
+ #if RAPIDJSON_SCHEMA_VERBOSE
52
+ #include "stringbuffer.h"
53
+ #endif
54
+
55
+ RAPIDJSON_DIAG_PUSH
56
+
57
+ #if defined(__GNUC__)
58
+ RAPIDJSON_DIAG_OFF(effc++)
59
+ #endif
60
+
61
+ #ifdef __clang__
62
+ RAPIDJSON_DIAG_OFF(weak-vtables)
63
+ RAPIDJSON_DIAG_OFF(exit-time-destructors)
64
+ RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
65
+ RAPIDJSON_DIAG_OFF(variadic-macros)
66
+ #endif
67
+
68
+ #ifdef _MSC_VER
69
+ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
70
+ #endif
71
+
72
+ RAPIDJSON_NAMESPACE_BEGIN
73
+
74
+ ///////////////////////////////////////////////////////////////////////////////
75
+ // Verbose Utilities
76
+
77
+ #if RAPIDJSON_SCHEMA_VERBOSE
78
+
79
+ namespace internal {
80
+
81
+ inline void PrintInvalidKeyword(const char* keyword) {
82
+ printf("Fail keyword: %s\n", keyword);
83
+ }
84
+
85
+ inline void PrintInvalidKeyword(const wchar_t* keyword) {
86
+ wprintf(L"Fail keyword: %ls\n", keyword);
87
+ }
88
+
89
+ inline void PrintInvalidDocument(const char* document) {
90
+ printf("Fail document: %s\n\n", document);
91
+ }
92
+
93
+ inline void PrintInvalidDocument(const wchar_t* document) {
94
+ wprintf(L"Fail document: %ls\n\n", document);
95
+ }
96
+
97
+ inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) {
98
+ printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d);
99
+ }
100
+
101
+ inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) {
102
+ wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d);
103
+ }
104
+
105
+ } // namespace internal
106
+
107
+ #endif // RAPIDJSON_SCHEMA_VERBOSE
108
+
109
+ ///////////////////////////////////////////////////////////////////////////////
110
+ // RAPIDJSON_INVALID_KEYWORD_RETURN
111
+
112
+ #if RAPIDJSON_SCHEMA_VERBOSE
113
+ #define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword)
114
+ #else
115
+ #define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)
116
+ #endif
117
+
118
+ #define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\
119
+ RAPIDJSON_MULTILINEMACRO_BEGIN\
120
+ context.invalidKeyword = keyword.GetString();\
121
+ RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\
122
+ return false;\
123
+ RAPIDJSON_MULTILINEMACRO_END
124
+
125
+ ///////////////////////////////////////////////////////////////////////////////
126
+ // Forward declarations
127
+
128
+ template <typename ValueType, typename Allocator>
129
+ class GenericSchemaDocument;
130
+
131
+ namespace internal {
132
+
133
+ template <typename SchemaDocumentType>
134
+ class Schema;
135
+
136
+ ///////////////////////////////////////////////////////////////////////////////
137
+ // ISchemaValidator
138
+
139
+ class ISchemaValidator {
140
+ public:
141
+ virtual ~ISchemaValidator() {}
142
+ virtual bool IsValid() const = 0;
143
+ };
144
+
145
+ ///////////////////////////////////////////////////////////////////////////////
146
+ // ISchemaStateFactory
147
+
148
+ template <typename SchemaType>
149
+ class ISchemaStateFactory {
150
+ public:
151
+ virtual ~ISchemaStateFactory() {}
152
+ virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0;
153
+ virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;
154
+ virtual void* CreateHasher() = 0;
155
+ virtual uint64_t GetHashCode(void* hasher) = 0;
156
+ virtual void DestroryHasher(void* hasher) = 0;
157
+ virtual void* MallocState(size_t size) = 0;
158
+ virtual void FreeState(void* p) = 0;
159
+ };
160
+
161
+ ///////////////////////////////////////////////////////////////////////////////
162
+ // IValidationErrorHandler
163
+
164
+ template <typename SchemaType>
165
+ class IValidationErrorHandler {
166
+ public:
167
+ typedef typename SchemaType::Ch Ch;
168
+ typedef typename SchemaType::SValue SValue;
169
+
170
+ virtual ~IValidationErrorHandler() {}
171
+
172
+ virtual void NotMultipleOf(int64_t actual, const SValue& expected) = 0;
173
+ virtual void NotMultipleOf(uint64_t actual, const SValue& expected) = 0;
174
+ virtual void NotMultipleOf(double actual, const SValue& expected) = 0;
175
+ virtual void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) = 0;
176
+ virtual void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) = 0;
177
+ virtual void AboveMaximum(double actual, const SValue& expected, bool exclusive) = 0;
178
+ virtual void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) = 0;
179
+ virtual void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) = 0;
180
+ virtual void BelowMinimum(double actual, const SValue& expected, bool exclusive) = 0;
181
+
182
+ virtual void TooLong(const Ch* str, SizeType length, SizeType expected) = 0;
183
+ virtual void TooShort(const Ch* str, SizeType length, SizeType expected) = 0;
184
+ virtual void DoesNotMatch(const Ch* str, SizeType length) = 0;
185
+
186
+ virtual void DisallowedItem(SizeType index) = 0;
187
+ virtual void TooFewItems(SizeType actualCount, SizeType expectedCount) = 0;
188
+ virtual void TooManyItems(SizeType actualCount, SizeType expectedCount) = 0;
189
+ virtual void DuplicateItems(SizeType index1, SizeType index2) = 0;
190
+
191
+ virtual void TooManyProperties(SizeType actualCount, SizeType expectedCount) = 0;
192
+ virtual void TooFewProperties(SizeType actualCount, SizeType expectedCount) = 0;
193
+ virtual void StartMissingProperties() = 0;
194
+ virtual void AddMissingProperty(const SValue& name) = 0;
195
+ virtual bool EndMissingProperties() = 0;
196
+ virtual void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) = 0;
197
+ virtual void DisallowedProperty(const Ch* name, SizeType length) = 0;
198
+
199
+ virtual void StartDependencyErrors() = 0;
200
+ virtual void StartMissingDependentProperties() = 0;
201
+ virtual void AddMissingDependentProperty(const SValue& targetName) = 0;
202
+ virtual void EndMissingDependentProperties(const SValue& sourceName) = 0;
203
+ virtual void AddDependencySchemaError(const SValue& souceName, ISchemaValidator* subvalidator) = 0;
204
+ virtual bool EndDependencyErrors() = 0;
205
+
206
+ virtual void DisallowedValue() = 0;
207
+ virtual void StartDisallowedType() = 0;
208
+ virtual void AddExpectedType(const typename SchemaType::ValueType& expectedType) = 0;
209
+ virtual void EndDisallowedType(const typename SchemaType::ValueType& actualType) = 0;
210
+ virtual void NotAllOf(ISchemaValidator** subvalidators, SizeType count) = 0;
211
+ virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0;
212
+ virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count) = 0;
213
+ virtual void Disallowed() = 0;
214
+ };
215
+
216
+
217
+ ///////////////////////////////////////////////////////////////////////////////
218
+ // Hasher
219
+
220
+ // For comparison of compound value
221
+ template<typename Encoding, typename Allocator>
222
+ class Hasher {
223
+ public:
224
+ typedef typename Encoding::Ch Ch;
225
+
226
+ Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}
227
+
228
+ bool Null() { return WriteType(kNullType); }
229
+ bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); }
230
+ bool Int(int i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
231
+ bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
232
+ bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
233
+ bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
234
+ bool Double(double d) {
235
+ Number n;
236
+ if (d < 0) n.u.i = static_cast<int64_t>(d);
237
+ else n.u.u = static_cast<uint64_t>(d);
238
+ n.d = d;
239
+ return WriteNumber(n);
240
+ }
241
+
242
+ bool RawNumber(const Ch* str, SizeType len, bool) {
243
+ WriteBuffer(kNumberType, str, len * sizeof(Ch));
244
+ return true;
245
+ }
246
+
247
+ bool String(const Ch* str, SizeType len, bool) {
248
+ WriteBuffer(kStringType, str, len * sizeof(Ch));
249
+ return true;
250
+ }
251
+
252
+ bool StartObject() { return true; }
253
+ bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); }
254
+ bool EndObject(SizeType memberCount) {
255
+ uint64_t h = Hash(0, kObjectType);
256
+ uint64_t* kv = stack_.template Pop<uint64_t>(memberCount * 2);
257
+ for (SizeType i = 0; i < memberCount; i++)
258
+ h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive
259
+ *stack_.template Push<uint64_t>() = h;
260
+ return true;
261
+ }
262
+
263
+ bool StartArray() { return true; }
264
+ bool EndArray(SizeType elementCount) {
265
+ uint64_t h = Hash(0, kArrayType);
266
+ uint64_t* e = stack_.template Pop<uint64_t>(elementCount);
267
+ for (SizeType i = 0; i < elementCount; i++)
268
+ h = Hash(h, e[i]); // Use hash to achieve element order sensitive
269
+ *stack_.template Push<uint64_t>() = h;
270
+ return true;
271
+ }
272
+
273
+ bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); }
274
+
275
+ uint64_t GetHashCode() const {
276
+ RAPIDJSON_ASSERT(IsValid());
277
+ return *stack_.template Top<uint64_t>();
278
+ }
279
+
280
+ private:
281
+ static const size_t kDefaultSize = 256;
282
+ struct Number {
283
+ union U {
284
+ uint64_t u;
285
+ int64_t i;
286
+ }u;
287
+ double d;
288
+ };
289
+
290
+ bool WriteType(Type type) { return WriteBuffer(type, 0, 0); }
291
+
292
+ bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); }
293
+
294
+ bool WriteBuffer(Type type, const void* data, size_t len) {
295
+ // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/
296
+ uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type);
297
+ const unsigned char* d = static_cast<const unsigned char*>(data);
298
+ for (size_t i = 0; i < len; i++)
299
+ h = Hash(h, d[i]);
300
+ *stack_.template Push<uint64_t>() = h;
301
+ return true;
302
+ }
303
+
304
+ static uint64_t Hash(uint64_t h, uint64_t d) {
305
+ static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3);
306
+ h ^= d;
307
+ h *= kPrime;
308
+ return h;
309
+ }
310
+
311
+ Stack<Allocator> stack_;
312
+ };
313
+
314
+ ///////////////////////////////////////////////////////////////////////////////
315
+ // SchemaValidationContext
316
+
317
+ template <typename SchemaDocumentType>
318
+ struct SchemaValidationContext {
319
+ typedef Schema<SchemaDocumentType> SchemaType;
320
+ typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType;
321
+ typedef IValidationErrorHandler<SchemaType> ErrorHandlerType;
322
+ typedef typename SchemaType::ValueType ValueType;
323
+ typedef typename ValueType::Ch Ch;
324
+
325
+ enum PatternValidatorType {
326
+ kPatternValidatorOnly,
327
+ kPatternValidatorWithProperty,
328
+ kPatternValidatorWithAdditionalProperty
329
+ };
330
+
331
+ SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s) :
332
+ factory(f),
333
+ error_handler(eh),
334
+ schema(s),
335
+ valueSchema(),
336
+ invalidKeyword(),
337
+ hasher(),
338
+ arrayElementHashCodes(),
339
+ validators(),
340
+ validatorCount(),
341
+ patternPropertiesValidators(),
342
+ patternPropertiesValidatorCount(),
343
+ patternPropertiesSchemas(),
344
+ patternPropertiesSchemaCount(),
345
+ valuePatternValidatorType(kPatternValidatorOnly),
346
+ propertyExist(),
347
+ inArray(false),
348
+ valueUniqueness(false),
349
+ arrayUniqueness(false)
350
+ {
351
+ }
352
+
353
+ ~SchemaValidationContext() {
354
+ if (hasher)
355
+ factory.DestroryHasher(hasher);
356
+ if (validators) {
357
+ for (SizeType i = 0; i < validatorCount; i++)
358
+ factory.DestroySchemaValidator(validators[i]);
359
+ factory.FreeState(validators);
360
+ }
361
+ if (patternPropertiesValidators) {
362
+ for (SizeType i = 0; i < patternPropertiesValidatorCount; i++)
363
+ factory.DestroySchemaValidator(patternPropertiesValidators[i]);
364
+ factory.FreeState(patternPropertiesValidators);
365
+ }
366
+ if (patternPropertiesSchemas)
367
+ factory.FreeState(patternPropertiesSchemas);
368
+ if (propertyExist)
369
+ factory.FreeState(propertyExist);
370
+ }
371
+
372
+ SchemaValidatorFactoryType& factory;
373
+ ErrorHandlerType& error_handler;
374
+ const SchemaType* schema;
375
+ const SchemaType* valueSchema;
376
+ const Ch* invalidKeyword;
377
+ void* hasher; // Only validator access
378
+ void* arrayElementHashCodes; // Only validator access this
379
+ ISchemaValidator** validators;
380
+ SizeType validatorCount;
381
+ ISchemaValidator** patternPropertiesValidators;
382
+ SizeType patternPropertiesValidatorCount;
383
+ const SchemaType** patternPropertiesSchemas;
384
+ SizeType patternPropertiesSchemaCount;
385
+ PatternValidatorType valuePatternValidatorType;
386
+ PatternValidatorType objectPatternValidatorType;
387
+ SizeType arrayElementIndex;
388
+ bool* propertyExist;
389
+ bool inArray;
390
+ bool valueUniqueness;
391
+ bool arrayUniqueness;
392
+ };
393
+
394
+ ///////////////////////////////////////////////////////////////////////////////
395
+ // Schema
396
+
397
+ template <typename SchemaDocumentType>
398
+ class Schema {
399
+ public:
400
+ typedef typename SchemaDocumentType::ValueType ValueType;
401
+ typedef typename SchemaDocumentType::AllocatorType AllocatorType;
402
+ typedef typename SchemaDocumentType::PointerType PointerType;
403
+ typedef typename ValueType::EncodingType EncodingType;
404
+ typedef typename EncodingType::Ch Ch;
405
+ typedef SchemaValidationContext<SchemaDocumentType> Context;
406
+ typedef Schema<SchemaDocumentType> SchemaType;
407
+ typedef GenericValue<EncodingType, AllocatorType> SValue;
408
+ typedef IValidationErrorHandler<Schema> ErrorHandler;
409
+ friend class GenericSchemaDocument<ValueType, AllocatorType>;
410
+
411
+ Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) :
412
+ allocator_(allocator),
413
+ uri_(schemaDocument->GetURI(), *allocator),
414
+ pointer_(p),
415
+ typeless_(schemaDocument->GetTypeless()),
416
+ enum_(),
417
+ enumCount_(),
418
+ not_(),
419
+ type_((1 << kTotalSchemaType) - 1), // typeless
420
+ validatorCount_(),
421
+ notValidatorIndex_(),
422
+ properties_(),
423
+ additionalPropertiesSchema_(),
424
+ patternProperties_(),
425
+ patternPropertyCount_(),
426
+ propertyCount_(),
427
+ minProperties_(),
428
+ maxProperties_(SizeType(~0)),
429
+ additionalProperties_(true),
430
+ hasDependencies_(),
431
+ hasRequired_(),
432
+ hasSchemaDependencies_(),
433
+ additionalItemsSchema_(),
434
+ itemsList_(),
435
+ itemsTuple_(),
436
+ itemsTupleCount_(),
437
+ minItems_(),
438
+ maxItems_(SizeType(~0)),
439
+ additionalItems_(true),
440
+ uniqueItems_(false),
441
+ pattern_(),
442
+ minLength_(0),
443
+ maxLength_(~SizeType(0)),
444
+ exclusiveMinimum_(false),
445
+ exclusiveMaximum_(false)
446
+ {
447
+ typedef typename SchemaDocumentType::ValueType ValueType;
448
+ typedef typename ValueType::ConstValueIterator ConstValueIterator;
449
+ typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
450
+
451
+ if (!value.IsObject())
452
+ return;
453
+
454
+ if (const ValueType* v = GetMember(value, GetTypeString())) {
455
+ type_ = 0;
456
+ if (v->IsString())
457
+ AddType(*v);
458
+ else if (v->IsArray())
459
+ for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)
460
+ AddType(*itr);
461
+ }
462
+
463
+ if (const ValueType* v = GetMember(value, GetEnumString()))
464
+ if (v->IsArray() && v->Size() > 0) {
465
+ enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));
466
+ for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
467
+ typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
468
+ char buffer[256 + 24];
469
+ MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));
470
+ EnumHasherType h(&hasherAllocator, 256);
471
+ itr->Accept(h);
472
+ enum_[enumCount_++] = h.GetHashCode();
473
+ }
474
+ }
475
+
476
+ if (schemaDocument) {
477
+ AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
478
+ AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
479
+ AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
480
+ }
481
+
482
+ if (const ValueType* v = GetMember(value, GetNotString())) {
483
+ schemaDocument->CreateSchema(&not_, p.Append(GetNotString(), allocator_), *v, document);
484
+ notValidatorIndex_ = validatorCount_;
485
+ validatorCount_++;
486
+ }
487
+
488
+ // Object
489
+
490
+ const ValueType* properties = GetMember(value, GetPropertiesString());
491
+ const ValueType* required = GetMember(value, GetRequiredString());
492
+ const ValueType* dependencies = GetMember(value, GetDependenciesString());
493
+ {
494
+ // Gather properties from properties/required/dependencies
495
+ SValue allProperties(kArrayType);
496
+
497
+ if (properties && properties->IsObject())
498
+ for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
499
+ AddUniqueElement(allProperties, itr->name);
500
+
501
+ if (required && required->IsArray())
502
+ for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
503
+ if (itr->IsString())
504
+ AddUniqueElement(allProperties, *itr);
505
+
506
+ if (dependencies && dependencies->IsObject())
507
+ for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
508
+ AddUniqueElement(allProperties, itr->name);
509
+ if (itr->value.IsArray())
510
+ for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)
511
+ if (i->IsString())
512
+ AddUniqueElement(allProperties, *i);
513
+ }
514
+
515
+ if (allProperties.Size() > 0) {
516
+ propertyCount_ = allProperties.Size();
517
+ properties_ = static_cast<Property*>(allocator_->Malloc(sizeof(Property) * propertyCount_));
518
+ for (SizeType i = 0; i < propertyCount_; i++) {
519
+ new (&properties_[i]) Property();
520
+ properties_[i].name = allProperties[i];
521
+ properties_[i].schema = typeless_;
522
+ }
523
+ }
524
+ }
525
+
526
+ if (properties && properties->IsObject()) {
527
+ PointerType q = p.Append(GetPropertiesString(), allocator_);
528
+ for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
529
+ SizeType index;
530
+ if (FindPropertyIndex(itr->name, &index))
531
+ schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document);
532
+ }
533
+ }
534
+
535
+ if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
536
+ PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
537
+ patternProperties_ = static_cast<PatternProperty*>(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount()));
538
+ patternPropertyCount_ = 0;
539
+
540
+ for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
541
+ new (&patternProperties_[patternPropertyCount_]) PatternProperty();
542
+ patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);
543
+ schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document);
544
+ patternPropertyCount_++;
545
+ }
546
+ }
547
+
548
+ if (required && required->IsArray())
549
+ for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
550
+ if (itr->IsString()) {
551
+ SizeType index;
552
+ if (FindPropertyIndex(*itr, &index)) {
553
+ properties_[index].required = true;
554
+ hasRequired_ = true;
555
+ }
556
+ }
557
+
558
+ if (dependencies && dependencies->IsObject()) {
559
+ PointerType q = p.Append(GetDependenciesString(), allocator_);
560
+ hasDependencies_ = true;
561
+ for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
562
+ SizeType sourceIndex;
563
+ if (FindPropertyIndex(itr->name, &sourceIndex)) {
564
+ if (itr->value.IsArray()) {
565
+ properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_));
566
+ std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_);
567
+ for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
568
+ SizeType targetIndex;
569
+ if (FindPropertyIndex(*targetItr, &targetIndex))
570
+ properties_[sourceIndex].dependencies[targetIndex] = true;
571
+ }
572
+ }
573
+ else if (itr->value.IsObject()) {
574
+ hasSchemaDependencies_ = true;
575
+ schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document);
576
+ properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;
577
+ validatorCount_++;
578
+ }
579
+ }
580
+ }
581
+ }
582
+
583
+ if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {
584
+ if (v->IsBool())
585
+ additionalProperties_ = v->GetBool();
586
+ else if (v->IsObject())
587
+ schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document);
588
+ }
589
+
590
+ AssignIfExist(minProperties_, value, GetMinPropertiesString());
591
+ AssignIfExist(maxProperties_, value, GetMaxPropertiesString());
592
+
593
+ // Array
594
+ if (const ValueType* v = GetMember(value, GetItemsString())) {
595
+ PointerType q = p.Append(GetItemsString(), allocator_);
596
+ if (v->IsObject()) // List validation
597
+ schemaDocument->CreateSchema(&itemsList_, q, *v, document);
598
+ else if (v->IsArray()) { // Tuple validation
599
+ itemsTuple_ = static_cast<const Schema**>(allocator_->Malloc(sizeof(const Schema*) * v->Size()));
600
+ SizeType index = 0;
601
+ for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
602
+ schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document);
603
+ }
604
+ }
605
+
606
+ AssignIfExist(minItems_, value, GetMinItemsString());
607
+ AssignIfExist(maxItems_, value, GetMaxItemsString());
608
+
609
+ if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
610
+ if (v->IsBool())
611
+ additionalItems_ = v->GetBool();
612
+ else if (v->IsObject())
613
+ schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document);
614
+ }
615
+
616
+ AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
617
+
618
+ // String
619
+ AssignIfExist(minLength_, value, GetMinLengthString());
620
+ AssignIfExist(maxLength_, value, GetMaxLengthString());
621
+
622
+ if (const ValueType* v = GetMember(value, GetPatternString()))
623
+ pattern_ = CreatePattern(*v);
624
+
625
+ // Number
626
+ if (const ValueType* v = GetMember(value, GetMinimumString()))
627
+ if (v->IsNumber())
628
+ minimum_.CopyFrom(*v, *allocator_);
629
+
630
+ if (const ValueType* v = GetMember(value, GetMaximumString()))
631
+ if (v->IsNumber())
632
+ maximum_.CopyFrom(*v, *allocator_);
633
+
634
+ AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());
635
+ AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());
636
+
637
+ if (const ValueType* v = GetMember(value, GetMultipleOfString()))
638
+ if (v->IsNumber() && v->GetDouble() > 0.0)
639
+ multipleOf_.CopyFrom(*v, *allocator_);
640
+ }
641
+
642
+ ~Schema() {
643
+ AllocatorType::Free(enum_);
644
+ if (properties_) {
645
+ for (SizeType i = 0; i < propertyCount_; i++)
646
+ properties_[i].~Property();
647
+ AllocatorType::Free(properties_);
648
+ }
649
+ if (patternProperties_) {
650
+ for (SizeType i = 0; i < patternPropertyCount_; i++)
651
+ patternProperties_[i].~PatternProperty();
652
+ AllocatorType::Free(patternProperties_);
653
+ }
654
+ AllocatorType::Free(itemsTuple_);
655
+ #if RAPIDJSON_SCHEMA_HAS_REGEX
656
+ if (pattern_) {
657
+ pattern_->~RegexType();
658
+ AllocatorType::Free(pattern_);
659
+ }
660
+ #endif
661
+ }
662
+
663
+ const SValue& GetURI() const {
664
+ return uri_;
665
+ }
666
+
667
+ const PointerType& GetPointer() const {
668
+ return pointer_;
669
+ }
670
+
671
+ bool BeginValue(Context& context) const {
672
+ if (context.inArray) {
673
+ if (uniqueItems_)
674
+ context.valueUniqueness = true;
675
+
676
+ if (itemsList_)
677
+ context.valueSchema = itemsList_;
678
+ else if (itemsTuple_) {
679
+ if (context.arrayElementIndex < itemsTupleCount_)
680
+ context.valueSchema = itemsTuple_[context.arrayElementIndex];
681
+ else if (additionalItemsSchema_)
682
+ context.valueSchema = additionalItemsSchema_;
683
+ else if (additionalItems_)
684
+ context.valueSchema = typeless_;
685
+ else {
686
+ context.error_handler.DisallowedItem(context.arrayElementIndex);
687
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString());
688
+ }
689
+ }
690
+ else
691
+ context.valueSchema = typeless_;
692
+
693
+ context.arrayElementIndex++;
694
+ }
695
+ return true;
696
+ }
697
+
698
+ RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const {
699
+ if (context.patternPropertiesValidatorCount > 0) {
700
+ bool otherValid = false;
701
+ SizeType count = context.patternPropertiesValidatorCount;
702
+ if (context.objectPatternValidatorType != Context::kPatternValidatorOnly)
703
+ otherValid = context.patternPropertiesValidators[--count]->IsValid();
704
+
705
+ bool patternValid = true;
706
+ for (SizeType i = 0; i < count; i++)
707
+ if (!context.patternPropertiesValidators[i]->IsValid()) {
708
+ patternValid = false;
709
+ break;
710
+ }
711
+
712
+ if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
713
+ if (!patternValid) {
714
+ context.error_handler.PropertyViolations(context.patternPropertiesValidators, count);
715
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
716
+ }
717
+ }
718
+ else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
719
+ if (!patternValid || !otherValid) {
720
+ context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);
721
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
722
+ }
723
+ }
724
+ else if (!patternValid && !otherValid) { // kPatternValidatorWithAdditionalProperty)
725
+ context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);
726
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
727
+ }
728
+ }
729
+
730
+ if (enum_) {
731
+ const uint64_t h = context.factory.GetHashCode(context.hasher);
732
+ for (SizeType i = 0; i < enumCount_; i++)
733
+ if (enum_[i] == h)
734
+ goto foundEnum;
735
+ context.error_handler.DisallowedValue();
736
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString());
737
+ foundEnum:;
738
+ }
739
+
740
+ if (allOf_.schemas)
741
+ for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
742
+ if (!context.validators[i]->IsValid()) {
743
+ context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count);
744
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString());
745
+ }
746
+
747
+ if (anyOf_.schemas) {
748
+ for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
749
+ if (context.validators[i]->IsValid())
750
+ goto foundAny;
751
+ context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);
752
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString());
753
+ foundAny:;
754
+ }
755
+
756
+ if (oneOf_.schemas) {
757
+ bool oneValid = false;
758
+ for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
759
+ if (context.validators[i]->IsValid()) {
760
+ if (oneValid) {
761
+ context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count);
762
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
763
+ } else
764
+ oneValid = true;
765
+ }
766
+ if (!oneValid) {
767
+ context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count);
768
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
769
+ }
770
+ }
771
+
772
+ if (not_ && context.validators[notValidatorIndex_]->IsValid()) {
773
+ context.error_handler.Disallowed();
774
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString());
775
+ }
776
+
777
+ return true;
778
+ }
779
+
780
+ bool Null(Context& context) const {
781
+ if (!(type_ & (1 << kNullSchemaType))) {
782
+ DisallowedType(context, GetNullString());
783
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
784
+ }
785
+ return CreateParallelValidator(context);
786
+ }
787
+
788
+ bool Bool(Context& context, bool) const {
789
+ if (!(type_ & (1 << kBooleanSchemaType))) {
790
+ DisallowedType(context, GetBooleanString());
791
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
792
+ }
793
+ return CreateParallelValidator(context);
794
+ }
795
+
796
+ bool Int(Context& context, int i) const {
797
+ if (!CheckInt(context, i))
798
+ return false;
799
+ return CreateParallelValidator(context);
800
+ }
801
+
802
+ bool Uint(Context& context, unsigned u) const {
803
+ if (!CheckUint(context, u))
804
+ return false;
805
+ return CreateParallelValidator(context);
806
+ }
807
+
808
+ bool Int64(Context& context, int64_t i) const {
809
+ if (!CheckInt(context, i))
810
+ return false;
811
+ return CreateParallelValidator(context);
812
+ }
813
+
814
+ bool Uint64(Context& context, uint64_t u) const {
815
+ if (!CheckUint(context, u))
816
+ return false;
817
+ return CreateParallelValidator(context);
818
+ }
819
+
820
+ bool Double(Context& context, double d) const {
821
+ if (!(type_ & (1 << kNumberSchemaType))) {
822
+ DisallowedType(context, GetNumberString());
823
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
824
+ }
825
+
826
+ if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
827
+ return false;
828
+
829
+ if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
830
+ return false;
831
+
832
+ if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
833
+ return false;
834
+
835
+ return CreateParallelValidator(context);
836
+ }
837
+
838
+ bool String(Context& context, const Ch* str, SizeType length, bool) const {
839
+ if (!(type_ & (1 << kStringSchemaType))) {
840
+ DisallowedType(context, GetStringString());
841
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
842
+ }
843
+
844
+ if (minLength_ != 0 || maxLength_ != SizeType(~0)) {
845
+ SizeType count;
846
+ if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
847
+ if (count < minLength_) {
848
+ context.error_handler.TooShort(str, length, minLength_);
849
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString());
850
+ }
851
+ if (count > maxLength_) {
852
+ context.error_handler.TooLong(str, length, maxLength_);
853
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString());
854
+ }
855
+ }
856
+ }
857
+
858
+ if (pattern_ && !IsPatternMatch(pattern_, str, length)) {
859
+ context.error_handler.DoesNotMatch(str, length);
860
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString());
861
+ }
862
+
863
+ return CreateParallelValidator(context);
864
+ }
865
+
866
+ bool StartObject(Context& context) const {
867
+ if (!(type_ & (1 << kObjectSchemaType))) {
868
+ DisallowedType(context, GetObjectString());
869
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
870
+ }
871
+
872
+ if (hasDependencies_ || hasRequired_) {
873
+ context.propertyExist = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_));
874
+ std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_);
875
+ }
876
+
877
+ if (patternProperties_) { // pre-allocate schema array
878
+ SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType
879
+ context.patternPropertiesSchemas = static_cast<const SchemaType**>(context.factory.MallocState(sizeof(const SchemaType*) * count));
880
+ context.patternPropertiesSchemaCount = 0;
881
+ std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count);
882
+ }
883
+
884
+ return CreateParallelValidator(context);
885
+ }
886
+
887
+ bool Key(Context& context, const Ch* str, SizeType len, bool) const {
888
+ if (patternProperties_) {
889
+ context.patternPropertiesSchemaCount = 0;
890
+ for (SizeType i = 0; i < patternPropertyCount_; i++)
891
+ if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) {
892
+ context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;
893
+ context.valueSchema = typeless_;
894
+ }
895
+ }
896
+
897
+ SizeType index;
898
+ if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
899
+ if (context.patternPropertiesSchemaCount > 0) {
900
+ context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
901
+ context.valueSchema = typeless_;
902
+ context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
903
+ }
904
+ else
905
+ context.valueSchema = properties_[index].schema;
906
+
907
+ if (context.propertyExist)
908
+ context.propertyExist[index] = true;
909
+
910
+ return true;
911
+ }
912
+
913
+ if (additionalPropertiesSchema_) {
914
+ if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) {
915
+ context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
916
+ context.valueSchema = typeless_;
917
+ context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
918
+ }
919
+ else
920
+ context.valueSchema = additionalPropertiesSchema_;
921
+ return true;
922
+ }
923
+ else if (additionalProperties_) {
924
+ context.valueSchema = typeless_;
925
+ return true;
926
+ }
927
+
928
+ if (context.patternPropertiesSchemaCount == 0) { // patternProperties are not additional properties
929
+ context.error_handler.DisallowedProperty(str, len);
930
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString());
931
+ }
932
+
933
+ return true;
934
+ }
935
+
936
+ bool EndObject(Context& context, SizeType memberCount) const {
937
+ if (hasRequired_) {
938
+ context.error_handler.StartMissingProperties();
939
+ for (SizeType index = 0; index < propertyCount_; index++)
940
+ if (properties_[index].required && !context.propertyExist[index])
941
+ context.error_handler.AddMissingProperty(properties_[index].name);
942
+ if (context.error_handler.EndMissingProperties())
943
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
944
+ }
945
+
946
+ if (memberCount < minProperties_) {
947
+ context.error_handler.TooFewProperties(memberCount, minProperties_);
948
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());
949
+ }
950
+
951
+ if (memberCount > maxProperties_) {
952
+ context.error_handler.TooManyProperties(memberCount, maxProperties_);
953
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString());
954
+ }
955
+
956
+ if (hasDependencies_) {
957
+ context.error_handler.StartDependencyErrors();
958
+ for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) {
959
+ const Property& source = properties_[sourceIndex];
960
+ if (context.propertyExist[sourceIndex]) {
961
+ if (source.dependencies) {
962
+ context.error_handler.StartMissingDependentProperties();
963
+ for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
964
+ if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex])
965
+ context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name);
966
+ context.error_handler.EndMissingDependentProperties(source.name);
967
+ }
968
+ else if (source.dependenciesSchema) {
969
+ ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex];
970
+ if (!dependenciesValidator->IsValid())
971
+ context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator);
972
+ }
973
+ }
974
+ }
975
+ if (context.error_handler.EndDependencyErrors())
976
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
977
+ }
978
+
979
+ return true;
980
+ }
981
+
982
+ bool StartArray(Context& context) const {
983
+ if (!(type_ & (1 << kArraySchemaType))) {
984
+ DisallowedType(context, GetArrayString());
985
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
986
+ }
987
+
988
+ context.arrayElementIndex = 0;
989
+ context.inArray = true;
990
+
991
+ return CreateParallelValidator(context);
992
+ }
993
+
994
+ bool EndArray(Context& context, SizeType elementCount) const {
995
+ context.inArray = false;
996
+
997
+ if (elementCount < minItems_) {
998
+ context.error_handler.TooFewItems(elementCount, minItems_);
999
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString());
1000
+ }
1001
+
1002
+ if (elementCount > maxItems_) {
1003
+ context.error_handler.TooManyItems(elementCount, maxItems_);
1004
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString());
1005
+ }
1006
+
1007
+ return true;
1008
+ }
1009
+
1010
+ // Generate functions for string literal according to Ch
1011
+ #define RAPIDJSON_STRING_(name, ...) \
1012
+ static const ValueType& Get##name##String() {\
1013
+ static const Ch s[] = { __VA_ARGS__, '\0' };\
1014
+ static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\
1015
+ return v;\
1016
+ }
1017
+
1018
+ RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
1019
+ RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n')
1020
+ RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't')
1021
+ RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y')
1022
+ RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g')
1023
+ RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r')
1024
+ RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r')
1025
+ RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e')
1026
+ RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm')
1027
+ RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f')
1028
+ RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f')
1029
+ RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f')
1030
+ RAPIDJSON_STRING_(Not, 'n', 'o', 't')
1031
+ RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1032
+ RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd')
1033
+ RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's')
1034
+ RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1035
+ RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1036
+ RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1037
+ RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1038
+ RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's')
1039
+ RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's')
1040
+ RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's')
1041
+ RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's')
1042
+ RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's')
1043
+ RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h')
1044
+ RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h')
1045
+ RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n')
1046
+ RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm')
1047
+ RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm')
1048
+ RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm')
1049
+ RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm')
1050
+ RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f')
1051
+
1052
+ #undef RAPIDJSON_STRING_
1053
+
1054
+ private:
1055
+ enum SchemaValueType {
1056
+ kNullSchemaType,
1057
+ kBooleanSchemaType,
1058
+ kObjectSchemaType,
1059
+ kArraySchemaType,
1060
+ kStringSchemaType,
1061
+ kNumberSchemaType,
1062
+ kIntegerSchemaType,
1063
+ kTotalSchemaType
1064
+ };
1065
+
1066
+ #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
1067
+ typedef internal::GenericRegex<EncodingType, AllocatorType> RegexType;
1068
+ #elif RAPIDJSON_SCHEMA_USE_STDREGEX
1069
+ typedef std::basic_regex<Ch> RegexType;
1070
+ #else
1071
+ typedef char RegexType;
1072
+ #endif
1073
+
1074
+ struct SchemaArray {
1075
+ SchemaArray() : schemas(), count() {}
1076
+ ~SchemaArray() { AllocatorType::Free(schemas); }
1077
+ const SchemaType** schemas;
1078
+ SizeType begin; // begin index of context.validators
1079
+ SizeType count;
1080
+ };
1081
+
1082
+ template <typename V1, typename V2>
1083
+ void AddUniqueElement(V1& a, const V2& v) {
1084
+ for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
1085
+ if (*itr == v)
1086
+ return;
1087
+ V1 c(v, *allocator_);
1088
+ a.PushBack(c, *allocator_);
1089
+ }
1090
+
1091
+ static const ValueType* GetMember(const ValueType& value, const ValueType& name) {
1092
+ typename ValueType::ConstMemberIterator itr = value.FindMember(name);
1093
+ return itr != value.MemberEnd() ? &(itr->value) : 0;
1094
+ }
1095
+
1096
+ static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) {
1097
+ if (const ValueType* v = GetMember(value, name))
1098
+ if (v->IsBool())
1099
+ out = v->GetBool();
1100
+ }
1101
+
1102
+ static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) {
1103
+ if (const ValueType* v = GetMember(value, name))
1104
+ if (v->IsUint64() && v->GetUint64() <= SizeType(~0))
1105
+ out = static_cast<SizeType>(v->GetUint64());
1106
+ }
1107
+
1108
+ void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) {
1109
+ if (const ValueType* v = GetMember(value, name)) {
1110
+ if (v->IsArray() && v->Size() > 0) {
1111
+ PointerType q = p.Append(name, allocator_);
1112
+ out.count = v->Size();
1113
+ out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));
1114
+ memset(out.schemas, 0, sizeof(Schema*)* out.count);
1115
+ for (SizeType i = 0; i < out.count; i++)
1116
+ schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);
1117
+ out.begin = validatorCount_;
1118
+ validatorCount_ += out.count;
1119
+ }
1120
+ }
1121
+ }
1122
+
1123
+ #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
1124
+ template <typename ValueType>
1125
+ RegexType* CreatePattern(const ValueType& value) {
1126
+ if (value.IsString()) {
1127
+ RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), allocator_);
1128
+ if (!r->IsValid()) {
1129
+ r->~RegexType();
1130
+ AllocatorType::Free(r);
1131
+ r = 0;
1132
+ }
1133
+ return r;
1134
+ }
1135
+ return 0;
1136
+ }
1137
+
1138
+ static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) {
1139
+ GenericRegexSearch<RegexType> rs(*pattern);
1140
+ return rs.Search(str);
1141
+ }
1142
+ #elif RAPIDJSON_SCHEMA_USE_STDREGEX
1143
+ template <typename ValueType>
1144
+ RegexType* CreatePattern(const ValueType& value) {
1145
+ if (value.IsString())
1146
+ try {
1147
+ return new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
1148
+ }
1149
+ catch (const std::regex_error&) {
1150
+ }
1151
+ return 0;
1152
+ }
1153
+
1154
+ static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) {
1155
+ std::match_results<const Ch*> r;
1156
+ return std::regex_search(str, str + length, r, *pattern);
1157
+ }
1158
+ #else
1159
+ template <typename ValueType>
1160
+ RegexType* CreatePattern(const ValueType&) { return 0; }
1161
+
1162
+ static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; }
1163
+ #endif // RAPIDJSON_SCHEMA_USE_STDREGEX
1164
+
1165
+ void AddType(const ValueType& type) {
1166
+ if (type == GetNullString() ) type_ |= 1 << kNullSchemaType;
1167
+ else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
1168
+ else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
1169
+ else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType;
1170
+ else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
1171
+ else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
1172
+ else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
1173
+ }
1174
+
1175
+ bool CreateParallelValidator(Context& context) const {
1176
+ if (enum_ || context.arrayUniqueness)
1177
+ context.hasher = context.factory.CreateHasher();
1178
+
1179
+ if (validatorCount_) {
1180
+ RAPIDJSON_ASSERT(context.validators == 0);
1181
+ context.validators = static_cast<ISchemaValidator**>(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_));
1182
+ context.validatorCount = validatorCount_;
1183
+
1184
+ if (allOf_.schemas)
1185
+ CreateSchemaValidators(context, allOf_);
1186
+
1187
+ if (anyOf_.schemas)
1188
+ CreateSchemaValidators(context, anyOf_);
1189
+
1190
+ if (oneOf_.schemas)
1191
+ CreateSchemaValidators(context, oneOf_);
1192
+
1193
+ if (not_)
1194
+ context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_);
1195
+
1196
+ if (hasSchemaDependencies_) {
1197
+ for (SizeType i = 0; i < propertyCount_; i++)
1198
+ if (properties_[i].dependenciesSchema)
1199
+ context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema);
1200
+ }
1201
+ }
1202
+
1203
+ return true;
1204
+ }
1205
+
1206
+ void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const {
1207
+ for (SizeType i = 0; i < schemas.count; i++)
1208
+ context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]);
1209
+ }
1210
+
1211
+ // O(n)
1212
+ bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const {
1213
+ SizeType len = name.GetStringLength();
1214
+ const Ch* str = name.GetString();
1215
+ for (SizeType index = 0; index < propertyCount_; index++)
1216
+ if (properties_[index].name.GetStringLength() == len &&
1217
+ (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0))
1218
+ {
1219
+ *outIndex = index;
1220
+ return true;
1221
+ }
1222
+ return false;
1223
+ }
1224
+
1225
+ bool CheckInt(Context& context, int64_t i) const {
1226
+ if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
1227
+ DisallowedType(context, GetIntegerString());
1228
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
1229
+ }
1230
+
1231
+ if (!minimum_.IsNull()) {
1232
+ if (minimum_.IsInt64()) {
1233
+ if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) {
1234
+ context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1235
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
1236
+ }
1237
+ }
1238
+ else if (minimum_.IsUint64()) {
1239
+ context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1240
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64()
1241
+ }
1242
+ else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
1243
+ return false;
1244
+ }
1245
+
1246
+ if (!maximum_.IsNull()) {
1247
+ if (maximum_.IsInt64()) {
1248
+ if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) {
1249
+ context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1250
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
1251
+ }
1252
+ }
1253
+ else if (maximum_.IsUint64()) { }
1254
+ /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64()
1255
+ else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
1256
+ return false;
1257
+ }
1258
+
1259
+ if (!multipleOf_.IsNull()) {
1260
+ if (multipleOf_.IsUint64()) {
1261
+ if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) {
1262
+ context.error_handler.NotMultipleOf(i, multipleOf_);
1263
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
1264
+ }
1265
+ }
1266
+ else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
1267
+ return false;
1268
+ }
1269
+
1270
+ return true;
1271
+ }
1272
+
1273
+ bool CheckUint(Context& context, uint64_t i) const {
1274
+ if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
1275
+ DisallowedType(context, GetIntegerString());
1276
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
1277
+ }
1278
+
1279
+ if (!minimum_.IsNull()) {
1280
+ if (minimum_.IsUint64()) {
1281
+ if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) {
1282
+ context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1283
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
1284
+ }
1285
+ }
1286
+ else if (minimum_.IsInt64())
1287
+ /* do nothing */; // i >= 0 > minimum.Getint64()
1288
+ else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
1289
+ return false;
1290
+ }
1291
+
1292
+ if (!maximum_.IsNull()) {
1293
+ if (maximum_.IsUint64()) {
1294
+ if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) {
1295
+ context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1296
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
1297
+ }
1298
+ }
1299
+ else if (maximum_.IsInt64()) {
1300
+ context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1301
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_
1302
+ }
1303
+ else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
1304
+ return false;
1305
+ }
1306
+
1307
+ if (!multipleOf_.IsNull()) {
1308
+ if (multipleOf_.IsUint64()) {
1309
+ if (i % multipleOf_.GetUint64() != 0) {
1310
+ context.error_handler.NotMultipleOf(i, multipleOf_);
1311
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
1312
+ }
1313
+ }
1314
+ else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
1315
+ return false;
1316
+ }
1317
+
1318
+ return true;
1319
+ }
1320
+
1321
+ bool CheckDoubleMinimum(Context& context, double d) const {
1322
+ if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) {
1323
+ context.error_handler.BelowMinimum(d, minimum_, exclusiveMinimum_);
1324
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
1325
+ }
1326
+ return true;
1327
+ }
1328
+
1329
+ bool CheckDoubleMaximum(Context& context, double d) const {
1330
+ if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) {
1331
+ context.error_handler.AboveMaximum(d, maximum_, exclusiveMaximum_);
1332
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
1333
+ }
1334
+ return true;
1335
+ }
1336
+
1337
+ bool CheckDoubleMultipleOf(Context& context, double d) const {
1338
+ double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
1339
+ double q = std::floor(a / b);
1340
+ double r = a - q * b;
1341
+ if (r > 0.0) {
1342
+ context.error_handler.NotMultipleOf(d, multipleOf_);
1343
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
1344
+ }
1345
+ return true;
1346
+ }
1347
+
1348
+ void DisallowedType(Context& context, const ValueType& actualType) const {
1349
+ ErrorHandler& eh = context.error_handler;
1350
+ eh.StartDisallowedType();
1351
+
1352
+ if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString());
1353
+ if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString());
1354
+ if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString());
1355
+ if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString());
1356
+ if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString());
1357
+
1358
+ if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString());
1359
+ else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString());
1360
+
1361
+ eh.EndDisallowedType(actualType);
1362
+ }
1363
+
1364
+ struct Property {
1365
+ Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {}
1366
+ ~Property() { AllocatorType::Free(dependencies); }
1367
+ SValue name;
1368
+ const SchemaType* schema;
1369
+ const SchemaType* dependenciesSchema;
1370
+ SizeType dependenciesValidatorIndex;
1371
+ bool* dependencies;
1372
+ bool required;
1373
+ };
1374
+
1375
+ struct PatternProperty {
1376
+ PatternProperty() : schema(), pattern() {}
1377
+ ~PatternProperty() {
1378
+ if (pattern) {
1379
+ pattern->~RegexType();
1380
+ AllocatorType::Free(pattern);
1381
+ }
1382
+ }
1383
+ const SchemaType* schema;
1384
+ RegexType* pattern;
1385
+ };
1386
+
1387
+ AllocatorType* allocator_;
1388
+ SValue uri_;
1389
+ PointerType pointer_;
1390
+ const SchemaType* typeless_;
1391
+ uint64_t* enum_;
1392
+ SizeType enumCount_;
1393
+ SchemaArray allOf_;
1394
+ SchemaArray anyOf_;
1395
+ SchemaArray oneOf_;
1396
+ const SchemaType* not_;
1397
+ unsigned type_; // bitmask of kSchemaType
1398
+ SizeType validatorCount_;
1399
+ SizeType notValidatorIndex_;
1400
+
1401
+ Property* properties_;
1402
+ const SchemaType* additionalPropertiesSchema_;
1403
+ PatternProperty* patternProperties_;
1404
+ SizeType patternPropertyCount_;
1405
+ SizeType propertyCount_;
1406
+ SizeType minProperties_;
1407
+ SizeType maxProperties_;
1408
+ bool additionalProperties_;
1409
+ bool hasDependencies_;
1410
+ bool hasRequired_;
1411
+ bool hasSchemaDependencies_;
1412
+
1413
+ const SchemaType* additionalItemsSchema_;
1414
+ const SchemaType* itemsList_;
1415
+ const SchemaType** itemsTuple_;
1416
+ SizeType itemsTupleCount_;
1417
+ SizeType minItems_;
1418
+ SizeType maxItems_;
1419
+ bool additionalItems_;
1420
+ bool uniqueItems_;
1421
+
1422
+ RegexType* pattern_;
1423
+ SizeType minLength_;
1424
+ SizeType maxLength_;
1425
+
1426
+ SValue minimum_;
1427
+ SValue maximum_;
1428
+ SValue multipleOf_;
1429
+ bool exclusiveMinimum_;
1430
+ bool exclusiveMaximum_;
1431
+ };
1432
+
1433
+ template<typename Stack, typename Ch>
1434
+ struct TokenHelper {
1435
+ RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
1436
+ *documentStack.template Push<Ch>() = '/';
1437
+ char buffer[21];
1438
+ size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer);
1439
+ for (size_t i = 0; i < length; i++)
1440
+ *documentStack.template Push<Ch>() = static_cast<Ch>(buffer[i]);
1441
+ }
1442
+ };
1443
+
1444
+ // Partial specialized version for char to prevent buffer copying.
1445
+ template <typename Stack>
1446
+ struct TokenHelper<Stack, char> {
1447
+ RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
1448
+ if (sizeof(SizeType) == 4) {
1449
+ char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint
1450
+ *buffer++ = '/';
1451
+ const char* end = internal::u32toa(index, buffer);
1452
+ documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer)));
1453
+ }
1454
+ else {
1455
+ char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64
1456
+ *buffer++ = '/';
1457
+ const char* end = internal::u64toa(index, buffer);
1458
+ documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer)));
1459
+ }
1460
+ }
1461
+ };
1462
+
1463
+ } // namespace internal
1464
+
1465
+ ///////////////////////////////////////////////////////////////////////////////
1466
+ // IGenericRemoteSchemaDocumentProvider
1467
+
1468
+ template <typename SchemaDocumentType>
1469
+ class IGenericRemoteSchemaDocumentProvider {
1470
+ public:
1471
+ typedef typename SchemaDocumentType::Ch Ch;
1472
+
1473
+ virtual ~IGenericRemoteSchemaDocumentProvider() {}
1474
+ virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0;
1475
+ };
1476
+
1477
+ ///////////////////////////////////////////////////////////////////////////////
1478
+ // GenericSchemaDocument
1479
+
1480
+ //! JSON schema document.
1481
+ /*!
1482
+ A JSON schema document is a compiled version of a JSON schema.
1483
+ It is basically a tree of internal::Schema.
1484
+
1485
+ \note This is an immutable class (i.e. its instance cannot be modified after construction).
1486
+ \tparam ValueT Type of JSON value (e.g. \c Value ), which also determine the encoding.
1487
+ \tparam Allocator Allocator type for allocating memory of this document.
1488
+ */
1489
+ template <typename ValueT, typename Allocator = CrtAllocator>
1490
+ class GenericSchemaDocument {
1491
+ public:
1492
+ typedef ValueT ValueType;
1493
+ typedef IGenericRemoteSchemaDocumentProvider<GenericSchemaDocument> IRemoteSchemaDocumentProviderType;
1494
+ typedef Allocator AllocatorType;
1495
+ typedef typename ValueType::EncodingType EncodingType;
1496
+ typedef typename EncodingType::Ch Ch;
1497
+ typedef internal::Schema<GenericSchemaDocument> SchemaType;
1498
+ typedef GenericPointer<ValueType, Allocator> PointerType;
1499
+ typedef GenericValue<EncodingType, Allocator> URIType;
1500
+ friend class internal::Schema<GenericSchemaDocument>;
1501
+ template <typename, typename, typename>
1502
+ friend class GenericSchemaValidator;
1503
+
1504
+ //! Constructor.
1505
+ /*!
1506
+ Compile a JSON document into schema document.
1507
+
1508
+ \param document A JSON document as source.
1509
+ \param uri The base URI of this schema document for purposes of violation reporting.
1510
+ \param uriLength Length of \c name, in code points.
1511
+ \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null.
1512
+ \param allocator An optional allocator instance for allocating memory. Can be null.
1513
+ */
1514
+ explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0,
1515
+ IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :
1516
+ remoteProvider_(remoteProvider),
1517
+ allocator_(allocator),
1518
+ ownAllocator_(),
1519
+ root_(),
1520
+ typeless_(),
1521
+ schemaMap_(allocator, kInitialSchemaMapSize),
1522
+ schemaRef_(allocator, kInitialSchemaRefSize)
1523
+ {
1524
+ if (!allocator_)
1525
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
1526
+
1527
+ Ch noUri[1] = {0};
1528
+ uri_.SetString(uri ? uri : noUri, uriLength, *allocator_);
1529
+
1530
+ typeless_ = static_cast<SchemaType*>(allocator_->Malloc(sizeof(SchemaType)));
1531
+ new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), allocator_);
1532
+
1533
+ // Generate root schema, it will call CreateSchema() to create sub-schemas,
1534
+ // And call AddRefSchema() if there are $ref.
1535
+ CreateSchemaRecursive(&root_, PointerType(), document, document);
1536
+
1537
+ // Resolve $ref
1538
+ while (!schemaRef_.Empty()) {
1539
+ SchemaRefEntry* refEntry = schemaRef_.template Pop<SchemaRefEntry>(1);
1540
+ if (const SchemaType* s = GetSchema(refEntry->target)) {
1541
+ if (refEntry->schema)
1542
+ *refEntry->schema = s;
1543
+
1544
+ // Create entry in map if not exist
1545
+ if (!GetSchema(refEntry->source)) {
1546
+ new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(refEntry->source, const_cast<SchemaType*>(s), false, allocator_);
1547
+ }
1548
+ }
1549
+ else if (refEntry->schema)
1550
+ *refEntry->schema = typeless_;
1551
+
1552
+ refEntry->~SchemaRefEntry();
1553
+ }
1554
+
1555
+ RAPIDJSON_ASSERT(root_ != 0);
1556
+
1557
+ schemaRef_.ShrinkToFit(); // Deallocate all memory for ref
1558
+ }
1559
+
1560
+ #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
1561
+ //! Move constructor in C++11
1562
+ GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT :
1563
+ remoteProvider_(rhs.remoteProvider_),
1564
+ allocator_(rhs.allocator_),
1565
+ ownAllocator_(rhs.ownAllocator_),
1566
+ root_(rhs.root_),
1567
+ typeless_(rhs.typeless_),
1568
+ schemaMap_(std::move(rhs.schemaMap_)),
1569
+ schemaRef_(std::move(rhs.schemaRef_)),
1570
+ uri_(std::move(rhs.uri_))
1571
+ {
1572
+ rhs.remoteProvider_ = 0;
1573
+ rhs.allocator_ = 0;
1574
+ rhs.ownAllocator_ = 0;
1575
+ rhs.typeless_ = 0;
1576
+ }
1577
+ #endif
1578
+
1579
+ //! Destructor
1580
+ ~GenericSchemaDocument() {
1581
+ while (!schemaMap_.Empty())
1582
+ schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();
1583
+
1584
+ if (typeless_) {
1585
+ typeless_->~SchemaType();
1586
+ Allocator::Free(typeless_);
1587
+ }
1588
+
1589
+ RAPIDJSON_DELETE(ownAllocator_);
1590
+ }
1591
+
1592
+ const URIType& GetURI() const { return uri_; }
1593
+
1594
+ //! Get the root schema.
1595
+ const SchemaType& GetRoot() const { return *root_; }
1596
+
1597
+ private:
1598
+ //! Prohibit copying
1599
+ GenericSchemaDocument(const GenericSchemaDocument&);
1600
+ //! Prohibit assignment
1601
+ GenericSchemaDocument& operator=(const GenericSchemaDocument&);
1602
+
1603
+ struct SchemaRefEntry {
1604
+ SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}
1605
+ PointerType source;
1606
+ PointerType target;
1607
+ const SchemaType** schema;
1608
+ };
1609
+
1610
+ struct SchemaEntry {
1611
+ SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {}
1612
+ ~SchemaEntry() {
1613
+ if (owned) {
1614
+ schema->~SchemaType();
1615
+ Allocator::Free(schema);
1616
+ }
1617
+ }
1618
+ PointerType pointer;
1619
+ SchemaType* schema;
1620
+ bool owned;
1621
+ };
1622
+
1623
+ void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
1624
+ if (schema)
1625
+ *schema = typeless_;
1626
+
1627
+ if (v.GetType() == kObjectType) {
1628
+ const SchemaType* s = GetSchema(pointer);
1629
+ if (!s)
1630
+ CreateSchema(schema, pointer, v, document);
1631
+
1632
+ for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
1633
+ CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document);
1634
+ }
1635
+ else if (v.GetType() == kArrayType)
1636
+ for (SizeType i = 0; i < v.Size(); i++)
1637
+ CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document);
1638
+ }
1639
+
1640
+ void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
1641
+ RAPIDJSON_ASSERT(pointer.IsValid());
1642
+ if (v.IsObject()) {
1643
+ if (!HandleRefSchema(pointer, schema, v, document)) {
1644
+ SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_);
1645
+ new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(pointer, s, true, allocator_);
1646
+ if (schema)
1647
+ *schema = s;
1648
+ }
1649
+ }
1650
+ }
1651
+
1652
+ bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) {
1653
+ static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' };
1654
+ static const ValueType kRefValue(kRefString, 4);
1655
+
1656
+ typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue);
1657
+ if (itr == v.MemberEnd())
1658
+ return false;
1659
+
1660
+ if (itr->value.IsString()) {
1661
+ SizeType len = itr->value.GetStringLength();
1662
+ if (len > 0) {
1663
+ const Ch* s = itr->value.GetString();
1664
+ SizeType i = 0;
1665
+ while (i < len && s[i] != '#') // Find the first #
1666
+ i++;
1667
+
1668
+ if (i > 0) { // Remote reference, resolve immediately
1669
+ if (remoteProvider_) {
1670
+ if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i)) {
1671
+ PointerType pointer(&s[i], len - i, allocator_);
1672
+ if (pointer.IsValid()) {
1673
+ if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) {
1674
+ if (schema)
1675
+ *schema = sc;
1676
+ return true;
1677
+ }
1678
+ }
1679
+ }
1680
+ }
1681
+ }
1682
+ else if (s[i] == '#') { // Local reference, defer resolution
1683
+ PointerType pointer(&s[i], len - i, allocator_);
1684
+ if (pointer.IsValid()) {
1685
+ if (const ValueType* nv = pointer.Get(document))
1686
+ if (HandleRefSchema(source, schema, *nv, document))
1687
+ return true;
1688
+
1689
+ new (schemaRef_.template Push<SchemaRefEntry>()) SchemaRefEntry(source, pointer, schema, allocator_);
1690
+ return true;
1691
+ }
1692
+ }
1693
+ }
1694
+ }
1695
+ return false;
1696
+ }
1697
+
1698
+ const SchemaType* GetSchema(const PointerType& pointer) const {
1699
+ for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
1700
+ if (pointer == target->pointer)
1701
+ return target->schema;
1702
+ return 0;
1703
+ }
1704
+
1705
+ PointerType GetPointer(const SchemaType* schema) const {
1706
+ for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
1707
+ if (schema == target->schema)
1708
+ return target->pointer;
1709
+ return PointerType();
1710
+ }
1711
+
1712
+ const SchemaType* GetTypeless() const { return typeless_; }
1713
+
1714
+ static const size_t kInitialSchemaMapSize = 64;
1715
+ static const size_t kInitialSchemaRefSize = 64;
1716
+
1717
+ IRemoteSchemaDocumentProviderType* remoteProvider_;
1718
+ Allocator *allocator_;
1719
+ Allocator *ownAllocator_;
1720
+ const SchemaType* root_; //!< Root schema.
1721
+ SchemaType* typeless_;
1722
+ internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas
1723
+ internal::Stack<Allocator> schemaRef_; // Stores Pointer from $ref and schema which holds the $ref
1724
+ URIType uri_;
1725
+ };
1726
+
1727
+ //! GenericSchemaDocument using Value type.
1728
+ typedef GenericSchemaDocument<Value> SchemaDocument;
1729
+ //! IGenericRemoteSchemaDocumentProvider using SchemaDocument.
1730
+ typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
1731
+
1732
+ ///////////////////////////////////////////////////////////////////////////////
1733
+ // GenericSchemaValidator
1734
+
1735
+ //! JSON Schema Validator.
1736
+ /*!
1737
+ A SAX style JSON schema validator.
1738
+ It uses a \c GenericSchemaDocument to validate SAX events.
1739
+ It delegates the incoming SAX events to an output handler.
1740
+ The default output handler does nothing.
1741
+ It can be reused multiple times by calling \c Reset().
1742
+
1743
+ \tparam SchemaDocumentType Type of schema document.
1744
+ \tparam OutputHandler Type of output handler. Default handler does nothing.
1745
+ \tparam StateAllocator Allocator for storing the internal validation states.
1746
+ */
1747
+ template <
1748
+ typename SchemaDocumentType,
1749
+ typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>,
1750
+ typename StateAllocator = CrtAllocator>
1751
+ class GenericSchemaValidator :
1752
+ public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>,
1753
+ public internal::ISchemaValidator,
1754
+ public internal::IValidationErrorHandler<typename SchemaDocumentType::SchemaType>
1755
+ {
1756
+ public:
1757
+ typedef typename SchemaDocumentType::SchemaType SchemaType;
1758
+ typedef typename SchemaDocumentType::PointerType PointerType;
1759
+ typedef typename SchemaType::EncodingType EncodingType;
1760
+ typedef typename SchemaType::SValue SValue;
1761
+ typedef typename EncodingType::Ch Ch;
1762
+ typedef GenericStringRef<Ch> StringRefType;
1763
+ typedef GenericValue<EncodingType, StateAllocator> ValueType;
1764
+
1765
+ //! Constructor without output handler.
1766
+ /*!
1767
+ \param schemaDocument The schema document to conform to.
1768
+ \param allocator Optional allocator for storing internal validation states.
1769
+ \param schemaStackCapacity Optional initial capacity of schema path stack.
1770
+ \param documentStackCapacity Optional initial capacity of document path stack.
1771
+ */
1772
+ GenericSchemaValidator(
1773
+ const SchemaDocumentType& schemaDocument,
1774
+ StateAllocator* allocator = 0,
1775
+ size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
1776
+ size_t documentStackCapacity = kDefaultDocumentStackCapacity)
1777
+ :
1778
+ schemaDocument_(&schemaDocument),
1779
+ root_(schemaDocument.GetRoot()),
1780
+ stateAllocator_(allocator),
1781
+ ownStateAllocator_(0),
1782
+ schemaStack_(allocator, schemaStackCapacity),
1783
+ documentStack_(allocator, documentStackCapacity),
1784
+ outputHandler_(0),
1785
+ error_(kObjectType),
1786
+ currentError_(),
1787
+ missingDependents_(),
1788
+ valid_(true)
1789
+ #if RAPIDJSON_SCHEMA_VERBOSE
1790
+ , depth_(0)
1791
+ #endif
1792
+ {
1793
+ }
1794
+
1795
+ //! Constructor with output handler.
1796
+ /*!
1797
+ \param schemaDocument The schema document to conform to.
1798
+ \param allocator Optional allocator for storing internal validation states.
1799
+ \param schemaStackCapacity Optional initial capacity of schema path stack.
1800
+ \param documentStackCapacity Optional initial capacity of document path stack.
1801
+ */
1802
+ GenericSchemaValidator(
1803
+ const SchemaDocumentType& schemaDocument,
1804
+ OutputHandler& outputHandler,
1805
+ StateAllocator* allocator = 0,
1806
+ size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
1807
+ size_t documentStackCapacity = kDefaultDocumentStackCapacity)
1808
+ :
1809
+ schemaDocument_(&schemaDocument),
1810
+ root_(schemaDocument.GetRoot()),
1811
+ stateAllocator_(allocator),
1812
+ ownStateAllocator_(0),
1813
+ schemaStack_(allocator, schemaStackCapacity),
1814
+ documentStack_(allocator, documentStackCapacity),
1815
+ outputHandler_(&outputHandler),
1816
+ error_(kObjectType),
1817
+ currentError_(),
1818
+ missingDependents_(),
1819
+ valid_(true)
1820
+ #if RAPIDJSON_SCHEMA_VERBOSE
1821
+ , depth_(0)
1822
+ #endif
1823
+ {
1824
+ }
1825
+
1826
+ //! Destructor.
1827
+ ~GenericSchemaValidator() {
1828
+ Reset();
1829
+ RAPIDJSON_DELETE(ownStateAllocator_);
1830
+ }
1831
+
1832
+ //! Reset the internal states.
1833
+ void Reset() {
1834
+ while (!schemaStack_.Empty())
1835
+ PopSchema();
1836
+ documentStack_.Clear();
1837
+ error_.SetObject();
1838
+ currentError_.SetNull();
1839
+ missingDependents_.SetNull();
1840
+ valid_ = true;
1841
+ }
1842
+
1843
+ //! Checks whether the current state is valid.
1844
+ // Implementation of ISchemaValidator
1845
+ virtual bool IsValid() const { return valid_; }
1846
+
1847
+ //! Gets the error object.
1848
+ ValueType& GetError() { return error_; }
1849
+ const ValueType& GetError() const { return error_; }
1850
+
1851
+ //! Gets the JSON pointer pointed to the invalid schema.
1852
+ PointerType GetInvalidSchemaPointer() const {
1853
+ return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer();
1854
+ }
1855
+
1856
+ //! Gets the keyword of invalid schema.
1857
+ const Ch* GetInvalidSchemaKeyword() const {
1858
+ return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword;
1859
+ }
1860
+
1861
+ //! Gets the JSON pointer pointed to the invalid value.
1862
+ PointerType GetInvalidDocumentPointer() const {
1863
+ return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch));
1864
+ }
1865
+
1866
+ void NotMultipleOf(int64_t actual, const SValue& expected) {
1867
+ AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);
1868
+ }
1869
+ void NotMultipleOf(uint64_t actual, const SValue& expected) {
1870
+ AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);
1871
+ }
1872
+ void NotMultipleOf(double actual, const SValue& expected) {
1873
+ AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);
1874
+ }
1875
+ void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) {
1876
+ AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,
1877
+ exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
1878
+ }
1879
+ void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) {
1880
+ AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,
1881
+ exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
1882
+ }
1883
+ void AboveMaximum(double actual, const SValue& expected, bool exclusive) {
1884
+ AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,
1885
+ exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
1886
+ }
1887
+ void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) {
1888
+ AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,
1889
+ exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
1890
+ }
1891
+ void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) {
1892
+ AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,
1893
+ exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
1894
+ }
1895
+ void BelowMinimum(double actual, const SValue& expected, bool exclusive) {
1896
+ AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,
1897
+ exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
1898
+ }
1899
+
1900
+ void TooLong(const Ch* str, SizeType length, SizeType expected) {
1901
+ AddNumberError(SchemaType::GetMaxLengthString(),
1902
+ ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
1903
+ }
1904
+ void TooShort(const Ch* str, SizeType length, SizeType expected) {
1905
+ AddNumberError(SchemaType::GetMinLengthString(),
1906
+ ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
1907
+ }
1908
+ void DoesNotMatch(const Ch* str, SizeType length) {
1909
+ currentError_.SetObject();
1910
+ currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator());
1911
+ AddCurrentError(SchemaType::GetPatternString());
1912
+ }
1913
+
1914
+ void DisallowedItem(SizeType index) {
1915
+ currentError_.SetObject();
1916
+ currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator());
1917
+ AddCurrentError(SchemaType::GetAdditionalItemsString(), true);
1918
+ }
1919
+ void TooFewItems(SizeType actualCount, SizeType expectedCount) {
1920
+ AddNumberError(SchemaType::GetMinItemsString(),
1921
+ ValueType(actualCount).Move(), SValue(expectedCount).Move());
1922
+ }
1923
+ void TooManyItems(SizeType actualCount, SizeType expectedCount) {
1924
+ AddNumberError(SchemaType::GetMaxItemsString(),
1925
+ ValueType(actualCount).Move(), SValue(expectedCount).Move());
1926
+ }
1927
+ void DuplicateItems(SizeType index1, SizeType index2) {
1928
+ ValueType duplicates(kArrayType);
1929
+ duplicates.PushBack(index1, GetStateAllocator());
1930
+ duplicates.PushBack(index2, GetStateAllocator());
1931
+ currentError_.SetObject();
1932
+ currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator());
1933
+ AddCurrentError(SchemaType::GetUniqueItemsString(), true);
1934
+ }
1935
+
1936
+ void TooManyProperties(SizeType actualCount, SizeType expectedCount) {
1937
+ AddNumberError(SchemaType::GetMaxPropertiesString(),
1938
+ ValueType(actualCount).Move(), SValue(expectedCount).Move());
1939
+ }
1940
+ void TooFewProperties(SizeType actualCount, SizeType expectedCount) {
1941
+ AddNumberError(SchemaType::GetMinPropertiesString(),
1942
+ ValueType(actualCount).Move(), SValue(expectedCount).Move());
1943
+ }
1944
+ void StartMissingProperties() {
1945
+ currentError_.SetArray();
1946
+ }
1947
+ void AddMissingProperty(const SValue& name) {
1948
+ currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator());
1949
+ }
1950
+ bool EndMissingProperties() {
1951
+ if (currentError_.Empty())
1952
+ return false;
1953
+ ValueType error(kObjectType);
1954
+ error.AddMember(GetMissingString(), currentError_, GetStateAllocator());
1955
+ currentError_ = error;
1956
+ AddCurrentError(SchemaType::GetRequiredString());
1957
+ return true;
1958
+ }
1959
+ void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) {
1960
+ for (SizeType i = 0; i < count; ++i)
1961
+ MergeError(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError());
1962
+ }
1963
+ void DisallowedProperty(const Ch* name, SizeType length) {
1964
+ currentError_.SetObject();
1965
+ currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator());
1966
+ AddCurrentError(SchemaType::GetAdditionalPropertiesString(), true);
1967
+ }
1968
+
1969
+ void StartDependencyErrors() {
1970
+ currentError_.SetObject();
1971
+ }
1972
+ void StartMissingDependentProperties() {
1973
+ missingDependents_.SetArray();
1974
+ }
1975
+ void AddMissingDependentProperty(const SValue& targetName) {
1976
+ missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator());
1977
+ }
1978
+ void EndMissingDependentProperties(const SValue& sourceName) {
1979
+ if (!missingDependents_.Empty())
1980
+ currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),
1981
+ missingDependents_, GetStateAllocator());
1982
+ }
1983
+ void AddDependencySchemaError(const SValue& sourceName, ISchemaValidator* subvalidator) {
1984
+ currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),
1985
+ static_cast<GenericSchemaValidator*>(subvalidator)->GetError(), GetStateAllocator());
1986
+ }
1987
+ bool EndDependencyErrors() {
1988
+ if (currentError_.ObjectEmpty())
1989
+ return false;
1990
+ ValueType error(kObjectType);
1991
+ error.AddMember(GetErrorsString(), currentError_, GetStateAllocator());
1992
+ currentError_ = error;
1993
+ AddCurrentError(SchemaType::GetDependenciesString());
1994
+ return true;
1995
+ }
1996
+
1997
+ void DisallowedValue() {
1998
+ currentError_.SetObject();
1999
+ AddCurrentError(SchemaType::GetEnumString());
2000
+ }
2001
+ void StartDisallowedType() {
2002
+ currentError_.SetArray();
2003
+ }
2004
+ void AddExpectedType(const typename SchemaType::ValueType& expectedType) {
2005
+ currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator());
2006
+ }
2007
+ void EndDisallowedType(const typename SchemaType::ValueType& actualType) {
2008
+ ValueType error(kObjectType);
2009
+ error.AddMember(GetExpectedString(), currentError_, GetStateAllocator());
2010
+ error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator());
2011
+ currentError_ = error;
2012
+ AddCurrentError(SchemaType::GetTypeString());
2013
+ }
2014
+ void NotAllOf(ISchemaValidator** subvalidators, SizeType count) {
2015
+ for (SizeType i = 0; i < count; ++i) {
2016
+ MergeError(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError());
2017
+ }
2018
+ }
2019
+ void NoneOf(ISchemaValidator** subvalidators, SizeType count) {
2020
+ AddErrorArray(SchemaType::GetAnyOfString(), subvalidators, count);
2021
+ }
2022
+ void NotOneOf(ISchemaValidator** subvalidators, SizeType count) {
2023
+ AddErrorArray(SchemaType::GetOneOfString(), subvalidators, count);
2024
+ }
2025
+ void Disallowed() {
2026
+ currentError_.SetObject();
2027
+ AddCurrentError(SchemaType::GetNotString());
2028
+ }
2029
+
2030
+ #define RAPIDJSON_STRING_(name, ...) \
2031
+ static const StringRefType& Get##name##String() {\
2032
+ static const Ch s[] = { __VA_ARGS__, '\0' };\
2033
+ static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \
2034
+ return v;\
2035
+ }
2036
+
2037
+ RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f')
2038
+ RAPIDJSON_STRING_(SchemaRef, 's', 'c', 'h', 'e', 'm', 'a', 'R', 'e', 'f')
2039
+ RAPIDJSON_STRING_(Expected, 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd')
2040
+ RAPIDJSON_STRING_(Actual, 'a', 'c', 't', 'u', 'a', 'l')
2041
+ RAPIDJSON_STRING_(Disallowed, 'd', 'i', 's', 'a', 'l', 'l', 'o', 'w', 'e', 'd')
2042
+ RAPIDJSON_STRING_(Missing, 'm', 'i', 's', 's', 'i', 'n', 'g')
2043
+ RAPIDJSON_STRING_(Errors, 'e', 'r', 'r', 'o', 'r', 's')
2044
+ RAPIDJSON_STRING_(Duplicates, 'd', 'u', 'p', 'l', 'i', 'c', 'a', 't', 'e', 's')
2045
+
2046
+ #undef RAPIDJSON_STRING_
2047
+
2048
+ #if RAPIDJSON_SCHEMA_VERBOSE
2049
+ #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
2050
+ RAPIDJSON_MULTILINEMACRO_BEGIN\
2051
+ *documentStack_.template Push<Ch>() = '\0';\
2052
+ documentStack_.template Pop<Ch>(1);\
2053
+ internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\
2054
+ RAPIDJSON_MULTILINEMACRO_END
2055
+ #else
2056
+ #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
2057
+ #endif
2058
+
2059
+ #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\
2060
+ if (!valid_) return false; \
2061
+ if (!BeginValue() || !CurrentSchema().method arg1) {\
2062
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\
2063
+ return valid_ = false;\
2064
+ }
2065
+
2066
+ #define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
2067
+ for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
2068
+ if (context->hasher)\
2069
+ static_cast<HasherType*>(context->hasher)->method arg2;\
2070
+ if (context->validators)\
2071
+ for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\
2072
+ static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\
2073
+ if (context->patternPropertiesValidators)\
2074
+ for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\
2075
+ static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\
2076
+ }
2077
+
2078
+ #define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
2079
+ return valid_ = EndValue() && (!outputHandler_ || outputHandler_->method arg2)
2080
+
2081
+ #define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
2082
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\
2083
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\
2084
+ RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2)
2085
+
2086
+ bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ( )); }
2087
+ bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); }
2088
+ bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); }
2089
+ bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); }
2090
+ bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); }
2091
+ bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
2092
+ bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
2093
+ bool RawNumber(const Ch* str, SizeType length, bool copy)
2094
+ { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
2095
+ bool String(const Ch* str, SizeType length, bool copy)
2096
+ { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
2097
+
2098
+ bool StartObject() {
2099
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
2100
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ());
2101
+ return valid_ = !outputHandler_ || outputHandler_->StartObject();
2102
+ }
2103
+
2104
+ bool Key(const Ch* str, SizeType len, bool copy) {
2105
+ if (!valid_) return false;
2106
+ AppendToken(str, len);
2107
+ if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false;
2108
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));
2109
+ return valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy);
2110
+ }
2111
+
2112
+ bool EndObject(SizeType memberCount) {
2113
+ if (!valid_) return false;
2114
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount));
2115
+ if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false;
2116
+ RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));
2117
+ }
2118
+
2119
+ bool StartArray() {
2120
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));
2121
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ());
2122
+ return valid_ = !outputHandler_ || outputHandler_->StartArray();
2123
+ }
2124
+
2125
+ bool EndArray(SizeType elementCount) {
2126
+ if (!valid_) return false;
2127
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount));
2128
+ if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false;
2129
+ RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));
2130
+ }
2131
+
2132
+ #undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_
2133
+ #undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_
2134
+ #undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_
2135
+ #undef RAPIDJSON_SCHEMA_HANDLE_VALUE_
2136
+
2137
+ // Implementation of ISchemaStateFactory<SchemaType>
2138
+ virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) {
2139
+ return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, documentStack_.template Bottom<char>(), documentStack_.GetSize(),
2140
+ #if RAPIDJSON_SCHEMA_VERBOSE
2141
+ depth_ + 1,
2142
+ #endif
2143
+ &GetStateAllocator());
2144
+ }
2145
+
2146
+ virtual void DestroySchemaValidator(ISchemaValidator* validator) {
2147
+ GenericSchemaValidator* v = static_cast<GenericSchemaValidator*>(validator);
2148
+ v->~GenericSchemaValidator();
2149
+ StateAllocator::Free(v);
2150
+ }
2151
+
2152
+ virtual void* CreateHasher() {
2153
+ return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator());
2154
+ }
2155
+
2156
+ virtual uint64_t GetHashCode(void* hasher) {
2157
+ return static_cast<HasherType*>(hasher)->GetHashCode();
2158
+ }
2159
+
2160
+ virtual void DestroryHasher(void* hasher) {
2161
+ HasherType* h = static_cast<HasherType*>(hasher);
2162
+ h->~HasherType();
2163
+ StateAllocator::Free(h);
2164
+ }
2165
+
2166
+ virtual void* MallocState(size_t size) {
2167
+ return GetStateAllocator().Malloc(size);
2168
+ }
2169
+
2170
+ virtual void FreeState(void* p) {
2171
+ StateAllocator::Free(p);
2172
+ }
2173
+
2174
+ private:
2175
+ typedef typename SchemaType::Context Context;
2176
+ typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray;
2177
+ typedef internal::Hasher<EncodingType, StateAllocator> HasherType;
2178
+
2179
+ GenericSchemaValidator(
2180
+ const SchemaDocumentType& schemaDocument,
2181
+ const SchemaType& root,
2182
+ const char* basePath, size_t basePathSize,
2183
+ #if RAPIDJSON_SCHEMA_VERBOSE
2184
+ unsigned depth,
2185
+ #endif
2186
+ StateAllocator* allocator = 0,
2187
+ size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
2188
+ size_t documentStackCapacity = kDefaultDocumentStackCapacity)
2189
+ :
2190
+ schemaDocument_(&schemaDocument),
2191
+ root_(root),
2192
+ stateAllocator_(allocator),
2193
+ ownStateAllocator_(0),
2194
+ schemaStack_(allocator, schemaStackCapacity),
2195
+ documentStack_(allocator, documentStackCapacity),
2196
+ outputHandler_(0),
2197
+ error_(kObjectType),
2198
+ currentError_(),
2199
+ missingDependents_(),
2200
+ valid_(true)
2201
+ #if RAPIDJSON_SCHEMA_VERBOSE
2202
+ , depth_(depth)
2203
+ #endif
2204
+ {
2205
+ if (basePath && basePathSize)
2206
+ memcpy(documentStack_.template Push<char>(basePathSize), basePath, basePathSize);
2207
+ }
2208
+
2209
+ StateAllocator& GetStateAllocator() {
2210
+ if (!stateAllocator_)
2211
+ stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)();
2212
+ return *stateAllocator_;
2213
+ }
2214
+
2215
+ bool BeginValue() {
2216
+ if (schemaStack_.Empty())
2217
+ PushSchema(root_);
2218
+ else {
2219
+ if (CurrentContext().inArray)
2220
+ internal::TokenHelper<internal::Stack<StateAllocator>, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex);
2221
+
2222
+ if (!CurrentSchema().BeginValue(CurrentContext()))
2223
+ return false;
2224
+
2225
+ SizeType count = CurrentContext().patternPropertiesSchemaCount;
2226
+ const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
2227
+ typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
2228
+ bool valueUniqueness = CurrentContext().valueUniqueness;
2229
+ RAPIDJSON_ASSERT(CurrentContext().valueSchema);
2230
+ PushSchema(*CurrentContext().valueSchema);
2231
+
2232
+ if (count > 0) {
2233
+ CurrentContext().objectPatternValidatorType = patternValidatorType;
2234
+ ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
2235
+ SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
2236
+ va = static_cast<ISchemaValidator**>(MallocState(sizeof(ISchemaValidator*) * count));
2237
+ for (SizeType i = 0; i < count; i++)
2238
+ va[validatorCount++] = CreateSchemaValidator(*sa[i]);
2239
+ }
2240
+
2241
+ CurrentContext().arrayUniqueness = valueUniqueness;
2242
+ }
2243
+ return true;
2244
+ }
2245
+
2246
+ bool EndValue() {
2247
+ if (!CurrentSchema().EndValue(CurrentContext()))
2248
+ return false;
2249
+
2250
+ #if RAPIDJSON_SCHEMA_VERBOSE
2251
+ GenericStringBuffer<EncodingType> sb;
2252
+ schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
2253
+
2254
+ *documentStack_.template Push<Ch>() = '\0';
2255
+ documentStack_.template Pop<Ch>(1);
2256
+ internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());
2257
+ #endif
2258
+
2259
+ uint64_t h = CurrentContext().arrayUniqueness ? static_cast<HasherType*>(CurrentContext().hasher)->GetHashCode() : 0;
2260
+
2261
+ PopSchema();
2262
+
2263
+ if (!schemaStack_.Empty()) {
2264
+ Context& context = CurrentContext();
2265
+ if (context.valueUniqueness) {
2266
+ HashCodeArray* a = static_cast<HashCodeArray*>(context.arrayElementHashCodes);
2267
+ if (!a)
2268
+ CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType);
2269
+ for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr)
2270
+ if (itr->GetUint64() == h) {
2271
+ DuplicateItems(static_cast<SizeType>(itr - a->Begin()), a->Size());
2272
+ RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString());
2273
+ }
2274
+ a->PushBack(h, GetStateAllocator());
2275
+ }
2276
+ }
2277
+
2278
+ // Remove the last token of document pointer
2279
+ while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/')
2280
+ ;
2281
+
2282
+ return true;
2283
+ }
2284
+
2285
+ void AppendToken(const Ch* str, SizeType len) {
2286
+ documentStack_.template Reserve<Ch>(1 + len * 2); // worst case all characters are escaped as two characters
2287
+ *documentStack_.template PushUnsafe<Ch>() = '/';
2288
+ for (SizeType i = 0; i < len; i++) {
2289
+ if (str[i] == '~') {
2290
+ *documentStack_.template PushUnsafe<Ch>() = '~';
2291
+ *documentStack_.template PushUnsafe<Ch>() = '0';
2292
+ }
2293
+ else if (str[i] == '/') {
2294
+ *documentStack_.template PushUnsafe<Ch>() = '~';
2295
+ *documentStack_.template PushUnsafe<Ch>() = '1';
2296
+ }
2297
+ else
2298
+ *documentStack_.template PushUnsafe<Ch>() = str[i];
2299
+ }
2300
+ }
2301
+
2302
+ RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, *this, &schema); }
2303
+
2304
+ RAPIDJSON_FORCEINLINE void PopSchema() {
2305
+ Context* c = schemaStack_.template Pop<Context>(1);
2306
+ if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) {
2307
+ a->~HashCodeArray();
2308
+ StateAllocator::Free(a);
2309
+ }
2310
+ c->~Context();
2311
+ }
2312
+
2313
+ void AddErrorLocation(ValueType& result, bool parent) {
2314
+ GenericStringBuffer<EncodingType> sb;
2315
+ PointerType instancePointer = GetInvalidDocumentPointer();
2316
+ ((parent && instancePointer.GetTokenCount() > 0)
2317
+ ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1)
2318
+ : instancePointer).StringifyUriFragment(sb);
2319
+ ValueType instanceRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
2320
+ GetStateAllocator());
2321
+ result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator());
2322
+ sb.Clear();
2323
+ memcpy(sb.Push(CurrentSchema().GetURI().GetStringLength()),
2324
+ CurrentSchema().GetURI().GetString(),
2325
+ CurrentSchema().GetURI().GetStringLength() * sizeof(Ch));
2326
+ GetInvalidSchemaPointer().StringifyUriFragment(sb);
2327
+ ValueType schemaRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
2328
+ GetStateAllocator());
2329
+ result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator());
2330
+ }
2331
+
2332
+ void AddError(ValueType& keyword, ValueType& error) {
2333
+ typename ValueType::MemberIterator member = error_.FindMember(keyword);
2334
+ if (member == error_.MemberEnd())
2335
+ error_.AddMember(keyword, error, GetStateAllocator());
2336
+ else {
2337
+ if (member->value.IsObject()) {
2338
+ ValueType errors(kArrayType);
2339
+ errors.PushBack(member->value, GetStateAllocator());
2340
+ member->value = errors;
2341
+ }
2342
+ member->value.PushBack(error, GetStateAllocator());
2343
+ }
2344
+ }
2345
+
2346
+ void AddCurrentError(const typename SchemaType::ValueType& keyword, bool parent = false) {
2347
+ AddErrorLocation(currentError_, parent);
2348
+ AddError(ValueType(keyword, GetStateAllocator(), false).Move(), currentError_);
2349
+ }
2350
+
2351
+ void MergeError(ValueType& other) {
2352
+ for (typename ValueType::MemberIterator it = other.MemberBegin(), end = other.MemberEnd(); it != end; ++it) {
2353
+ AddError(it->name, it->value);
2354
+ }
2355
+ }
2356
+
2357
+ void AddNumberError(const typename SchemaType::ValueType& keyword, ValueType& actual, const SValue& expected,
2358
+ const typename SchemaType::ValueType& (*exclusive)() = 0) {
2359
+ currentError_.SetObject();
2360
+ currentError_.AddMember(GetActualString(), actual, GetStateAllocator());
2361
+ currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator());
2362
+ if (exclusive)
2363
+ currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(), true, GetStateAllocator());
2364
+ AddCurrentError(keyword);
2365
+ }
2366
+
2367
+ void AddErrorArray(const typename SchemaType::ValueType& keyword,
2368
+ ISchemaValidator** subvalidators, SizeType count) {
2369
+ ValueType errors(kArrayType);
2370
+ for (SizeType i = 0; i < count; ++i)
2371
+ errors.PushBack(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError(), GetStateAllocator());
2372
+ currentError_.SetObject();
2373
+ currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator());
2374
+ AddCurrentError(keyword);
2375
+ }
2376
+
2377
+ const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; }
2378
+ Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
2379
+ const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); }
2380
+
2381
+ static const size_t kDefaultSchemaStackCapacity = 1024;
2382
+ static const size_t kDefaultDocumentStackCapacity = 256;
2383
+ const SchemaDocumentType* schemaDocument_;
2384
+ const SchemaType& root_;
2385
+ StateAllocator* stateAllocator_;
2386
+ StateAllocator* ownStateAllocator_;
2387
+ internal::Stack<StateAllocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *)
2388
+ internal::Stack<StateAllocator> documentStack_; //!< stack to store the current path of validating document (Ch)
2389
+ OutputHandler* outputHandler_;
2390
+ ValueType error_;
2391
+ ValueType currentError_;
2392
+ ValueType missingDependents_;
2393
+ bool valid_;
2394
+ #if RAPIDJSON_SCHEMA_VERBOSE
2395
+ unsigned depth_;
2396
+ #endif
2397
+ };
2398
+
2399
+ typedef GenericSchemaValidator<SchemaDocument> SchemaValidator;
2400
+
2401
+ ///////////////////////////////////////////////////////////////////////////////
2402
+ // SchemaValidatingReader
2403
+
2404
+ //! A helper class for parsing with validation.
2405
+ /*!
2406
+ This helper class is a functor, designed as a parameter of \ref GenericDocument::Populate().
2407
+
2408
+ \tparam parseFlags Combination of \ref ParseFlag.
2409
+ \tparam InputStream Type of input stream, implementing Stream concept.
2410
+ \tparam SourceEncoding Encoding of the input stream.
2411
+ \tparam SchemaDocumentType Type of schema document.
2412
+ \tparam StackAllocator Allocator type for stack.
2413
+ */
2414
+ template <
2415
+ unsigned parseFlags,
2416
+ typename InputStream,
2417
+ typename SourceEncoding,
2418
+ typename SchemaDocumentType = SchemaDocument,
2419
+ typename StackAllocator = CrtAllocator>
2420
+ class SchemaValidatingReader {
2421
+ public:
2422
+ typedef typename SchemaDocumentType::PointerType PointerType;
2423
+ typedef typename InputStream::Ch Ch;
2424
+ typedef GenericValue<SourceEncoding, StackAllocator> ValueType;
2425
+
2426
+ //! Constructor
2427
+ /*!
2428
+ \param is Input stream.
2429
+ \param sd Schema document.
2430
+ */
2431
+ SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), error_(kObjectType), isValid_(true) {}
2432
+
2433
+ template <typename Handler>
2434
+ bool operator()(Handler& handler) {
2435
+ GenericReader<SourceEncoding, typename SchemaDocumentType::EncodingType, StackAllocator> reader;
2436
+ GenericSchemaValidator<SchemaDocumentType, Handler> validator(sd_, handler);
2437
+ parseResult_ = reader.template Parse<parseFlags>(is_, validator);
2438
+
2439
+ isValid_ = validator.IsValid();
2440
+ if (isValid_) {
2441
+ invalidSchemaPointer_ = PointerType();
2442
+ invalidSchemaKeyword_ = 0;
2443
+ invalidDocumentPointer_ = PointerType();
2444
+ error_.SetObject();
2445
+ }
2446
+ else {
2447
+ invalidSchemaPointer_ = validator.GetInvalidSchemaPointer();
2448
+ invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword();
2449
+ invalidDocumentPointer_ = validator.GetInvalidDocumentPointer();
2450
+ error_.CopyFrom(validator.GetError(), allocator_);
2451
+ }
2452
+
2453
+ return parseResult_;
2454
+ }
2455
+
2456
+ const ParseResult& GetParseResult() const { return parseResult_; }
2457
+ bool IsValid() const { return isValid_; }
2458
+ const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; }
2459
+ const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; }
2460
+ const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; }
2461
+ const ValueType& GetError() const { return error_; }
2462
+
2463
+ private:
2464
+ InputStream& is_;
2465
+ const SchemaDocumentType& sd_;
2466
+
2467
+ ParseResult parseResult_;
2468
+ PointerType invalidSchemaPointer_;
2469
+ const Ch* invalidSchemaKeyword_;
2470
+ PointerType invalidDocumentPointer_;
2471
+ StackAllocator allocator_;
2472
+ ValueType error_;
2473
+ bool isValid_;
2474
+ };
2475
+
2476
+ RAPIDJSON_NAMESPACE_END
2477
+ RAPIDJSON_DIAG_POP
2478
+
2479
+ #endif // RAPIDJSON_SCHEMA_H_