passenger 3.0.21 → 3.9.1.beta

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (835) hide show
  1. data/DEVELOPERS.TXT +4 -10
  2. data/NEWS +19 -27
  3. data/Rakefile +20 -19
  4. data/bin/passenger +3 -2
  5. data/bin/passenger-config +35 -5
  6. data/bin/passenger-install-apache2-module +12 -12
  7. data/bin/passenger-install-nginx-module +55 -38
  8. data/bin/passenger-memory-stats +3 -1
  9. data/bin/passenger-status +7 -35
  10. data/build/agents.rb +107 -21
  11. data/build/apache2.rb +11 -46
  12. data/build/basics.rb +61 -9
  13. data/build/common_library.rb +59 -142
  14. data/build/cxx_tests.rb +111 -110
  15. data/build/documentation.rb +33 -0
  16. data/build/misc.rb +30 -12
  17. data/build/nginx.rb +10 -39
  18. data/build/oxt_tests.rb +1 -0
  19. data/build/ruby_extension.rb +1 -5
  20. data/build/test_basics.rb +3 -2
  21. data/dev/copy_boost_headers.rb +2 -1
  22. data/doc/Architectural overview.html +49 -90
  23. data/doc/DebuggingAndStressTesting.txt.md +49 -0
  24. data/doc/Packaging.txt.md +254 -0
  25. data/doc/Security of user switching support.html +35 -66
  26. data/doc/Users guide Apache.html +588 -758
  27. data/doc/Users guide Apache.idmap.txt +253 -136
  28. data/doc/Users guide Apache.txt +154 -109
  29. data/doc/Users guide Nginx.html +544 -660
  30. data/doc/Users guide Nginx.idmap.txt +179 -91
  31. data/doc/Users guide Nginx.txt +192 -118
  32. data/doc/Users guide Standalone.html +65 -48
  33. data/doc/Users guide Standalone.idmap.txt +10 -2
  34. data/doc/Users guide Standalone.txt +4 -0
  35. data/doc/images/glyphicons-halflings-white.png +0 -0
  36. data/doc/images/glyphicons-halflings.png +0 -0
  37. data/doc/images/phusion_banner_small.png +0 -0
  38. data/doc/images/{smart-lv2.png → smart.png} +0 -0
  39. data/doc/images/{smart-lv2.svg → smart.svg} +0 -0
  40. data/doc/templates/bootstrap.min.css +397 -0
  41. data/doc/templates/markdown.html.erb +117 -0
  42. data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +2 -1
  43. data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +26 -48
  44. data/doc/users_guide_snippets/passenger_spawn_method.txt +18 -30
  45. data/doc/users_guide_snippets/support_information.txt +30 -0
  46. data/ext/apache2/Bucket.cpp +9 -26
  47. data/ext/apache2/Bucket.h +13 -10
  48. data/ext/apache2/Configuration.cpp +70 -58
  49. data/ext/apache2/Configuration.hpp +19 -47
  50. data/ext/apache2/DirectoryMapper.h +7 -7
  51. data/ext/apache2/Hooks.cpp +150 -313
  52. data/ext/boost/algorithm/string/detail/case_conv.hpp +4 -2
  53. data/ext/boost/algorithm/string/detail/find_format.hpp +20 -20
  54. data/ext/boost/algorithm/string/detail/find_format_all.hpp +23 -23
  55. data/ext/boost/algorithm/string/detail/find_format_store.hpp +2 -2
  56. data/ext/boost/algorithm/string/detail/formatter.hpp +25 -0
  57. data/ext/boost/algorithm/string/formatter.hpp +20 -3
  58. data/ext/boost/assert.hpp +85 -4
  59. data/ext/boost/bind/bind.hpp +1 -1
  60. data/ext/boost/concept/detail/backward_compatibility.hpp +1 -1
  61. data/ext/boost/concept_check.hpp +140 -64
  62. data/ext/boost/config.hpp +1 -1
  63. data/ext/boost/config/auto_link.hpp +8 -6
  64. data/ext/boost/config/compiler/borland.hpp +12 -2
  65. data/ext/boost/config/compiler/clang.hpp +89 -30
  66. data/ext/boost/config/compiler/codegear.hpp +3 -2
  67. data/ext/boost/config/compiler/common_edg.hpp +7 -5
  68. data/ext/boost/config/compiler/cray.hpp +61 -0
  69. data/ext/boost/config/compiler/digitalmars.hpp +9 -1
  70. data/ext/boost/config/compiler/gcc.hpp +33 -24
  71. data/ext/boost/config/compiler/gcc_xml.hpp +4 -0
  72. data/ext/boost/config/compiler/hp_acc.hpp +12 -1
  73. data/ext/boost/config/compiler/intel.hpp +78 -4
  74. data/ext/boost/config/compiler/metrowerks.hpp +4 -1
  75. data/ext/boost/config/compiler/mpw.hpp +4 -1
  76. data/ext/boost/config/compiler/nvcc.hpp +8 -66
  77. data/ext/boost/config/compiler/pathscale.hpp +80 -0
  78. data/ext/boost/config/compiler/pgi.hpp +5 -5
  79. data/ext/boost/config/compiler/sunpro_cc.hpp +4 -1
  80. data/ext/boost/config/compiler/vacpp.hpp +37 -13
  81. data/ext/boost/config/compiler/visualc.hpp +24 -11
  82. data/ext/boost/config/platform/bsd.hpp +1 -1
  83. data/ext/boost/config/platform/cray.hpp +18 -0
  84. data/ext/boost/config/platform/cygwin.hpp +10 -0
  85. data/ext/boost/config/platform/linux.hpp +5 -0
  86. data/ext/boost/config/platform/macos.hpp +5 -4
  87. data/ext/boost/config/platform/symbian.hpp +5 -2
  88. data/ext/boost/config/platform/vms.hpp +25 -0
  89. data/ext/boost/config/platform/win32.hpp +7 -1
  90. data/ext/boost/config/select_compiler_config.hpp +8 -25
  91. data/ext/boost/config/select_platform_config.hpp +8 -1
  92. data/ext/boost/config/select_stdlib_config.hpp +9 -1
  93. data/ext/boost/config/stdlib/dinkumware.hpp +6 -9
  94. data/ext/boost/config/stdlib/libcomo.hpp +1 -4
  95. data/ext/boost/config/stdlib/libcpp.hpp +36 -0
  96. data/ext/boost/config/stdlib/libstdcpp3.hpp +37 -11
  97. data/ext/boost/config/stdlib/modena.hpp +1 -4
  98. data/ext/boost/config/stdlib/msl.hpp +1 -4
  99. data/ext/boost/config/stdlib/roguewave.hpp +9 -6
  100. data/ext/boost/config/stdlib/sgi.hpp +12 -4
  101. data/ext/boost/config/stdlib/stlport.hpp +11 -4
  102. data/ext/boost/config/stdlib/vacpp.hpp +11 -4
  103. data/ext/boost/config/suffix.hpp +71 -6
  104. data/ext/boost/config/warning_disable.hpp +1 -1
  105. data/ext/boost/container/container_fwd.hpp +177 -0
  106. data/ext/boost/cstdint.hpp +17 -12
  107. data/ext/boost/current_function.hpp +2 -1
  108. data/ext/boost/date_time/c_time.hpp +17 -1
  109. data/ext/boost/date_time/compiler_config.hpp +13 -15
  110. data/ext/boost/date_time/date_formatting.hpp +7 -1
  111. data/ext/boost/date_time/filetime_functions.hpp +4 -4
  112. data/ext/boost/date_time/gregorian_calendar.ipp +2 -2
  113. data/ext/boost/date_time/strings_from_facet.hpp +3 -3
  114. data/ext/boost/date_time/time_facet.hpp +101 -101
  115. data/ext/boost/detail/endian.hpp +4 -2
  116. data/ext/boost/detail/fenv.hpp +74 -0
  117. data/ext/boost/detail/sp_typeinfo.hpp +6 -0
  118. data/ext/boost/exception/detail/clone_current_exception.hpp +47 -0
  119. data/ext/boost/exception/detail/exception_ptr.hpp +194 -122
  120. data/ext/boost/exception/detail/type_info.hpp +3 -3
  121. data/ext/boost/exception/diagnostic_information.hpp +37 -21
  122. data/ext/boost/exception/exception.hpp +21 -1
  123. data/ext/boost/exception/info.hpp +0 -1
  124. data/ext/boost/function.hpp +2 -2
  125. data/ext/boost/function/function_base.hpp +15 -9
  126. data/ext/boost/function/function_template.hpp +26 -48
  127. data/ext/boost/integer_fwd.hpp +0 -16
  128. data/ext/boost/integer_traits.hpp +2 -2
  129. data/ext/boost/iterator.hpp +1 -1
  130. data/ext/boost/iterator/iterator_adaptor.hpp +1 -7
  131. data/ext/boost/iterator/iterator_facade.hpp +13 -13
  132. data/ext/boost/iterator/transform_iterator.hpp +5 -20
  133. data/ext/boost/lexical_cast.hpp +1655 -673
  134. data/ext/boost/math/policies/policy.hpp +982 -0
  135. data/ext/boost/math/special_functions/detail/fp_traits.hpp +570 -0
  136. data/ext/boost/math/special_functions/detail/round_fwd.hpp +80 -0
  137. data/ext/boost/math/special_functions/fpclassify.hpp +533 -0
  138. data/ext/boost/math/special_functions/math_fwd.hpp +1070 -0
  139. data/ext/boost/math/special_functions/sign.hpp +145 -0
  140. data/ext/boost/math/tools/config.hpp +321 -0
  141. data/ext/boost/math/tools/promotion.hpp +150 -0
  142. data/ext/boost/math/tools/real_cast.hpp +29 -0
  143. data/ext/boost/math/tools/user.hpp +97 -0
  144. data/ext/boost/move/move.hpp +1222 -0
  145. data/ext/boost/mpl/O1_size.hpp +40 -0
  146. data/ext/boost/mpl/O1_size_fwd.hpp +24 -0
  147. data/ext/boost/mpl/advance.hpp +76 -0
  148. data/ext/boost/mpl/advance_fwd.hpp +28 -0
  149. data/ext/boost/mpl/at.hpp +52 -0
  150. data/ext/boost/mpl/at_fwd.hpp +24 -0
  151. data/ext/boost/mpl/aux_/O1_size_impl.hpp +87 -0
  152. data/ext/boost/mpl/aux_/advance_backward.hpp +128 -0
  153. data/ext/boost/mpl/aux_/advance_forward.hpp +127 -0
  154. data/ext/boost/mpl/aux_/arithmetic_op.hpp +92 -0
  155. data/ext/boost/mpl/aux_/at_impl.hpp +45 -0
  156. data/ext/boost/mpl/aux_/begin_end_impl.hpp +101 -0
  157. data/ext/boost/mpl/aux_/clear_impl.hpp +35 -0
  158. data/ext/boost/mpl/aux_/comparison_op.hpp +83 -0
  159. data/ext/boost/mpl/aux_/config/forwarding.hpp +27 -0
  160. data/ext/boost/mpl/aux_/config/typeof.hpp +38 -0
  161. data/ext/boost/mpl/aux_/contains_impl.hpp +61 -0
  162. data/ext/boost/mpl/aux_/find_if_pred.hpp +31 -0
  163. data/ext/boost/mpl/aux_/fold_impl.hpp +43 -0
  164. data/ext/boost/mpl/aux_/has_begin.hpp +23 -0
  165. data/ext/boost/mpl/aux_/has_size.hpp +23 -0
  166. data/ext/boost/mpl/aux_/has_tag.hpp +23 -0
  167. data/ext/boost/mpl/aux_/inserter_algorithm.hpp +159 -0
  168. data/ext/boost/mpl/aux_/is_msvc_eti_arg.hpp +64 -0
  169. data/ext/boost/mpl/aux_/iter_apply.hpp +47 -0
  170. data/ext/boost/mpl/aux_/iter_fold_if_impl.hpp +210 -0
  171. data/ext/boost/mpl/aux_/iter_fold_impl.hpp +42 -0
  172. data/ext/boost/mpl/aux_/lambda_spec.hpp +49 -0
  173. data/ext/boost/mpl/aux_/largest_int.hpp +63 -0
  174. data/ext/boost/mpl/aux_/msvc_eti_base.hpp +77 -0
  175. data/ext/boost/mpl/aux_/msvc_type.hpp +62 -0
  176. data/ext/boost/mpl/aux_/numeric_cast_utils.hpp +77 -0
  177. data/ext/boost/mpl/aux_/numeric_op.hpp +315 -0
  178. data/ext/boost/mpl/aux_/preprocessed/gcc/advance_backward.hpp +97 -0
  179. data/ext/boost/mpl/aux_/preprocessed/gcc/advance_forward.hpp +97 -0
  180. data/ext/boost/mpl/aux_/preprocessed/gcc/equal_to.hpp +94 -0
  181. data/ext/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp +180 -0
  182. data/ext/boost/mpl/aux_/preprocessed/gcc/greater.hpp +94 -0
  183. data/ext/boost/mpl/aux_/preprocessed/gcc/greater_equal.hpp +94 -0
  184. data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp +133 -0
  185. data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_impl.hpp +180 -0
  186. data/ext/boost/mpl/aux_/preprocessed/gcc/less.hpp +94 -0
  187. data/ext/boost/mpl/aux_/preprocessed/gcc/less_equal.hpp +94 -0
  188. data/ext/boost/mpl/aux_/preprocessed/gcc/list.hpp +323 -0
  189. data/ext/boost/mpl/aux_/preprocessed/gcc/minus.hpp +146 -0
  190. data/ext/boost/mpl/aux_/preprocessed/gcc/not_equal_to.hpp +94 -0
  191. data/ext/boost/mpl/aux_/preprocessed/gcc/plus.hpp +146 -0
  192. data/ext/boost/mpl/aux_/preprocessed/gcc/reverse_fold_impl.hpp +231 -0
  193. data/ext/boost/mpl/aux_/preprocessed/gcc/times.hpp +146 -0
  194. data/ext/boost/mpl/aux_/preprocessed/gcc/vector.hpp +323 -0
  195. data/ext/boost/mpl/aux_/preprocessor/default_params.hpp +67 -0
  196. data/ext/boost/mpl/aux_/push_back_impl.hpp +70 -0
  197. data/ext/boost/mpl/aux_/push_front_impl.hpp +71 -0
  198. data/ext/boost/mpl/aux_/reverse_fold_impl.hpp +44 -0
  199. data/ext/boost/mpl/aux_/size_impl.hpp +52 -0
  200. data/ext/boost/mpl/aux_/traits_lambda_spec.hpp +63 -0
  201. data/ext/boost/mpl/back_fwd.hpp +24 -0
  202. data/ext/boost/mpl/back_inserter.hpp +34 -0
  203. data/ext/boost/mpl/begin_end.hpp +57 -0
  204. data/ext/boost/mpl/begin_end_fwd.hpp +27 -0
  205. data/ext/boost/mpl/clear.hpp +39 -0
  206. data/ext/boost/mpl/clear_fwd.hpp +24 -0
  207. data/ext/boost/mpl/comparison.hpp +24 -0
  208. data/ext/boost/mpl/contains.hpp +41 -0
  209. data/ext/boost/mpl/contains_fwd.hpp +25 -0
  210. data/ext/boost/mpl/deref.hpp +41 -0
  211. data/ext/boost/mpl/distance.hpp +78 -0
  212. data/ext/boost/mpl/distance_fwd.hpp +28 -0
  213. data/ext/boost/mpl/empty_fwd.hpp +24 -0
  214. data/ext/boost/mpl/equal_to.hpp +21 -0
  215. data/ext/boost/mpl/find.hpp +38 -0
  216. data/ext/boost/mpl/find_if.hpp +50 -0
  217. data/ext/boost/mpl/fold.hpp +48 -0
  218. data/ext/boost/mpl/front_fwd.hpp +24 -0
  219. data/ext/boost/mpl/front_inserter.hpp +33 -0
  220. data/ext/boost/mpl/greater.hpp +21 -0
  221. data/ext/boost/mpl/greater_equal.hpp +21 -0
  222. data/ext/boost/mpl/inserter.hpp +32 -0
  223. data/ext/boost/mpl/iter_fold.hpp +49 -0
  224. data/ext/boost/mpl/iter_fold_if.hpp +117 -0
  225. data/ext/boost/mpl/iterator_range.hpp +42 -0
  226. data/ext/boost/mpl/iterator_tags.hpp +27 -0
  227. data/ext/boost/mpl/less.hpp +21 -0
  228. data/ext/boost/mpl/less_equal.hpp +21 -0
  229. data/ext/boost/mpl/limits/list.hpp +21 -0
  230. data/ext/boost/mpl/limits/vector.hpp +21 -0
  231. data/ext/boost/mpl/list.hpp +57 -0
  232. data/ext/boost/mpl/list/aux_/O1_size.hpp +33 -0
  233. data/ext/boost/mpl/list/aux_/begin_end.hpp +44 -0
  234. data/ext/boost/mpl/list/aux_/clear.hpp +34 -0
  235. data/ext/boost/mpl/list/aux_/empty.hpp +34 -0
  236. data/ext/boost/mpl/list/aux_/front.hpp +33 -0
  237. data/ext/boost/mpl/list/aux_/include_preprocessed.hpp +35 -0
  238. data/ext/boost/mpl/list/aux_/item.hpp +55 -0
  239. data/ext/boost/mpl/list/aux_/iterator.hpp +76 -0
  240. data/ext/boost/mpl/list/aux_/pop_front.hpp +34 -0
  241. data/ext/boost/mpl/list/aux_/preprocessed/plain/list10.hpp +149 -0
  242. data/ext/boost/mpl/list/aux_/preprocessed/plain/list20.hpp +169 -0
  243. data/ext/boost/mpl/list/aux_/push_back.hpp +36 -0
  244. data/ext/boost/mpl/list/aux_/push_front.hpp +39 -0
  245. data/ext/boost/mpl/list/aux_/size.hpp +33 -0
  246. data/ext/boost/mpl/list/aux_/tag.hpp +24 -0
  247. data/ext/boost/mpl/list/list0.hpp +42 -0
  248. data/ext/boost/mpl/list/list10.hpp +43 -0
  249. data/ext/boost/mpl/list/list20.hpp +43 -0
  250. data/ext/boost/mpl/long.hpp +22 -0
  251. data/ext/boost/mpl/long_fwd.hpp +27 -0
  252. data/ext/boost/mpl/minus.hpp +21 -0
  253. data/ext/boost/mpl/multiplies.hpp +53 -0
  254. data/ext/boost/mpl/negate.hpp +81 -0
  255. data/ext/boost/mpl/not_equal_to.hpp +21 -0
  256. data/ext/boost/mpl/numeric_cast.hpp +41 -0
  257. data/ext/boost/mpl/pair.hpp +70 -0
  258. data/ext/boost/mpl/plus.hpp +21 -0
  259. data/ext/boost/mpl/pop_back_fwd.hpp +24 -0
  260. data/ext/boost/mpl/pop_front_fwd.hpp +24 -0
  261. data/ext/boost/mpl/prior.hpp +19 -0
  262. data/ext/boost/mpl/push_back.hpp +53 -0
  263. data/ext/boost/mpl/push_back_fwd.hpp +24 -0
  264. data/ext/boost/mpl/push_front.hpp +52 -0
  265. data/ext/boost/mpl/push_front_fwd.hpp +24 -0
  266. data/ext/boost/mpl/remove_if.hpp +83 -0
  267. data/ext/boost/mpl/reverse_fold.hpp +50 -0
  268. data/ext/boost/mpl/same_as.hpp +55 -0
  269. data/ext/boost/mpl/sequence_tag.hpp +124 -0
  270. data/ext/boost/mpl/sequence_tag_fwd.hpp +26 -0
  271. data/ext/boost/mpl/size.hpp +42 -0
  272. data/ext/boost/mpl/size_fwd.hpp +24 -0
  273. data/ext/boost/mpl/tag.hpp +52 -0
  274. data/ext/boost/mpl/times.hpp +21 -0
  275. data/ext/boost/mpl/vector.hpp +57 -0
  276. data/ext/boost/mpl/vector/aux_/O1_size.hpp +56 -0
  277. data/ext/boost/mpl/vector/aux_/at.hpp +116 -0
  278. data/ext/boost/mpl/vector/aux_/back.hpp +59 -0
  279. data/ext/boost/mpl/vector/aux_/begin_end.hpp +49 -0
  280. data/ext/boost/mpl/vector/aux_/clear.hpp +55 -0
  281. data/ext/boost/mpl/vector/aux_/empty.hpp +68 -0
  282. data/ext/boost/mpl/vector/aux_/front.hpp +56 -0
  283. data/ext/boost/mpl/vector/aux_/include_preprocessed.hpp +55 -0
  284. data/ext/boost/mpl/vector/aux_/item.hpp +103 -0
  285. data/ext/boost/mpl/vector/aux_/iterator.hpp +130 -0
  286. data/ext/boost/mpl/vector/aux_/pop_back.hpp +40 -0
  287. data/ext/boost/mpl/vector/aux_/pop_front.hpp +40 -0
  288. data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector10.hpp +829 -0
  289. data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector20.hpp +1144 -0
  290. data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10.hpp +139 -0
  291. data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20.hpp +159 -0
  292. data/ext/boost/mpl/vector/aux_/push_back.hpp +40 -0
  293. data/ext/boost/mpl/vector/aux_/push_front.hpp +40 -0
  294. data/ext/boost/mpl/vector/aux_/size.hpp +49 -0
  295. data/ext/boost/mpl/vector/aux_/tag.hpp +32 -0
  296. data/ext/boost/mpl/vector/aux_/vector0.hpp +52 -0
  297. data/ext/boost/mpl/vector/vector0.hpp +34 -0
  298. data/ext/boost/mpl/vector/vector10.hpp +45 -0
  299. data/ext/boost/mpl/vector/vector20.hpp +45 -0
  300. data/ext/boost/none.hpp +1 -1
  301. data/ext/boost/numeric/conversion/bounds.hpp +24 -0
  302. data/ext/boost/numeric/conversion/cast.hpp +61 -0
  303. data/ext/boost/numeric/conversion/conversion_traits.hpp +39 -0
  304. data/ext/boost/numeric/conversion/converter.hpp +68 -0
  305. data/ext/boost/numeric/conversion/converter_policies.hpp +186 -0
  306. data/ext/boost/numeric/conversion/detail/bounds.hpp +58 -0
  307. data/ext/boost/numeric/conversion/detail/conversion_traits.hpp +97 -0
  308. data/ext/boost/numeric/conversion/detail/converter.hpp +602 -0
  309. data/ext/boost/numeric/conversion/detail/int_float_mixture.hpp +72 -0
  310. data/ext/boost/numeric/conversion/detail/is_subranged.hpp +234 -0
  311. data/ext/boost/numeric/conversion/detail/meta.hpp +120 -0
  312. data/ext/boost/numeric/conversion/detail/numeric_cast_traits.hpp +138 -0
  313. data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_common.hpp +1741 -0
  314. data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_long_long.hpp +347 -0
  315. data/ext/boost/numeric/conversion/detail/sign_mixture.hpp +72 -0
  316. data/ext/boost/numeric/conversion/detail/udt_builtin_mixture.hpp +69 -0
  317. data/ext/boost/numeric/conversion/int_float_mixture_enum.hpp +29 -0
  318. data/ext/boost/numeric/conversion/numeric_cast_traits.hpp +31 -0
  319. data/ext/boost/numeric/conversion/sign_mixture_enum.hpp +29 -0
  320. data/ext/boost/numeric/conversion/udt_builtin_mixture_enum.hpp +26 -0
  321. data/ext/boost/operators.hpp +3 -1
  322. data/ext/boost/optional/optional.hpp +146 -79
  323. data/ext/boost/optional/optional_fwd.hpp +8 -1
  324. data/ext/boost/preprocessor/cat.hpp +2 -2
  325. data/ext/boost/preprocessor/config/config.hpp +39 -4
  326. data/ext/boost/preprocessor/facilities/intercept.hpp +277 -0
  327. data/ext/boost/preprocessor/facilities/overload.hpp +25 -0
  328. data/ext/boost/preprocessor/iteration/detail/iter/forward1.hpp +3 -3
  329. data/ext/boost/preprocessor/iteration/iterate.hpp +3 -3
  330. data/ext/boost/preprocessor/punctuation/paren.hpp +23 -0
  331. data/ext/boost/preprocessor/repetition/enum_shifted_params.hpp +44 -0
  332. data/ext/boost/preprocessor/seq/cat.hpp +5 -4
  333. data/ext/boost/preprocessor/seq/size.hpp +0 -1
  334. data/ext/boost/preprocessor/tuple/eat.hpp +83 -34
  335. data/ext/boost/preprocessor/tuple/elem.hpp +161 -355
  336. data/ext/boost/preprocessor/tuple/rem.hpp +110 -48
  337. data/ext/boost/preprocessor/tuple/to_list.hpp +90 -36
  338. data/ext/boost/preprocessor/variadic/elem.hpp +94 -0
  339. data/ext/boost/preprocessor/variadic/size.hpp +30 -0
  340. data/ext/boost/range/begin.hpp +17 -6
  341. data/ext/boost/range/concepts.hpp +37 -2
  342. data/ext/boost/range/detail/safe_bool.hpp +72 -0
  343. data/ext/boost/range/end.hpp +14 -9
  344. data/ext/boost/range/iterator_range_core.hpp +120 -12
  345. data/ext/boost/range/size.hpp +21 -5
  346. data/ext/boost/smart_ptr/detail/shared_count.hpp +88 -0
  347. data/ext/boost/smart_ptr/detail/sp_counted_base.hpp +3 -0
  348. data/ext/boost/smart_ptr/detail/sp_counted_base_aix.hpp +142 -0
  349. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +9 -0
  350. data/ext/boost/smart_ptr/detail/sp_counted_impl.hpp +10 -2
  351. data/ext/boost/smart_ptr/detail/sp_has_sync.hpp +5 -1
  352. data/ext/boost/smart_ptr/detail/spinlock.hpp +4 -1
  353. data/ext/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +20 -3
  354. data/ext/boost/smart_ptr/detail/spinlock_pool.hpp +4 -0
  355. data/ext/boost/smart_ptr/make_shared.hpp +591 -22
  356. data/ext/boost/smart_ptr/shared_array.hpp +29 -1
  357. data/ext/boost/smart_ptr/shared_ptr.hpp +29 -13
  358. data/ext/boost/smart_ptr/weak_ptr.hpp +24 -12
  359. data/ext/boost/src/pthread/once.cpp +9 -7
  360. data/ext/boost/src/pthread/thread.cpp +32 -28
  361. data/ext/boost/src/pthread/timeconv.inl +4 -5
  362. data/ext/boost/src/tss_null.cpp +5 -1
  363. data/ext/boost/static_assert.hpp +8 -2
  364. data/ext/boost/thread/detail/config.hpp +19 -4
  365. data/ext/boost/thread/detail/move.hpp +11 -5
  366. data/ext/boost/thread/detail/thread.hpp +59 -43
  367. data/ext/boost/thread/exceptions.hpp +9 -9
  368. data/ext/boost/thread/future.hpp +150 -82
  369. data/ext/boost/thread/locks.hpp +101 -60
  370. data/ext/boost/thread/pthread/condition_variable.hpp +79 -32
  371. data/ext/boost/thread/pthread/condition_variable_fwd.hpp +12 -3
  372. data/ext/boost/thread/pthread/mutex.hpp +17 -14
  373. data/ext/boost/thread/pthread/once.hpp +3 -4
  374. data/ext/boost/thread/pthread/pthread_mutex_scoped_lock.hpp +12 -2
  375. data/ext/boost/thread/pthread/recursive_mutex.hpp +19 -19
  376. data/ext/boost/thread/pthread/shared_mutex.hpp +13 -13
  377. data/ext/boost/thread/pthread/thread_data.hpp +40 -12
  378. data/ext/boost/thread/thread_time.hpp +5 -0
  379. data/ext/boost/throw_exception.hpp +1 -1
  380. data/ext/boost/token_functions.hpp +34 -10
  381. data/ext/boost/type_traits/add_rvalue_reference.hpp +66 -0
  382. data/ext/boost/type_traits/alignment_of.hpp +1 -1
  383. data/ext/boost/type_traits/detail/bool_trait_def.hpp +26 -3
  384. data/ext/boost/type_traits/detail/bool_trait_undef.hpp +3 -2
  385. data/ext/boost/type_traits/detail/cv_traits_impl.hpp +1 -1
  386. data/ext/boost/type_traits/detail/size_t_trait_def.hpp +6 -4
  387. data/ext/boost/type_traits/detail/type_trait_def.hpp +8 -2
  388. data/ext/boost/type_traits/function_traits.hpp +1 -1
  389. data/ext/boost/type_traits/has_nothrow_constructor.hpp +53 -0
  390. data/ext/boost/type_traits/has_nothrow_copy.hpp +19 -5
  391. data/ext/boost/type_traits/has_trivial_constructor.hpp +51 -0
  392. data/ext/boost/type_traits/has_trivial_copy.hpp +20 -5
  393. data/ext/boost/type_traits/has_trivial_destructor.hpp +12 -5
  394. data/ext/boost/type_traits/intrinsics.hpp +119 -71
  395. data/ext/boost/type_traits/is_const.hpp +5 -5
  396. data/ext/boost/type_traits/is_convertible.hpp +14 -13
  397. data/ext/boost/type_traits/is_enum.hpp +1 -1
  398. data/ext/boost/type_traits/is_floating_point.hpp +27 -0
  399. data/ext/boost/type_traits/is_function.hpp +3 -3
  400. data/ext/boost/type_traits/is_fundamental.hpp +1 -1
  401. data/ext/boost/type_traits/is_member_function_pointer.hpp +2 -2
  402. data/ext/boost/type_traits/is_member_pointer.hpp +2 -2
  403. data/ext/boost/type_traits/is_pod.hpp +11 -3
  404. data/ext/boost/type_traits/is_pointer.hpp +2 -2
  405. data/ext/boost/type_traits/is_signed.hpp +8 -3
  406. data/ext/boost/type_traits/is_union.hpp +8 -0
  407. data/ext/boost/type_traits/is_unsigned.hpp +9 -4
  408. data/ext/boost/type_traits/is_volatile.hpp +5 -5
  409. data/ext/boost/type_traits/remove_cv.hpp +4 -3
  410. data/ext/boost/type_traits/remove_pointer.hpp +51 -2
  411. data/ext/boost/type_traits/remove_reference.hpp +2 -2
  412. data/ext/boost/type_traits/type_with_alignment.hpp +8 -2
  413. data/ext/boost/utility/declval.hpp +44 -0
  414. data/ext/boost/utility/detail/in_place_factory_prefix.hpp +36 -0
  415. data/ext/boost/utility/detail/in_place_factory_suffix.hpp +23 -0
  416. data/ext/boost/utility/detail/result_of_iterate.hpp +142 -0
  417. data/ext/boost/utility/in_place_factory.hpp +88 -0
  418. data/ext/boost/utility/result_of.hpp +103 -0
  419. data/ext/boost/utility/swap.hpp +55 -0
  420. data/ext/common/AnsiColorConstants.h +36 -0
  421. data/ext/common/ApplicationPool2/Common.h +87 -0
  422. data/ext/common/ApplicationPool2/ComponentInfo.h +53 -0
  423. data/ext/common/ApplicationPool2/Group.h +648 -0
  424. data/ext/common/ApplicationPool2/Implementation.cpp +580 -0
  425. data/ext/common/ApplicationPool2/Options.h +576 -0
  426. data/ext/common/ApplicationPool2/PipeWatcher.h +61 -0
  427. data/ext/common/ApplicationPool2/Pool.h +1181 -0
  428. data/ext/common/ApplicationPool2/Process.h +425 -0
  429. data/ext/common/ApplicationPool2/README.md +96 -0
  430. data/ext/common/ApplicationPool2/Session.h +158 -0
  431. data/ext/common/ApplicationPool2/Socket.h +246 -0
  432. data/ext/common/ApplicationPool2/Spawner.h +2212 -0
  433. data/ext/common/ApplicationPool2/SuperGroup.h +749 -0
  434. data/ext/common/BackgroundEventLoop.cpp +129 -0
  435. data/ext/common/BackgroundEventLoop.h +61 -0
  436. data/ext/common/Constants.h +3 -1
  437. data/ext/common/EventedBufferedInput.h +331 -0
  438. data/ext/common/EventedMessageServer.h +17 -34
  439. data/ext/common/EventedServer.h +2 -2
  440. data/ext/common/Exceptions.h +71 -19
  441. data/ext/common/FileDescriptor.h +8 -6
  442. data/ext/common/HttpConstants.h +167 -0
  443. data/ext/common/IniFile.h +24 -0
  444. data/ext/common/Logging.h +62 -849
  445. data/ext/common/MessageReadersWriters.h +19 -0
  446. data/ext/common/MessageServer.h +11 -14
  447. data/ext/common/MultiLibeio.cpp +198 -0
  448. data/ext/common/MultiLibeio.h +67 -0
  449. data/ext/common/ResourceLocator.h +24 -41
  450. data/ext/common/SafeLibev.h +186 -14
  451. data/ext/common/StaticString.h +23 -3
  452. data/ext/common/UnionStation.h +972 -0
  453. data/ext/common/Utils.cpp +168 -24
  454. data/ext/common/Utils.h +25 -3
  455. data/ext/common/Utils/CachedFileStat.hpp +4 -3
  456. data/ext/common/Utils/FileChangeChecker.h +2 -2
  457. data/ext/common/Utils/HashMap.h +50 -0
  458. data/ext/common/Utils/IOUtils.cpp +229 -68
  459. data/ext/common/Utils/IOUtils.h +134 -3
  460. data/ext/common/Utils/Lock.h +28 -0
  461. data/ext/common/Utils/MemoryBarrier.h +52 -0
  462. data/ext/common/Utils/PriorityQueue.h +54 -0
  463. data/ext/common/Utils/ProcessMetricsCollector.h +9 -11
  464. data/ext/common/Utils/ScopeGuard.h +50 -1
  465. data/ext/common/Utils/SmallVector.h +653 -0
  466. data/ext/common/Utils/StrIntUtils.cpp +26 -2
  467. data/ext/common/Utils/StrIntUtils.h +18 -2
  468. data/ext/common/Utils/StringMap.h +125 -8
  469. data/ext/common/Utils/Template.h +212 -0
  470. data/ext/common/Utils/fib.c +699 -0
  471. data/ext/common/Utils/fib.h +101 -0
  472. data/ext/common/Utils/fibpriv.h +67 -0
  473. data/ext/common/Utils/json-forwards.h +249 -0
  474. data/ext/common/Utils/json.h +1855 -0
  475. data/ext/common/Utils/jsoncpp.cpp +4230 -0
  476. data/ext/common/agents/Base.cpp +1126 -0
  477. data/ext/common/{AgentBase.h → agents/Base.h} +5 -1
  478. data/ext/common/agents/EnvPrinter.c +16 -0
  479. data/ext/common/agents/HelperAgent/AgentOptions.h +81 -0
  480. data/ext/common/{HelperAgent → agents/HelperAgent}/BacktracesServer.h +3 -2
  481. data/ext/common/agents/HelperAgent/FileBackedPipe.h +732 -0
  482. data/ext/common/agents/HelperAgent/Main.cpp +497 -0
  483. data/ext/common/agents/HelperAgent/RequestHandler.cpp +283 -0
  484. data/ext/common/agents/HelperAgent/RequestHandler.h +2139 -0
  485. data/ext/common/agents/HelperAgent/ScgiRequestParser.h +451 -0
  486. data/ext/common/{LoggingAgent → agents/LoggingAgent}/DataStoreId.h +1 -1
  487. data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.cpp +1 -1
  488. data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.h +0 -0
  489. data/ext/common/{LoggingAgent → agents/LoggingAgent}/LoggingServer.h +18 -16
  490. data/ext/common/{LoggingAgent → agents/LoggingAgent}/Main.cpp +15 -13
  491. data/ext/common/{LoggingAgent → agents/LoggingAgent}/RemoteSender.h +6 -6
  492. data/ext/common/agents/SpawnPreparer.cpp +127 -0
  493. data/ext/common/{Watchdog.cpp → agents/Watchdog/Main.cpp} +63 -25
  494. data/ext/libeio/Changes +72 -0
  495. data/ext/{google/COPYING → libeio/LICENSE} +17 -9
  496. data/ext/libeio/Makefile.am +15 -0
  497. data/ext/libeio/Makefile.in +694 -0
  498. data/ext/libeio/aclocal.m4 +9418 -0
  499. data/ext/libeio/autogen.sh +3 -0
  500. data/ext/libeio/config.guess +1501 -0
  501. data/ext/libeio/config.h.in +136 -0
  502. data/ext/libeio/config.sub +1705 -0
  503. data/ext/libeio/configure +14822 -0
  504. data/ext/libeio/configure.ac +22 -0
  505. data/ext/libeio/demo.c +194 -0
  506. data/ext/libeio/ecb.h +457 -0
  507. data/ext/libeio/eio.c +2816 -0
  508. data/ext/libeio/eio.h +411 -0
  509. data/ext/libeio/install-sh +520 -0
  510. data/ext/libeio/libeio.m4 +211 -0
  511. data/ext/libeio/ltmain.sh +9636 -0
  512. data/ext/libeio/missing +376 -0
  513. data/ext/libeio/xthread.h +166 -0
  514. data/ext/libev/Changes +125 -7
  515. data/ext/libev/Makefile.am +5 -3
  516. data/ext/libev/Makefile.in +209 -120
  517. data/ext/libev/aclocal.m4 +6027 -4619
  518. data/ext/libev/autogen.sh +1 -4
  519. data/ext/libev/config.h.in +11 -7
  520. data/ext/libev/configure +7312 -14993
  521. data/ext/libev/configure.ac +12 -5
  522. data/ext/libev/depcomp +630 -0
  523. data/ext/libev/ev++.h +48 -32
  524. data/ext/libev/ev.c +1173 -391
  525. data/ext/libev/ev.h +315 -181
  526. data/ext/libev/ev_epoll.c +66 -15
  527. data/ext/libev/ev_kqueue.c +20 -18
  528. data/ext/libev/ev_poll.c +27 -23
  529. data/ext/libev/ev_port.c +39 -19
  530. data/ext/libev/ev_select.c +23 -17
  531. data/ext/libev/ev_vars.h +25 -8
  532. data/ext/libev/ev_win32.c +6 -6
  533. data/ext/libev/ev_wrap.h +22 -2
  534. data/ext/libev/event.c +18 -17
  535. data/ext/libev/event.h +16 -4
  536. data/ext/libev/libev.m4 +10 -6
  537. data/ext/libev/ltmain.sh +7353 -5811
  538. data/ext/nginx/Configuration.c +74 -42
  539. data/ext/nginx/Configuration.h +3 -5
  540. data/ext/nginx/ContentHandler.c +26 -83
  541. data/ext/nginx/ContentHandler.h +1 -1
  542. data/ext/nginx/config +13 -9
  543. data/ext/nginx/ngx_http_passenger_module.c +3 -7
  544. data/ext/oxt/detail/backtrace_enabled.hpp +5 -102
  545. data/ext/oxt/detail/context.hpp +90 -0
  546. data/ext/oxt/detail/spin_lock_darwin.hpp +4 -0
  547. data/ext/oxt/detail/spin_lock_gcc_x86.hpp +4 -0
  548. data/ext/oxt/detail/spin_lock_pthreads.hpp +14 -0
  549. data/ext/oxt/detail/tracable_exception_enabled.hpp +2 -2
  550. data/ext/oxt/dynamic_thread_group.hpp +27 -1
  551. data/ext/oxt/implementation.cpp +415 -0
  552. data/ext/oxt/{thread.cpp → initialize.hpp} +13 -6
  553. data/ext/oxt/macros.hpp +32 -1
  554. data/ext/oxt/spin_lock.hpp +6 -11
  555. data/ext/oxt/system_calls.cpp +204 -16
  556. data/ext/oxt/system_calls.hpp +85 -45
  557. data/ext/oxt/thread.hpp +13 -117
  558. data/ext/ruby/passenger_native_support.c +82 -237
  559. data/helper-scripts/backtrace-sanitizer.rb +114 -0
  560. data/helper-scripts/classic-rails-loader.rb +135 -0
  561. data/helper-scripts/classic-rails-preloader.rb +161 -0
  562. data/helper-scripts/node-loader.js +314 -0
  563. data/helper-scripts/rack-loader.rb +104 -0
  564. data/helper-scripts/rack-preloader.rb +132 -0
  565. data/helper-scripts/wsgi-loader.py +231 -0
  566. data/helper-scripts/wsgi-preloader.py +1 -0
  567. data/lib/phusion_passenger.rb +159 -61
  568. data/lib/phusion_passenger/abstract_installer.rb +182 -87
  569. data/lib/phusion_passenger/admin_tools/server_instance.rb +25 -19
  570. data/lib/phusion_passenger/analytics_logger.rb +5 -4
  571. data/lib/phusion_passenger/classic_rails/{request_handler.rb → thread_handler_extension.rb} +4 -40
  572. data/lib/phusion_passenger/classic_rails_extensions/init.rb +5 -3
  573. data/lib/phusion_passenger/common_library.rb +441 -0
  574. data/lib/phusion_passenger/console_text_template.rb +4 -16
  575. data/lib/phusion_passenger/constants.rb +1 -8
  576. data/lib/phusion_passenger/debug_logging.rb +5 -2
  577. data/lib/phusion_passenger/dependencies.rb +51 -13
  578. data/lib/phusion_passenger/loader_shared_helpers.rb +318 -0
  579. data/lib/phusion_passenger/message_channel.rb +3 -47
  580. data/lib/phusion_passenger/message_client.rb +2 -2
  581. data/lib/phusion_passenger/native_support.rb +36 -15
  582. data/lib/phusion_passenger/packaging.rb +8 -11
  583. data/lib/phusion_passenger/platform_info.rb +25 -17
  584. data/lib/phusion_passenger/platform_info/apache.rb +10 -7
  585. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +10 -30
  586. data/lib/phusion_passenger/platform_info/compiler.rb +93 -34
  587. data/lib/phusion_passenger/platform_info/ruby.rb +37 -97
  588. data/lib/phusion_passenger/preloader_shared_helpers.rb +121 -0
  589. data/lib/phusion_passenger/public_api.rb +1 -4
  590. data/lib/phusion_passenger/rack/{request_handler.rb → thread_handler_extension.rb} +14 -63
  591. data/lib/phusion_passenger/rails3_extensions/init.rb +9 -8
  592. data/lib/phusion_passenger/request_handler.rb +500 -0
  593. data/lib/phusion_passenger/request_handler/thread_handler.rb +360 -0
  594. data/lib/phusion_passenger/ruby_core_enhancements.rb +142 -0
  595. data/lib/phusion_passenger/standalone/command.rb +36 -15
  596. data/lib/phusion_passenger/standalone/package_runtime_command.rb +16 -8
  597. data/lib/phusion_passenger/standalone/runtime_installer.rb +169 -72
  598. data/lib/phusion_passenger/standalone/start_command.rb +44 -39
  599. data/lib/phusion_passenger/standalone/utils.rb +5 -5
  600. data/lib/phusion_passenger/utils.rb +35 -914
  601. data/lib/phusion_passenger/utils/ansi_colors.rb +59 -0
  602. data/lib/phusion_passenger/utils/file_system_watcher.rb +1 -1
  603. data/lib/phusion_passenger/utils/robust_interruption.rb +134 -0
  604. data/lib/phusion_passenger/utils/tee_input.rb +174 -0
  605. data/lib/phusion_passenger/utils/tmpio.rb +33 -0
  606. data/lib/phusion_passenger/utils/unseekable_socket.rb +6 -0
  607. data/resources/mime.types +5 -1
  608. data/{lib/phusion_passenger/templates → resources}/standalone_default_root/index.html +0 -0
  609. data/{lib/phusion_passenger → resources}/templates/apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb +0 -0
  610. data/{lib/phusion_passenger → resources}/templates/apache2/config_snippets.txt.erb +0 -0
  611. data/{lib/phusion_passenger → resources}/templates/apache2/deployment_example.txt.erb +0 -0
  612. data/{lib/phusion_passenger → resources}/templates/apache2/no_write_permission_to_passenger_root.txt.erb +0 -0
  613. data/{lib/phusion_passenger → resources}/templates/apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
  614. data/{lib/phusion_passenger → resources}/templates/apache2/run_installer_as_root.txt.erb +0 -0
  615. data/{lib/phusion_passenger → resources}/templates/apache2/welcome.txt.erb +0 -0
  616. data/{lib/phusion_passenger → resources}/templates/error_layout.css +6 -0
  617. data/resources/templates/error_layout.html.template +89 -0
  618. data/resources/templates/general_error.html.template +1 -0
  619. data/resources/templates/general_error_with_html.html.template +1 -0
  620. data/{lib/phusion_passenger → resources}/templates/nginx/ask_for_extra_configure_flags.txt.erb +0 -0
  621. data/{lib/phusion_passenger → resources}/templates/nginx/cannot_write_to_dir.txt.erb +0 -0
  622. data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets.txt.erb +0 -0
  623. data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets_inserted.txt.erb +0 -0
  624. data/{lib/phusion_passenger → resources}/templates/nginx/confirm_extra_configure_flags.txt.erb +0 -0
  625. data/{lib/phusion_passenger → resources}/templates/nginx/deployment_example.txt.erb +0 -0
  626. data/resources/templates/nginx/not_available_when_natively_packaged.txt.erb +8 -0
  627. data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_downloaded.txt.erb +0 -0
  628. data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_extracted.txt.erb +0 -0
  629. data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
  630. data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
  631. data/{lib/phusion_passenger → resources}/templates/nginx/query_download_and_install.txt.erb +0 -0
  632. data/{lib/phusion_passenger → resources}/templates/nginx/run_installer_as_root.txt.erb +0 -0
  633. data/{lib/phusion_passenger → resources}/templates/nginx/welcome.txt.erb +0 -0
  634. data/{lib/phusion_passenger → resources}/templates/standalone/cannot_write_to_dir.txt.erb +0 -0
  635. data/{lib/phusion_passenger → resources}/templates/standalone/config.erb +26 -5
  636. data/{lib/phusion_passenger → resources}/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
  637. data/{lib/phusion_passenger → resources}/templates/standalone/run_installer_as_root.txt.erb +0 -0
  638. data/{lib/phusion_passenger → resources}/templates/standalone/welcome.txt.erb +0 -0
  639. data/resources/templates/undisclosed_error.html.template +25 -0
  640. data/test/config.json.example +42 -0
  641. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +86 -0
  642. data/test/cxx/ApplicationPool2/OptionsTest.cpp +44 -0
  643. data/test/cxx/ApplicationPool2/PoolTest.cpp +1234 -0
  644. data/test/cxx/ApplicationPool2/ProcessTest.cpp +131 -0
  645. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +229 -0
  646. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +744 -0
  647. data/test/cxx/BufferedIOTest.cpp +7 -7
  648. data/test/cxx/CxxTestMain.cpp +65 -2
  649. data/test/cxx/FileBackedPipeTest.cpp +626 -0
  650. data/test/cxx/FileChangeCheckerTest.cpp +20 -18
  651. data/test/cxx/FilterSupportTest.cpp +5 -5
  652. data/test/cxx/IOUtilsTest.cpp +11 -4
  653. data/test/cxx/MessageReadersWritersTest.cpp +1 -1
  654. data/test/cxx/MessageServerTest.cpp +31 -30
  655. data/test/cxx/RequestHandlerTest.cpp +777 -0
  656. data/test/cxx/ScgiRequestParserTest.cpp +36 -16
  657. data/test/cxx/ServerInstanceDirTest.cpp +1 -1
  658. data/test/cxx/StringMapTest.cpp +61 -0
  659. data/test/cxx/TemplateTest.cpp +118 -0
  660. data/test/cxx/TestSupport.cpp +25 -68
  661. data/test/cxx/TestSupport.h +81 -41
  662. data/test/cxx/{LoggingTest.cpp → UnionStationTest.cpp} +79 -74
  663. data/test/cxx/UtilsTest.cpp +59 -5
  664. data/test/integration_tests/apache2_tests.rb +2 -2
  665. data/test/integration_tests/nginx_tests.rb +1 -1
  666. data/test/integration_tests/spec_helper.rb +7 -5
  667. data/test/oxt/oxt_test_main.cpp +2 -0
  668. data/test/oxt/syscall_interruption_test.cpp +1 -0
  669. data/test/ruby/classic_rails/loader_spec.rb +48 -0
  670. data/test/ruby/classic_rails/preloader_spec.rb +54 -0
  671. data/test/ruby/rack/loader_spec.rb +62 -0
  672. data/test/ruby/rack/preloader_spec.rb +74 -0
  673. data/test/ruby/{abstract_request_handler_spec.rb → request_handler_spec.rb} +31 -68
  674. data/test/ruby/shared/loader_spec.rb +241 -0
  675. data/test/ruby/shared/rails/analytics_logging_extensions_spec.rb +141 -182
  676. data/test/ruby/shared/ruby_loader_spec.rb +55 -0
  677. data/test/ruby/spec_helper.rb +8 -53
  678. data/test/ruby/utils/file_system_watcher_spec.rb +9 -1
  679. data/test/ruby/utils_spec.rb +10 -683
  680. data/test/stub/rack/config.ru +28 -3
  681. data/test/stub/rack/start.rb +47 -0
  682. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/Rakefile +0 -0
  683. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/application_controller.rb +0 -2
  684. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_1.rb +0 -0
  685. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_2.rb +0 -0
  686. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/foo_controller.rb +0 -0
  687. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/helpers/application_helper.rb +0 -0
  688. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/boot.rb +0 -0
  689. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/database.yml +3 -3
  690. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environment.rb +5 -2
  691. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/development.rb +0 -0
  692. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/production.rb +0 -0
  693. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/staging.rb +0 -0
  694. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/inflections.rb +0 -0
  695. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/mime_types.rb +0 -0
  696. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/routes.rb +1 -0
  697. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/about +0 -0
  698. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/console +0 -0
  699. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/dbconsole +0 -0
  700. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/destroy +0 -0
  701. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/generate +0 -0
  702. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/benchmarker +0 -0
  703. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/profiler +0 -0
  704. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/request +0 -0
  705. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/plugin +0 -0
  706. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/inspector +0 -0
  707. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/reaper +0 -0
  708. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/spawner +0 -0
  709. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/runner +0 -0
  710. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/server +0 -0
  711. data/test/stub/{rails_apps/3.0/empty → rails3.0}/Gemfile +0 -0
  712. data/test/stub/rails3.0/Gemfile.lock +80 -0
  713. data/test/stub/{rails_apps/3.0/empty → rails3.0}/Rakefile +0 -0
  714. data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/controllers/application_controller.rb +0 -0
  715. data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/helpers/application_helper.rb +0 -0
  716. data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/views/layouts/application.html.erb +0 -0
  717. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config.ru +0 -0
  718. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/application.rb +0 -0
  719. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/boot.rb +0 -0
  720. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/database.yml +0 -0
  721. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environment.rb +0 -0
  722. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/development.rb +0 -0
  723. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/production.rb +0 -0
  724. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/test.rb +0 -0
  725. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/backtrace_silencers.rb +0 -0
  726. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/inflections.rb +0 -0
  727. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/mime_types.rb +0 -0
  728. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/passenger.rb +0 -0
  729. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/secret_token.rb +0 -0
  730. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/session_store.rb +0 -0
  731. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/locales/en.yml +0 -0
  732. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/routes.rb +0 -0
  733. data/test/stub/{rails_apps/3.0/empty → rails3.0}/db/seeds.rb +0 -0
  734. data/test/stub/{rails_apps/3.0/empty → rails3.0}/doc/README_FOR_APP +0 -0
  735. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/404.html +0 -0
  736. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/422.html +0 -0
  737. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/500.html +0 -0
  738. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/favicon.ico +0 -0
  739. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/index.html +0 -0
  740. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/robots.txt +0 -0
  741. data/test/stub/{rails_apps/3.0/empty → rails3.0}/script/rails +0 -0
  742. data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/performance/browsing_test.rb +0 -0
  743. data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/test_helper.rb +0 -0
  744. data/test/stub/start_error.pl +24 -0
  745. data/test/stub/wsgi/passenger_wsgi.py +71 -3
  746. data/test/support/apache2_controller.rb +2 -2
  747. data/test/support/placebo-preloader.rb +88 -0
  748. data/test/support/test_helper.rb +1 -14
  749. data/test/tut/tut.h +11 -4
  750. metadata +590 -326
  751. data.tar.gz.asc +0 -12
  752. data/PACKAGING.TXT +0 -25
  753. data/build/config.rb +0 -46
  754. data/ext/apache2/HelperAgent.cpp +0 -364
  755. data/ext/boost/call_traits.hpp +0 -24
  756. data/ext/boost/detail/call_traits.hpp +0 -164
  757. data/ext/common/AbstractSpawnManager.h +0 -110
  758. data/ext/common/AgentBase.cpp +0 -432
  759. data/ext/common/ApplicationPool/Client.h +0 -788
  760. data/ext/common/ApplicationPool/Interface.h +0 -295
  761. data/ext/common/ApplicationPool/Pool.h +0 -1327
  762. data/ext/common/ApplicationPool/Server.h +0 -479
  763. data/ext/common/MessageChannel.h +0 -494
  764. data/ext/common/PoolOptions.h +0 -518
  765. data/ext/common/Process.h +0 -253
  766. data/ext/common/Session.h +0 -436
  767. data/ext/common/SpawnManager.h +0 -611
  768. data/ext/google/ChangeLog +0 -167
  769. data/ext/google/dense_hash_map +0 -310
  770. data/ext/google/dense_hash_set +0 -287
  771. data/ext/google/sparse_hash_map +0 -294
  772. data/ext/google/sparse_hash_set +0 -275
  773. data/ext/google/sparsehash/densehashtable.h +0 -1062
  774. data/ext/google/sparsehash/sparseconfig.h +0 -55
  775. data/ext/google/sparsehash/sparsehashtable.h +0 -1015
  776. data/ext/google/sparsetable +0 -1468
  777. data/ext/google/type_traits.h +0 -250
  778. data/ext/nginx/HelperAgent.cpp +0 -1355
  779. data/ext/nginx/ScgiRequestParser.h +0 -375
  780. data/ext/oxt/backtrace.cpp +0 -185
  781. data/ext/oxt/tracable_exception.cpp +0 -89
  782. data/helper-scripts/passenger-spawn-server +0 -106
  783. data/lib/phusion_passenger/abstract_request_handler.rb +0 -766
  784. data/lib/phusion_passenger/abstract_server.rb +0 -372
  785. data/lib/phusion_passenger/abstract_server_collection.rb +0 -335
  786. data/lib/phusion_passenger/app_process.rb +0 -174
  787. data/lib/phusion_passenger/classic_rails/application_spawner.rb +0 -344
  788. data/lib/phusion_passenger/classic_rails/framework_spawner.rb +0 -311
  789. data/lib/phusion_passenger/exceptions.rb +0 -103
  790. data/lib/phusion_passenger/html_template.rb +0 -107
  791. data/lib/phusion_passenger/rack/application_spawner.rb +0 -231
  792. data/lib/phusion_passenger/spawn_manager.rb +0 -359
  793. data/lib/phusion_passenger/templates/app_exited_during_initialization.html.erb +0 -38
  794. data/lib/phusion_passenger/templates/app_init_error.html.erb +0 -64
  795. data/lib/phusion_passenger/templates/database_error.html.erb +0 -66
  796. data/lib/phusion_passenger/templates/error_layout.html.erb +0 -39
  797. data/lib/phusion_passenger/templates/framework_init_error.html.erb +0 -39
  798. data/lib/phusion_passenger/templates/general_error.html.erb +0 -22
  799. data/lib/phusion_passenger/templates/load_error.html.erb +0 -46
  800. data/lib/phusion_passenger/templates/version_not_found.html.erb +0 -34
  801. data/lib/phusion_passenger/utils/rewindable_input.rb +0 -125
  802. data/lib/phusion_passenger/wsgi/application_spawner.rb +0 -108
  803. data/test/config.yml.example +0 -41
  804. data/test/cxx/ApplicationPool_PoolTest.cpp +0 -33
  805. data/test/cxx/ApplicationPool_PoolTestCases.cpp +0 -1029
  806. data/test/cxx/ApplicationPool_ServerTest.cpp +0 -308
  807. data/test/cxx/ApplicationPool_Server_PoolTest.cpp +0 -80
  808. data/test/cxx/MessageChannelTest.cpp +0 -557
  809. data/test/cxx/PoolOptionsTest.cpp +0 -116
  810. data/test/cxx/SpawnManagerTest.cpp +0 -161
  811. data/test/ruby/abstract_server_collection_spec.rb +0 -247
  812. data/test/ruby/abstract_server_spec.rb +0 -61
  813. data/test/ruby/app_process_spec.rb +0 -43
  814. data/test/ruby/classic_rails/application_spawner_spec.rb +0 -89
  815. data/test/ruby/classic_rails/framework_spawner_spec.rb +0 -92
  816. data/test/ruby/rack/application_spawner_spec.rb +0 -116
  817. data/test/ruby/shared/abstract_server_spec.rb +0 -23
  818. data/test/ruby/shared/spawners/classic_rails/framework_spawner_spec.rb +0 -38
  819. data/test/ruby/shared/spawners/classic_rails/lack_of_rails_gem_version_spec.rb +0 -19
  820. data/test/ruby/shared/spawners/classic_rails/spawner_spec.rb +0 -15
  821. data/test/ruby/shared/spawners/non_preloading_spawner_spec.rb +0 -27
  822. data/test/ruby/shared/spawners/preloading_spawner_spec.rb +0 -29
  823. data/test/ruby/shared/spawners/reload_all_spec.rb +0 -36
  824. data/test/ruby/shared/spawners/reload_single_spec.rb +0 -52
  825. data/test/ruby/shared/spawners/spawn_server_spec.rb +0 -28
  826. data/test/ruby/shared/spawners/spawner_spec.rb +0 -273
  827. data/test/ruby/shared/utils/pseudo_io_spec.rb +0 -60
  828. data/test/ruby/spawn_manager_spec.rb +0 -134
  829. data/test/ruby/wsgi/application_spawner_spec.rb +0 -50
  830. data/test/stub/message_channel.rb +0 -11
  831. data/test/stub/message_channel_2.rb +0 -12
  832. data/test/stub/message_channel_3.rb +0 -19
  833. data/test/stub/rails_apps/3.0/empty/Gemfile.lock +0 -73
  834. data/test/stub/spawn_server.rb +0 -22
  835. metadata.gz.asc +0 -12
@@ -0,0 +1,4230 @@
1
+ /// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).
2
+ /// It is intented to be used with #include <json/json.h>
3
+
4
+ // //////////////////////////////////////////////////////////////////////
5
+ // Beginning of content of file: LICENSE
6
+ // //////////////////////////////////////////////////////////////////////
7
+
8
+ /*
9
+ The JsonCpp library's source code, including accompanying documentation,
10
+ tests and demonstration applications, are licensed under the following
11
+ conditions...
12
+
13
+ The author (Baptiste Lepilleur) explicitly disclaims copyright in all
14
+ jurisdictions which recognize such a disclaimer. In such jurisdictions,
15
+ this software is released into the Public Domain.
16
+
17
+ In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
18
+ 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
19
+ released under the terms of the MIT License (see below).
20
+
21
+ In jurisdictions which recognize Public Domain property, the user of this
22
+ software may choose to accept it either as 1) Public Domain, 2) under the
23
+ conditions of the MIT License (see below), or 3) under the terms of dual
24
+ Public Domain/MIT License conditions described here, as they choose.
25
+
26
+ The MIT License is about as close to Public Domain as a license can get, and is
27
+ described in clear, concise terms at:
28
+
29
+ http://en.wikipedia.org/wiki/MIT_License
30
+
31
+ The full text of the MIT License follows:
32
+
33
+ ========================================================================
34
+ Copyright (c) 2007-2010 Baptiste Lepilleur
35
+
36
+ Permission is hereby granted, free of charge, to any person
37
+ obtaining a copy of this software and associated documentation
38
+ files (the "Software"), to deal in the Software without
39
+ restriction, including without limitation the rights to use, copy,
40
+ modify, merge, publish, distribute, sublicense, and/or sell copies
41
+ of the Software, and to permit persons to whom the Software is
42
+ furnished to do so, subject to the following conditions:
43
+
44
+ The above copyright notice and this permission notice shall be
45
+ included in all copies or substantial portions of the Software.
46
+
47
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
48
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
50
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
51
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
52
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
53
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
54
+ SOFTWARE.
55
+ ========================================================================
56
+ (END LICENSE TEXT)
57
+
58
+ The MIT license is compatible with both the GPL and commercial
59
+ software, affording one all of the rights of Public Domain with the
60
+ minor nuisance of being required to keep the above copyright notice
61
+ and license text in the source code. Note also that by accepting the
62
+ Public Domain "license" you can re-license your copy using whatever
63
+ license you like.
64
+
65
+ */
66
+
67
+ // //////////////////////////////////////////////////////////////////////
68
+ // End of content of file: LICENSE
69
+ // //////////////////////////////////////////////////////////////////////
70
+
71
+
72
+
73
+
74
+
75
+
76
+ #include <Utils/json.h>
77
+
78
+
79
+ // //////////////////////////////////////////////////////////////////////
80
+ // Beginning of content of file: src/lib_json/json_tool.h
81
+ // //////////////////////////////////////////////////////////////////////
82
+
83
+ // Copyright 2007-2010 Baptiste Lepilleur
84
+ // Distributed under MIT license, or public domain if desired and
85
+ // recognized in your jurisdiction.
86
+ // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
87
+
88
+ #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
89
+ # define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
90
+
91
+ /* This header provides common string manipulation support, such as UTF-8,
92
+ * portable conversion from/to string...
93
+ *
94
+ * It is an internal header that must not be exposed.
95
+ */
96
+
97
+ namespace Json {
98
+
99
+ /// Converts a unicode code-point to UTF-8.
100
+ static inline std::string
101
+ codePointToUTF8(unsigned int cp)
102
+ {
103
+ std::string result;
104
+
105
+ // based on description from http://en.wikipedia.org/wiki/UTF-8
106
+
107
+ if (cp <= 0x7f)
108
+ {
109
+ result.resize(1);
110
+ result[0] = static_cast<char>(cp);
111
+ }
112
+ else if (cp <= 0x7FF)
113
+ {
114
+ result.resize(2);
115
+ result[1] = static_cast<char>(0x80 | (0x3f & cp));
116
+ result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
117
+ }
118
+ else if (cp <= 0xFFFF)
119
+ {
120
+ result.resize(3);
121
+ result[2] = static_cast<char>(0x80 | (0x3f & cp));
122
+ result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
123
+ result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
124
+ }
125
+ else if (cp <= 0x10FFFF)
126
+ {
127
+ result.resize(4);
128
+ result[3] = static_cast<char>(0x80 | (0x3f & cp));
129
+ result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
130
+ result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
131
+ result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
132
+ }
133
+
134
+ return result;
135
+ }
136
+
137
+
138
+ /// Returns true if ch is a control character (in range [0,32[).
139
+ static inline bool
140
+ isControlCharacter(char ch)
141
+ {
142
+ return ch > 0 && ch <= 0x1F;
143
+ }
144
+
145
+
146
+ enum {
147
+ /// Constant that specify the size of the buffer that must be passed to uintToString.
148
+ uintToStringBufferSize = 3*sizeof(LargestUInt)+1
149
+ };
150
+
151
+ // Defines a char buffer for use with uintToString().
152
+ typedef char UIntToStringBuffer[uintToStringBufferSize];
153
+
154
+
155
+ /** Converts an unsigned integer to string.
156
+ * @param value Unsigned interger to convert to string
157
+ * @param current Input/Output string buffer.
158
+ * Must have at least uintToStringBufferSize chars free.
159
+ */
160
+ static inline void
161
+ uintToString( LargestUInt value,
162
+ char *&current )
163
+ {
164
+ *--current = 0;
165
+ do
166
+ {
167
+ *--current = char(value % 10) + '0';
168
+ value /= 10;
169
+ }
170
+ while ( value != 0 );
171
+ }
172
+
173
+ } // namespace Json {
174
+
175
+ #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
176
+
177
+ // //////////////////////////////////////////////////////////////////////
178
+ // End of content of file: src/lib_json/json_tool.h
179
+ // //////////////////////////////////////////////////////////////////////
180
+
181
+
182
+
183
+
184
+
185
+
186
+ // //////////////////////////////////////////////////////////////////////
187
+ // Beginning of content of file: src/lib_json/json_reader.cpp
188
+ // //////////////////////////////////////////////////////////////////////
189
+
190
+ // Copyright 2007-2010 Baptiste Lepilleur
191
+ // Distributed under MIT license, or public domain if desired and
192
+ // recognized in your jurisdiction.
193
+ // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
194
+
195
+ #if !defined(JSON_IS_AMALGAMATION)
196
+ # include <json/reader.h>
197
+ # include <json/value.h>
198
+ # include "json_tool.h"
199
+ #endif // if !defined(JSON_IS_AMALGAMATION)
200
+ #include <utility>
201
+ #include <cstdio>
202
+ #include <cassert>
203
+ #include <cstring>
204
+ #include <iostream>
205
+ #include <stdexcept>
206
+
207
+ #if _MSC_VER >= 1400 // VC++ 8.0
208
+ #pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
209
+ #endif
210
+
211
+ namespace Json {
212
+
213
+ // Implementation of class Features
214
+ // ////////////////////////////////
215
+
216
+ Features::Features()
217
+ : allowComments_( true )
218
+ , strictRoot_( false )
219
+ {
220
+ }
221
+
222
+
223
+ Features
224
+ Features::all()
225
+ {
226
+ return Features();
227
+ }
228
+
229
+
230
+ Features
231
+ Features::strictMode()
232
+ {
233
+ Features features;
234
+ features.allowComments_ = false;
235
+ features.strictRoot_ = true;
236
+ return features;
237
+ }
238
+
239
+ // Implementation of class Reader
240
+ // ////////////////////////////////
241
+
242
+
243
+ static inline bool
244
+ in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
245
+ {
246
+ return c == c1 || c == c2 || c == c3 || c == c4;
247
+ }
248
+
249
+ static inline bool
250
+ in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
251
+ {
252
+ return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
253
+ }
254
+
255
+
256
+ static bool
257
+ containsNewLine( Reader::Location begin,
258
+ Reader::Location end )
259
+ {
260
+ for ( ;begin < end; ++begin )
261
+ if ( *begin == '\n' || *begin == '\r' )
262
+ return true;
263
+ return false;
264
+ }
265
+
266
+
267
+ // Class Reader
268
+ // //////////////////////////////////////////////////////////////////
269
+
270
+ Reader::Reader()
271
+ : features_( Features::all() )
272
+ {
273
+ }
274
+
275
+
276
+ Reader::Reader( const Features &features )
277
+ : features_( features )
278
+ {
279
+ }
280
+
281
+
282
+ bool
283
+ Reader::parse( const std::string &document,
284
+ Value &root,
285
+ bool collectComments )
286
+ {
287
+ document_ = document;
288
+ const char *begin = document_.c_str();
289
+ const char *end = begin + document_.length();
290
+ return parse( begin, end, root, collectComments );
291
+ }
292
+
293
+
294
+ bool
295
+ Reader::parse( std::istream& sin,
296
+ Value &root,
297
+ bool collectComments )
298
+ {
299
+ //std::istream_iterator<char> begin(sin);
300
+ //std::istream_iterator<char> end;
301
+ // Those would allow streamed input from a file, if parse() were a
302
+ // template function.
303
+
304
+ // Since std::string is reference-counted, this at least does not
305
+ // create an extra copy.
306
+ std::string doc;
307
+ std::getline(sin, doc, (char)EOF);
308
+ return parse( doc, root, collectComments );
309
+ }
310
+
311
+ bool
312
+ Reader::parse( const char *beginDoc, const char *endDoc,
313
+ Value &root,
314
+ bool collectComments )
315
+ {
316
+ if ( !features_.allowComments_ )
317
+ {
318
+ collectComments = false;
319
+ }
320
+
321
+ begin_ = beginDoc;
322
+ end_ = endDoc;
323
+ collectComments_ = collectComments;
324
+ current_ = begin_;
325
+ lastValueEnd_ = 0;
326
+ lastValue_ = 0;
327
+ commentsBefore_ = "";
328
+ errors_.clear();
329
+ while ( !nodes_.empty() )
330
+ nodes_.pop();
331
+ nodes_.push( &root );
332
+
333
+ bool successful = readValue();
334
+ Token token;
335
+ skipCommentTokens( token );
336
+ if ( collectComments_ && !commentsBefore_.empty() )
337
+ root.setComment( commentsBefore_, commentAfter );
338
+ if ( features_.strictRoot_ )
339
+ {
340
+ if ( !root.isArray() && !root.isObject() )
341
+ {
342
+ // Set error location to start of doc, ideally should be first token found in doc
343
+ token.type_ = tokenError;
344
+ token.start_ = beginDoc;
345
+ token.end_ = endDoc;
346
+ addError( "A valid JSON document must be either an array or an object value.",
347
+ token );
348
+ return false;
349
+ }
350
+ }
351
+ return successful;
352
+ }
353
+
354
+
355
+ bool
356
+ Reader::readValue()
357
+ {
358
+ Token token;
359
+ skipCommentTokens( token );
360
+ bool successful = true;
361
+
362
+ if ( collectComments_ && !commentsBefore_.empty() )
363
+ {
364
+ currentValue().setComment( commentsBefore_, commentBefore );
365
+ commentsBefore_ = "";
366
+ }
367
+
368
+
369
+ switch ( token.type_ )
370
+ {
371
+ case tokenObjectBegin:
372
+ successful = readObject( token );
373
+ break;
374
+ case tokenArrayBegin:
375
+ successful = readArray( token );
376
+ break;
377
+ case tokenNumber:
378
+ successful = decodeNumber( token );
379
+ break;
380
+ case tokenString:
381
+ successful = decodeString( token );
382
+ break;
383
+ case tokenTrue:
384
+ currentValue() = true;
385
+ break;
386
+ case tokenFalse:
387
+ currentValue() = false;
388
+ break;
389
+ case tokenNull:
390
+ currentValue() = Value();
391
+ break;
392
+ default:
393
+ return addError( "Syntax error: value, object or array expected.", token );
394
+ }
395
+
396
+ if ( collectComments_ )
397
+ {
398
+ lastValueEnd_ = current_;
399
+ lastValue_ = &currentValue();
400
+ }
401
+
402
+ return successful;
403
+ }
404
+
405
+
406
+ void
407
+ Reader::skipCommentTokens( Token &token )
408
+ {
409
+ if ( features_.allowComments_ )
410
+ {
411
+ do
412
+ {
413
+ readToken( token );
414
+ }
415
+ while ( token.type_ == tokenComment );
416
+ }
417
+ else
418
+ {
419
+ readToken( token );
420
+ }
421
+ }
422
+
423
+
424
+ bool
425
+ Reader::expectToken( TokenType type, Token &token, const char *message )
426
+ {
427
+ readToken( token );
428
+ if ( token.type_ != type )
429
+ return addError( message, token );
430
+ return true;
431
+ }
432
+
433
+
434
+ bool
435
+ Reader::readToken( Token &token )
436
+ {
437
+ skipSpaces();
438
+ token.start_ = current_;
439
+ Char c = getNextChar();
440
+ bool ok = true;
441
+ switch ( c )
442
+ {
443
+ case '{':
444
+ token.type_ = tokenObjectBegin;
445
+ break;
446
+ case '}':
447
+ token.type_ = tokenObjectEnd;
448
+ break;
449
+ case '[':
450
+ token.type_ = tokenArrayBegin;
451
+ break;
452
+ case ']':
453
+ token.type_ = tokenArrayEnd;
454
+ break;
455
+ case '"':
456
+ token.type_ = tokenString;
457
+ ok = readString();
458
+ break;
459
+ case '/':
460
+ token.type_ = tokenComment;
461
+ ok = readComment();
462
+ break;
463
+ case '0':
464
+ case '1':
465
+ case '2':
466
+ case '3':
467
+ case '4':
468
+ case '5':
469
+ case '6':
470
+ case '7':
471
+ case '8':
472
+ case '9':
473
+ case '-':
474
+ token.type_ = tokenNumber;
475
+ readNumber();
476
+ break;
477
+ case 't':
478
+ token.type_ = tokenTrue;
479
+ ok = match( "rue", 3 );
480
+ break;
481
+ case 'f':
482
+ token.type_ = tokenFalse;
483
+ ok = match( "alse", 4 );
484
+ break;
485
+ case 'n':
486
+ token.type_ = tokenNull;
487
+ ok = match( "ull", 3 );
488
+ break;
489
+ case ',':
490
+ token.type_ = tokenArraySeparator;
491
+ break;
492
+ case ':':
493
+ token.type_ = tokenMemberSeparator;
494
+ break;
495
+ case 0:
496
+ token.type_ = tokenEndOfStream;
497
+ break;
498
+ default:
499
+ ok = false;
500
+ break;
501
+ }
502
+ if ( !ok )
503
+ token.type_ = tokenError;
504
+ token.end_ = current_;
505
+ return true;
506
+ }
507
+
508
+
509
+ void
510
+ Reader::skipSpaces()
511
+ {
512
+ while ( current_ != end_ )
513
+ {
514
+ Char c = *current_;
515
+ if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' )
516
+ ++current_;
517
+ else
518
+ break;
519
+ }
520
+ }
521
+
522
+
523
+ bool
524
+ Reader::match( Location pattern,
525
+ int patternLength )
526
+ {
527
+ if ( end_ - current_ < patternLength )
528
+ return false;
529
+ int index = patternLength;
530
+ while ( index-- )
531
+ if ( current_[index] != pattern[index] )
532
+ return false;
533
+ current_ += patternLength;
534
+ return true;
535
+ }
536
+
537
+
538
+ bool
539
+ Reader::readComment()
540
+ {
541
+ Location commentBegin = current_ - 1;
542
+ Char c = getNextChar();
543
+ bool successful = false;
544
+ if ( c == '*' )
545
+ successful = readCStyleComment();
546
+ else if ( c == '/' )
547
+ successful = readCppStyleComment();
548
+ if ( !successful )
549
+ return false;
550
+
551
+ if ( collectComments_ )
552
+ {
553
+ CommentPlacement placement = commentBefore;
554
+ if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) )
555
+ {
556
+ if ( c != '*' || !containsNewLine( commentBegin, current_ ) )
557
+ placement = commentAfterOnSameLine;
558
+ }
559
+
560
+ addComment( commentBegin, current_, placement );
561
+ }
562
+ return true;
563
+ }
564
+
565
+
566
+ void
567
+ Reader::addComment( Location begin,
568
+ Location end,
569
+ CommentPlacement placement )
570
+ {
571
+ assert( collectComments_ );
572
+ if ( placement == commentAfterOnSameLine )
573
+ {
574
+ assert( lastValue_ != 0 );
575
+ lastValue_->setComment( std::string( begin, end ), placement );
576
+ }
577
+ else
578
+ {
579
+ if ( !commentsBefore_.empty() )
580
+ commentsBefore_ += "\n";
581
+ commentsBefore_ += std::string( begin, end );
582
+ }
583
+ }
584
+
585
+
586
+ bool
587
+ Reader::readCStyleComment()
588
+ {
589
+ while ( current_ != end_ )
590
+ {
591
+ Char c = getNextChar();
592
+ if ( c == '*' && *current_ == '/' )
593
+ break;
594
+ }
595
+ return getNextChar() == '/';
596
+ }
597
+
598
+
599
+ bool
600
+ Reader::readCppStyleComment()
601
+ {
602
+ while ( current_ != end_ )
603
+ {
604
+ Char c = getNextChar();
605
+ if ( c == '\r' || c == '\n' )
606
+ break;
607
+ }
608
+ return true;
609
+ }
610
+
611
+
612
+ void
613
+ Reader::readNumber()
614
+ {
615
+ while ( current_ != end_ )
616
+ {
617
+ if ( !(*current_ >= '0' && *current_ <= '9') &&
618
+ !in( *current_, '.', 'e', 'E', '+', '-' ) )
619
+ break;
620
+ ++current_;
621
+ }
622
+ }
623
+
624
+ bool
625
+ Reader::readString()
626
+ {
627
+ Char c = 0;
628
+ while ( current_ != end_ )
629
+ {
630
+ c = getNextChar();
631
+ if ( c == '\\' )
632
+ getNextChar();
633
+ else if ( c == '"' )
634
+ break;
635
+ }
636
+ return c == '"';
637
+ }
638
+
639
+
640
+ bool
641
+ Reader::readObject( Token &/*tokenStart*/ )
642
+ {
643
+ Token tokenName;
644
+ std::string name;
645
+ currentValue() = Value( objectValue );
646
+ while ( readToken( tokenName ) )
647
+ {
648
+ bool initialTokenOk = true;
649
+ while ( tokenName.type_ == tokenComment && initialTokenOk )
650
+ initialTokenOk = readToken( tokenName );
651
+ if ( !initialTokenOk )
652
+ break;
653
+ if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object
654
+ return true;
655
+ if ( tokenName.type_ != tokenString )
656
+ break;
657
+
658
+ name = "";
659
+ if ( !decodeString( tokenName, name ) )
660
+ return recoverFromError( tokenObjectEnd );
661
+
662
+ Token colon;
663
+ if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator )
664
+ {
665
+ return addErrorAndRecover( "Missing ':' after object member name",
666
+ colon,
667
+ tokenObjectEnd );
668
+ }
669
+ Value &value = currentValue()[ name ];
670
+ nodes_.push( &value );
671
+ bool ok = readValue();
672
+ nodes_.pop();
673
+ if ( !ok ) // error already set
674
+ return recoverFromError( tokenObjectEnd );
675
+
676
+ Token comma;
677
+ if ( !readToken( comma )
678
+ || ( comma.type_ != tokenObjectEnd &&
679
+ comma.type_ != tokenArraySeparator &&
680
+ comma.type_ != tokenComment ) )
681
+ {
682
+ return addErrorAndRecover( "Missing ',' or '}' in object declaration",
683
+ comma,
684
+ tokenObjectEnd );
685
+ }
686
+ bool finalizeTokenOk = true;
687
+ while ( comma.type_ == tokenComment &&
688
+ finalizeTokenOk )
689
+ finalizeTokenOk = readToken( comma );
690
+ if ( comma.type_ == tokenObjectEnd )
691
+ return true;
692
+ }
693
+ return addErrorAndRecover( "Missing '}' or object member name",
694
+ tokenName,
695
+ tokenObjectEnd );
696
+ }
697
+
698
+
699
+ bool
700
+ Reader::readArray( Token &/*tokenStart*/ )
701
+ {
702
+ currentValue() = Value( arrayValue );
703
+ skipSpaces();
704
+ if ( *current_ == ']' ) // empty array
705
+ {
706
+ Token endArray;
707
+ readToken( endArray );
708
+ return true;
709
+ }
710
+ int index = 0;
711
+ for (;;)
712
+ {
713
+ Value &value = currentValue()[ index++ ];
714
+ nodes_.push( &value );
715
+ bool ok = readValue();
716
+ nodes_.pop();
717
+ if ( !ok ) // error already set
718
+ return recoverFromError( tokenArrayEnd );
719
+
720
+ Token token;
721
+ // Accept Comment after last item in the array.
722
+ ok = readToken( token );
723
+ while ( token.type_ == tokenComment && ok )
724
+ {
725
+ ok = readToken( token );
726
+ }
727
+ bool badTokenType = ( token.type_ != tokenArraySeparator &&
728
+ token.type_ != tokenArrayEnd );
729
+ if ( !ok || badTokenType )
730
+ {
731
+ return addErrorAndRecover( "Missing ',' or ']' in array declaration",
732
+ token,
733
+ tokenArrayEnd );
734
+ }
735
+ if ( token.type_ == tokenArrayEnd )
736
+ break;
737
+ }
738
+ return true;
739
+ }
740
+
741
+
742
+ bool
743
+ Reader::decodeNumber( Token &token )
744
+ {
745
+ bool isDouble = false;
746
+ for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
747
+ {
748
+ isDouble = isDouble
749
+ || in( *inspect, '.', 'e', 'E', '+' )
750
+ || ( *inspect == '-' && inspect != token.start_ );
751
+ }
752
+ if ( isDouble )
753
+ return decodeDouble( token );
754
+ // Attempts to parse the number as an integer. If the number is
755
+ // larger than the maximum supported value of an integer then
756
+ // we decode the number as a double.
757
+ Location current = token.start_;
758
+ bool isNegative = *current == '-';
759
+ if ( isNegative )
760
+ ++current;
761
+ Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt)
762
+ : Value::maxLargestUInt;
763
+ Value::LargestUInt threshold = maxIntegerValue / 10;
764
+ Value::UInt lastDigitThreshold = Value::UInt( maxIntegerValue % 10 );
765
+ assert( lastDigitThreshold >=0 && lastDigitThreshold <= 9 );
766
+ Value::LargestUInt value = 0;
767
+ while ( current < token.end_ )
768
+ {
769
+ Char c = *current++;
770
+ if ( c < '0' || c > '9' )
771
+ return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
772
+ Value::UInt digit(c - '0');
773
+ if ( value >= threshold )
774
+ {
775
+ // If the current digit is not the last one, or if it is
776
+ // greater than the last digit of the maximum integer value,
777
+ // the parse the number as a double.
778
+ if ( current != token.end_ || digit > lastDigitThreshold )
779
+ {
780
+ return decodeDouble( token );
781
+ }
782
+ }
783
+ value = value * 10 + digit;
784
+ }
785
+ if ( isNegative )
786
+ currentValue() = -Value::LargestInt( value );
787
+ else if ( value <= Value::LargestUInt(Value::maxInt) )
788
+ currentValue() = Value::LargestInt( value );
789
+ else
790
+ currentValue() = value;
791
+ return true;
792
+ }
793
+
794
+
795
+ bool
796
+ Reader::decodeDouble( Token &token )
797
+ {
798
+ double value = 0;
799
+ const int bufferSize = 32;
800
+ int count;
801
+ int length = int(token.end_ - token.start_);
802
+ if ( length <= bufferSize )
803
+ {
804
+ Char buffer[bufferSize+1];
805
+ memcpy( buffer, token.start_, length );
806
+ buffer[length] = 0;
807
+ count = sscanf( buffer, "%lf", &value );
808
+ }
809
+ else
810
+ {
811
+ std::string buffer( token.start_, token.end_ );
812
+ count = sscanf( buffer.c_str(), "%lf", &value );
813
+ }
814
+
815
+ if ( count != 1 )
816
+ return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
817
+ currentValue() = value;
818
+ return true;
819
+ }
820
+
821
+
822
+ bool
823
+ Reader::decodeString( Token &token )
824
+ {
825
+ std::string decoded;
826
+ if ( !decodeString( token, decoded ) )
827
+ return false;
828
+ currentValue() = decoded;
829
+ return true;
830
+ }
831
+
832
+
833
+ bool
834
+ Reader::decodeString( Token &token, std::string &decoded )
835
+ {
836
+ decoded.reserve( token.end_ - token.start_ - 2 );
837
+ Location current = token.start_ + 1; // skip '"'
838
+ Location end = token.end_ - 1; // do not include '"'
839
+ while ( current != end )
840
+ {
841
+ Char c = *current++;
842
+ if ( c == '"' )
843
+ break;
844
+ else if ( c == '\\' )
845
+ {
846
+ if ( current == end )
847
+ return addError( "Empty escape sequence in string", token, current );
848
+ Char escape = *current++;
849
+ switch ( escape )
850
+ {
851
+ case '"': decoded += '"'; break;
852
+ case '/': decoded += '/'; break;
853
+ case '\\': decoded += '\\'; break;
854
+ case 'b': decoded += '\b'; break;
855
+ case 'f': decoded += '\f'; break;
856
+ case 'n': decoded += '\n'; break;
857
+ case 'r': decoded += '\r'; break;
858
+ case 't': decoded += '\t'; break;
859
+ case 'u':
860
+ {
861
+ unsigned int unicode;
862
+ if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
863
+ return false;
864
+ decoded += codePointToUTF8(unicode);
865
+ }
866
+ break;
867
+ default:
868
+ return addError( "Bad escape sequence in string", token, current );
869
+ }
870
+ }
871
+ else
872
+ {
873
+ decoded += c;
874
+ }
875
+ }
876
+ return true;
877
+ }
878
+
879
+ bool
880
+ Reader::decodeUnicodeCodePoint( Token &token,
881
+ Location &current,
882
+ Location end,
883
+ unsigned int &unicode )
884
+ {
885
+
886
+ if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
887
+ return false;
888
+ if (unicode >= 0xD800 && unicode <= 0xDBFF)
889
+ {
890
+ // surrogate pairs
891
+ if (end - current < 6)
892
+ return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
893
+ unsigned int surrogatePair;
894
+ if (*(current++) == '\\' && *(current++)== 'u')
895
+ {
896
+ if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
897
+ {
898
+ unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
899
+ }
900
+ else
901
+ return false;
902
+ }
903
+ else
904
+ return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
905
+ }
906
+ return true;
907
+ }
908
+
909
+ bool
910
+ Reader::decodeUnicodeEscapeSequence( Token &token,
911
+ Location &current,
912
+ Location end,
913
+ unsigned int &unicode )
914
+ {
915
+ if ( end - current < 4 )
916
+ return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
917
+ unicode = 0;
918
+ for ( int index =0; index < 4; ++index )
919
+ {
920
+ Char c = *current++;
921
+ unicode *= 16;
922
+ if ( c >= '0' && c <= '9' )
923
+ unicode += c - '0';
924
+ else if ( c >= 'a' && c <= 'f' )
925
+ unicode += c - 'a' + 10;
926
+ else if ( c >= 'A' && c <= 'F' )
927
+ unicode += c - 'A' + 10;
928
+ else
929
+ return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
930
+ }
931
+ return true;
932
+ }
933
+
934
+
935
+ bool
936
+ Reader::addError( const std::string &message,
937
+ Token &token,
938
+ Location extra )
939
+ {
940
+ ErrorInfo info;
941
+ info.token_ = token;
942
+ info.message_ = message;
943
+ info.extra_ = extra;
944
+ errors_.push_back( info );
945
+ return false;
946
+ }
947
+
948
+
949
+ bool
950
+ Reader::recoverFromError( TokenType skipUntilToken )
951
+ {
952
+ int errorCount = int(errors_.size());
953
+ Token skip;
954
+ for (;;)
955
+ {
956
+ if ( !readToken(skip) )
957
+ errors_.resize( errorCount ); // discard errors caused by recovery
958
+ if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream )
959
+ break;
960
+ }
961
+ errors_.resize( errorCount );
962
+ return false;
963
+ }
964
+
965
+
966
+ bool
967
+ Reader::addErrorAndRecover( const std::string &message,
968
+ Token &token,
969
+ TokenType skipUntilToken )
970
+ {
971
+ addError( message, token );
972
+ return recoverFromError( skipUntilToken );
973
+ }
974
+
975
+
976
+ Value &
977
+ Reader::currentValue()
978
+ {
979
+ return *(nodes_.top());
980
+ }
981
+
982
+
983
+ Reader::Char
984
+ Reader::getNextChar()
985
+ {
986
+ if ( current_ == end_ )
987
+ return 0;
988
+ return *current_++;
989
+ }
990
+
991
+
992
+ void
993
+ Reader::getLocationLineAndColumn( Location location,
994
+ int &line,
995
+ int &column ) const
996
+ {
997
+ Location current = begin_;
998
+ Location lastLineStart = current;
999
+ line = 0;
1000
+ while ( current < location && current != end_ )
1001
+ {
1002
+ Char c = *current++;
1003
+ if ( c == '\r' )
1004
+ {
1005
+ if ( *current == '\n' )
1006
+ ++current;
1007
+ lastLineStart = current;
1008
+ ++line;
1009
+ }
1010
+ else if ( c == '\n' )
1011
+ {
1012
+ lastLineStart = current;
1013
+ ++line;
1014
+ }
1015
+ }
1016
+ // column & line start at 1
1017
+ column = int(location - lastLineStart) + 1;
1018
+ ++line;
1019
+ }
1020
+
1021
+
1022
+ std::string
1023
+ Reader::getLocationLineAndColumn( Location location ) const
1024
+ {
1025
+ int line, column;
1026
+ getLocationLineAndColumn( location, line, column );
1027
+ char buffer[18+16+16+1];
1028
+ sprintf( buffer, "Line %d, Column %d", line, column );
1029
+ return buffer;
1030
+ }
1031
+
1032
+
1033
+ // Deprecated. Preserved for backward compatibility
1034
+ std::string
1035
+ Reader::getFormatedErrorMessages() const
1036
+ {
1037
+ return getFormattedErrorMessages();
1038
+ }
1039
+
1040
+
1041
+ std::string
1042
+ Reader::getFormattedErrorMessages() const
1043
+ {
1044
+ std::string formattedMessage;
1045
+ for ( Errors::const_iterator itError = errors_.begin();
1046
+ itError != errors_.end();
1047
+ ++itError )
1048
+ {
1049
+ const ErrorInfo &error = *itError;
1050
+ formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
1051
+ formattedMessage += " " + error.message_ + "\n";
1052
+ if ( error.extra_ )
1053
+ formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
1054
+ }
1055
+ return formattedMessage;
1056
+ }
1057
+
1058
+
1059
+ std::istream& operator>>( std::istream &sin, Value &root )
1060
+ {
1061
+ Json::Reader reader;
1062
+ bool ok = reader.parse(sin, root, true);
1063
+ //JSON_ASSERT( ok );
1064
+ if (!ok) throw std::runtime_error(reader.getFormattedErrorMessages());
1065
+ return sin;
1066
+ }
1067
+
1068
+
1069
+ } // namespace Json
1070
+
1071
+ // //////////////////////////////////////////////////////////////////////
1072
+ // End of content of file: src/lib_json/json_reader.cpp
1073
+ // //////////////////////////////////////////////////////////////////////
1074
+
1075
+
1076
+
1077
+
1078
+
1079
+
1080
+ // //////////////////////////////////////////////////////////////////////
1081
+ // Beginning of content of file: src/lib_json/json_batchallocator.h
1082
+ // //////////////////////////////////////////////////////////////////////
1083
+
1084
+ // Copyright 2007-2010 Baptiste Lepilleur
1085
+ // Distributed under MIT license, or public domain if desired and
1086
+ // recognized in your jurisdiction.
1087
+ // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
1088
+
1089
+ #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
1090
+ # define JSONCPP_BATCHALLOCATOR_H_INCLUDED
1091
+
1092
+ # include <stdlib.h>
1093
+ # include <assert.h>
1094
+
1095
+ # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
1096
+
1097
+ namespace Json {
1098
+
1099
+ /* Fast memory allocator.
1100
+ *
1101
+ * This memory allocator allocates memory for a batch of object (specified by
1102
+ * the page size, the number of object in each page).
1103
+ *
1104
+ * It does not allow the destruction of a single object. All the allocated objects
1105
+ * can be destroyed at once. The memory can be either released or reused for future
1106
+ * allocation.
1107
+ *
1108
+ * The in-place new operator must be used to construct the object using the pointer
1109
+ * returned by allocate.
1110
+ */
1111
+ template<typename AllocatedType
1112
+ ,const unsigned int objectPerAllocation>
1113
+ class BatchAllocator
1114
+ {
1115
+ public:
1116
+ typedef AllocatedType Type;
1117
+
1118
+ BatchAllocator( unsigned int objectsPerPage = 255 )
1119
+ : freeHead_( 0 )
1120
+ , objectsPerPage_( objectsPerPage )
1121
+ {
1122
+ // printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
1123
+ assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
1124
+ assert( objectsPerPage >= 16 );
1125
+ batches_ = allocateBatch( 0 ); // allocated a dummy page
1126
+ currentBatch_ = batches_;
1127
+ }
1128
+
1129
+ ~BatchAllocator()
1130
+ {
1131
+ for ( BatchInfo *batch = batches_; batch; )
1132
+ {
1133
+ BatchInfo *nextBatch = batch->next_;
1134
+ free( batch );
1135
+ batch = nextBatch;
1136
+ }
1137
+ }
1138
+
1139
+ /// allocate space for an array of objectPerAllocation object.
1140
+ /// @warning it is the responsability of the caller to call objects constructors.
1141
+ AllocatedType *allocate()
1142
+ {
1143
+ if ( freeHead_ ) // returns node from free list.
1144
+ {
1145
+ AllocatedType *object = freeHead_;
1146
+ freeHead_ = *(AllocatedType **)object;
1147
+ return object;
1148
+ }
1149
+ if ( currentBatch_->used_ == currentBatch_->end_ )
1150
+ {
1151
+ currentBatch_ = currentBatch_->next_;
1152
+ while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
1153
+ currentBatch_ = currentBatch_->next_;
1154
+
1155
+ if ( !currentBatch_ ) // no free batch found, allocate a new one
1156
+ {
1157
+ currentBatch_ = allocateBatch( objectsPerPage_ );
1158
+ currentBatch_->next_ = batches_; // insert at the head of the list
1159
+ batches_ = currentBatch_;
1160
+ }
1161
+ }
1162
+ AllocatedType *allocated = currentBatch_->used_;
1163
+ currentBatch_->used_ += objectPerAllocation;
1164
+ return allocated;
1165
+ }
1166
+
1167
+ /// Release the object.
1168
+ /// @warning it is the responsability of the caller to actually destruct the object.
1169
+ void release( AllocatedType *object )
1170
+ {
1171
+ assert( object != 0 );
1172
+ *(AllocatedType **)object = freeHead_;
1173
+ freeHead_ = object;
1174
+ }
1175
+
1176
+ private:
1177
+ struct BatchInfo
1178
+ {
1179
+ BatchInfo *next_;
1180
+ AllocatedType *used_;
1181
+ AllocatedType *end_;
1182
+ AllocatedType buffer_[objectPerAllocation];
1183
+ };
1184
+
1185
+ // disabled copy constructor and assignement operator.
1186
+ BatchAllocator( const BatchAllocator & );
1187
+ void operator =( const BatchAllocator &);
1188
+
1189
+ static BatchInfo *allocateBatch( unsigned int objectsPerPage )
1190
+ {
1191
+ const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
1192
+ + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
1193
+ BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
1194
+ batch->next_ = 0;
1195
+ batch->used_ = batch->buffer_;
1196
+ batch->end_ = batch->buffer_ + objectsPerPage;
1197
+ return batch;
1198
+ }
1199
+
1200
+ BatchInfo *batches_;
1201
+ BatchInfo *currentBatch_;
1202
+ /// Head of a single linked list within the allocated space of freeed object
1203
+ AllocatedType *freeHead_;
1204
+ unsigned int objectsPerPage_;
1205
+ };
1206
+
1207
+
1208
+ } // namespace Json
1209
+
1210
+ # endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
1211
+
1212
+ #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
1213
+
1214
+
1215
+ // //////////////////////////////////////////////////////////////////////
1216
+ // End of content of file: src/lib_json/json_batchallocator.h
1217
+ // //////////////////////////////////////////////////////////////////////
1218
+
1219
+
1220
+
1221
+
1222
+
1223
+
1224
+ // //////////////////////////////////////////////////////////////////////
1225
+ // Beginning of content of file: src/lib_json/json_valueiterator.inl
1226
+ // //////////////////////////////////////////////////////////////////////
1227
+
1228
+ // Copyright 2007-2010 Baptiste Lepilleur
1229
+ // Distributed under MIT license, or public domain if desired and
1230
+ // recognized in your jurisdiction.
1231
+ // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
1232
+
1233
+ // included by json_value.cpp
1234
+
1235
+ namespace Json {
1236
+
1237
+ // //////////////////////////////////////////////////////////////////
1238
+ // //////////////////////////////////////////////////////////////////
1239
+ // //////////////////////////////////////////////////////////////////
1240
+ // class ValueIteratorBase
1241
+ // //////////////////////////////////////////////////////////////////
1242
+ // //////////////////////////////////////////////////////////////////
1243
+ // //////////////////////////////////////////////////////////////////
1244
+
1245
+ ValueIteratorBase::ValueIteratorBase()
1246
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1247
+ : current_()
1248
+ , isNull_( true )
1249
+ {
1250
+ }
1251
+ #else
1252
+ : isArray_( true )
1253
+ , isNull_( true )
1254
+ {
1255
+ iterator_.array_ = ValueInternalArray::IteratorState();
1256
+ }
1257
+ #endif
1258
+
1259
+
1260
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1261
+ ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current )
1262
+ : current_( current )
1263
+ , isNull_( false )
1264
+ {
1265
+ }
1266
+ #else
1267
+ ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
1268
+ : isArray_( true )
1269
+ {
1270
+ iterator_.array_ = state;
1271
+ }
1272
+
1273
+
1274
+ ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
1275
+ : isArray_( false )
1276
+ {
1277
+ iterator_.map_ = state;
1278
+ }
1279
+ #endif
1280
+
1281
+ Value &
1282
+ ValueIteratorBase::deref() const
1283
+ {
1284
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1285
+ return current_->second;
1286
+ #else
1287
+ if ( isArray_ )
1288
+ return ValueInternalArray::dereference( iterator_.array_ );
1289
+ return ValueInternalMap::value( iterator_.map_ );
1290
+ #endif
1291
+ }
1292
+
1293
+
1294
+ void
1295
+ ValueIteratorBase::increment()
1296
+ {
1297
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1298
+ ++current_;
1299
+ #else
1300
+ if ( isArray_ )
1301
+ ValueInternalArray::increment( iterator_.array_ );
1302
+ ValueInternalMap::increment( iterator_.map_ );
1303
+ #endif
1304
+ }
1305
+
1306
+
1307
+ void
1308
+ ValueIteratorBase::decrement()
1309
+ {
1310
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1311
+ --current_;
1312
+ #else
1313
+ if ( isArray_ )
1314
+ ValueInternalArray::decrement( iterator_.array_ );
1315
+ ValueInternalMap::decrement( iterator_.map_ );
1316
+ #endif
1317
+ }
1318
+
1319
+
1320
+ ValueIteratorBase::difference_type
1321
+ ValueIteratorBase::computeDistance( const SelfType &other ) const
1322
+ {
1323
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1324
+ # ifdef JSON_USE_CPPTL_SMALLMAP
1325
+ return current_ - other.current_;
1326
+ # else
1327
+ // Iterator for null value are initialized using the default
1328
+ // constructor, which initialize current_ to the default
1329
+ // std::map::iterator. As begin() and end() are two instance
1330
+ // of the default std::map::iterator, they can not be compared.
1331
+ // To allow this, we handle this comparison specifically.
1332
+ if ( isNull_ && other.isNull_ )
1333
+ {
1334
+ return 0;
1335
+ }
1336
+
1337
+
1338
+ // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
1339
+ // which is the one used by default).
1340
+ // Using a portable hand-made version for non random iterator instead:
1341
+ // return difference_type( std::distance( current_, other.current_ ) );
1342
+ difference_type myDistance = 0;
1343
+ for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
1344
+ {
1345
+ ++myDistance;
1346
+ }
1347
+ return myDistance;
1348
+ # endif
1349
+ #else
1350
+ if ( isArray_ )
1351
+ return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
1352
+ return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
1353
+ #endif
1354
+ }
1355
+
1356
+
1357
+ bool
1358
+ ValueIteratorBase::isEqual( const SelfType &other ) const
1359
+ {
1360
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1361
+ if ( isNull_ )
1362
+ {
1363
+ return other.isNull_;
1364
+ }
1365
+ return current_ == other.current_;
1366
+ #else
1367
+ if ( isArray_ )
1368
+ return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
1369
+ return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
1370
+ #endif
1371
+ }
1372
+
1373
+
1374
+ void
1375
+ ValueIteratorBase::copy( const SelfType &other )
1376
+ {
1377
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1378
+ current_ = other.current_;
1379
+ #else
1380
+ if ( isArray_ )
1381
+ iterator_.array_ = other.iterator_.array_;
1382
+ iterator_.map_ = other.iterator_.map_;
1383
+ #endif
1384
+ }
1385
+
1386
+
1387
+ Value
1388
+ ValueIteratorBase::key() const
1389
+ {
1390
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1391
+ const Value::CZString czstring = (*current_).first;
1392
+ if ( czstring.c_str() )
1393
+ {
1394
+ if ( czstring.isStaticString() )
1395
+ return Value( StaticString( czstring.c_str() ) );
1396
+ return Value( czstring.c_str() );
1397
+ }
1398
+ return Value( czstring.index() );
1399
+ #else
1400
+ if ( isArray_ )
1401
+ return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
1402
+ bool isStatic;
1403
+ const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
1404
+ if ( isStatic )
1405
+ return Value( StaticString( memberName ) );
1406
+ return Value( memberName );
1407
+ #endif
1408
+ }
1409
+
1410
+
1411
+ UInt
1412
+ ValueIteratorBase::index() const
1413
+ {
1414
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1415
+ const Value::CZString czstring = (*current_).first;
1416
+ if ( !czstring.c_str() )
1417
+ return czstring.index();
1418
+ return Value::UInt( -1 );
1419
+ #else
1420
+ if ( isArray_ )
1421
+ return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
1422
+ return Value::UInt( -1 );
1423
+ #endif
1424
+ }
1425
+
1426
+
1427
+ const char *
1428
+ ValueIteratorBase::memberName() const
1429
+ {
1430
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1431
+ const char *name = (*current_).first.c_str();
1432
+ return name ? name : "";
1433
+ #else
1434
+ if ( !isArray_ )
1435
+ return ValueInternalMap::key( iterator_.map_ );
1436
+ return "";
1437
+ #endif
1438
+ }
1439
+
1440
+
1441
+ // //////////////////////////////////////////////////////////////////
1442
+ // //////////////////////////////////////////////////////////////////
1443
+ // //////////////////////////////////////////////////////////////////
1444
+ // class ValueConstIterator
1445
+ // //////////////////////////////////////////////////////////////////
1446
+ // //////////////////////////////////////////////////////////////////
1447
+ // //////////////////////////////////////////////////////////////////
1448
+
1449
+ ValueConstIterator::ValueConstIterator()
1450
+ {
1451
+ }
1452
+
1453
+
1454
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1455
+ ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current )
1456
+ : ValueIteratorBase( current )
1457
+ {
1458
+ }
1459
+ #else
1460
+ ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
1461
+ : ValueIteratorBase( state )
1462
+ {
1463
+ }
1464
+
1465
+ ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
1466
+ : ValueIteratorBase( state )
1467
+ {
1468
+ }
1469
+ #endif
1470
+
1471
+ ValueConstIterator &
1472
+ ValueConstIterator::operator =( const ValueIteratorBase &other )
1473
+ {
1474
+ copy( other );
1475
+ return *this;
1476
+ }
1477
+
1478
+
1479
+ // //////////////////////////////////////////////////////////////////
1480
+ // //////////////////////////////////////////////////////////////////
1481
+ // //////////////////////////////////////////////////////////////////
1482
+ // class ValueIterator
1483
+ // //////////////////////////////////////////////////////////////////
1484
+ // //////////////////////////////////////////////////////////////////
1485
+ // //////////////////////////////////////////////////////////////////
1486
+
1487
+ ValueIterator::ValueIterator()
1488
+ {
1489
+ }
1490
+
1491
+
1492
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1493
+ ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current )
1494
+ : ValueIteratorBase( current )
1495
+ {
1496
+ }
1497
+ #else
1498
+ ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
1499
+ : ValueIteratorBase( state )
1500
+ {
1501
+ }
1502
+
1503
+ ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
1504
+ : ValueIteratorBase( state )
1505
+ {
1506
+ }
1507
+ #endif
1508
+
1509
+ ValueIterator::ValueIterator( const ValueConstIterator &other )
1510
+ : ValueIteratorBase( other )
1511
+ {
1512
+ }
1513
+
1514
+ ValueIterator::ValueIterator( const ValueIterator &other )
1515
+ : ValueIteratorBase( other )
1516
+ {
1517
+ }
1518
+
1519
+ ValueIterator &
1520
+ ValueIterator::operator =( const SelfType &other )
1521
+ {
1522
+ copy( other );
1523
+ return *this;
1524
+ }
1525
+
1526
+ } // namespace Json
1527
+
1528
+ // //////////////////////////////////////////////////////////////////////
1529
+ // End of content of file: src/lib_json/json_valueiterator.inl
1530
+ // //////////////////////////////////////////////////////////////////////
1531
+
1532
+
1533
+
1534
+
1535
+
1536
+
1537
+ // //////////////////////////////////////////////////////////////////////
1538
+ // Beginning of content of file: src/lib_json/json_value.cpp
1539
+ // //////////////////////////////////////////////////////////////////////
1540
+
1541
+ // Copyright 2007-2010 Baptiste Lepilleur
1542
+ // Distributed under MIT license, or public domain if desired and
1543
+ // recognized in your jurisdiction.
1544
+ // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
1545
+
1546
+ #if !defined(JSON_IS_AMALGAMATION)
1547
+ # include <json/value.h>
1548
+ # include <json/writer.h>
1549
+ # ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
1550
+ # include "json_batchallocator.h"
1551
+ # endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
1552
+ #endif // if !defined(JSON_IS_AMALGAMATION)
1553
+ #include <iostream>
1554
+ #include <utility>
1555
+ #include <stdexcept>
1556
+ #include <cstring>
1557
+ #include <cassert>
1558
+ #ifdef JSON_USE_CPPTL
1559
+ # include <cpptl/conststring.h>
1560
+ #endif
1561
+ #include <cstddef> // size_t
1562
+
1563
+ #define JSON_ASSERT_UNREACHABLE assert( false )
1564
+ #define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw
1565
+ #define JSON_FAIL_MESSAGE( message ) throw std::runtime_error( message );
1566
+ #define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) JSON_FAIL_MESSAGE( message )
1567
+
1568
+ namespace Json {
1569
+
1570
+ const Value Value::null;
1571
+ const Int Value::minInt = Int( ~(UInt(-1)/2) );
1572
+ const Int Value::maxInt = Int( UInt(-1)/2 );
1573
+ const UInt Value::maxUInt = UInt(-1);
1574
+ const Int64 Value::minInt64 = Int64( ~(UInt64(-1)/2) );
1575
+ const Int64 Value::maxInt64 = Int64( UInt64(-1)/2 );
1576
+ const UInt64 Value::maxUInt64 = UInt64(-1);
1577
+ const LargestInt Value::minLargestInt = LargestInt( ~(LargestUInt(-1)/2) );
1578
+ const LargestInt Value::maxLargestInt = LargestInt( LargestUInt(-1)/2 );
1579
+ const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
1580
+
1581
+
1582
+ /// Unknown size marker
1583
+ static const unsigned int unknown = (unsigned)-1;
1584
+
1585
+
1586
+ /** Duplicates the specified string value.
1587
+ * @param value Pointer to the string to duplicate. Must be zero-terminated if
1588
+ * length is "unknown".
1589
+ * @param length Length of the value. if equals to unknown, then it will be
1590
+ * computed using strlen(value).
1591
+ * @return Pointer on the duplicate instance of string.
1592
+ */
1593
+ static inline char *
1594
+ duplicateStringValue( const char *value,
1595
+ unsigned int length = unknown )
1596
+ {
1597
+ if ( length == unknown )
1598
+ length = (unsigned int)strlen(value);
1599
+ char *newString = static_cast<char *>( malloc( length + 1 ) );
1600
+ JSON_ASSERT_MESSAGE( newString != 0, "Failed to allocate string value buffer" );
1601
+ memcpy( newString, value, length );
1602
+ newString[length] = 0;
1603
+ return newString;
1604
+ }
1605
+
1606
+
1607
+ /** Free the string duplicated by duplicateStringValue().
1608
+ */
1609
+ static inline void
1610
+ releaseStringValue( char *value )
1611
+ {
1612
+ if ( value )
1613
+ free( value );
1614
+ }
1615
+
1616
+ } // namespace Json
1617
+
1618
+
1619
+ // //////////////////////////////////////////////////////////////////
1620
+ // //////////////////////////////////////////////////////////////////
1621
+ // //////////////////////////////////////////////////////////////////
1622
+ // ValueInternals...
1623
+ // //////////////////////////////////////////////////////////////////
1624
+ // //////////////////////////////////////////////////////////////////
1625
+ // //////////////////////////////////////////////////////////////////
1626
+ #if !defined(JSON_IS_AMALGAMATION)
1627
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1628
+ # include "json_internalarray.inl"
1629
+ # include "json_internalmap.inl"
1630
+ # endif // JSON_VALUE_USE_INTERNAL_MAP
1631
+
1632
+ # include "json_valueiterator.inl"
1633
+ #endif // if !defined(JSON_IS_AMALGAMATION)
1634
+
1635
+ namespace Json {
1636
+
1637
+ // //////////////////////////////////////////////////////////////////
1638
+ // //////////////////////////////////////////////////////////////////
1639
+ // //////////////////////////////////////////////////////////////////
1640
+ // class Value::CommentInfo
1641
+ // //////////////////////////////////////////////////////////////////
1642
+ // //////////////////////////////////////////////////////////////////
1643
+ // //////////////////////////////////////////////////////////////////
1644
+
1645
+
1646
+ Value::CommentInfo::CommentInfo()
1647
+ : comment_( 0 )
1648
+ {
1649
+ }
1650
+
1651
+ Value::CommentInfo::~CommentInfo()
1652
+ {
1653
+ if ( comment_ )
1654
+ releaseStringValue( comment_ );
1655
+ }
1656
+
1657
+
1658
+ void
1659
+ Value::CommentInfo::setComment( const char *text )
1660
+ {
1661
+ if ( comment_ )
1662
+ releaseStringValue( comment_ );
1663
+ JSON_ASSERT( text != 0 );
1664
+ JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
1665
+ // It seems that /**/ style comments are acceptable as well.
1666
+ comment_ = duplicateStringValue( text );
1667
+ }
1668
+
1669
+
1670
+ // //////////////////////////////////////////////////////////////////
1671
+ // //////////////////////////////////////////////////////////////////
1672
+ // //////////////////////////////////////////////////////////////////
1673
+ // class Value::CZString
1674
+ // //////////////////////////////////////////////////////////////////
1675
+ // //////////////////////////////////////////////////////////////////
1676
+ // //////////////////////////////////////////////////////////////////
1677
+ # ifndef JSON_VALUE_USE_INTERNAL_MAP
1678
+
1679
+ // Notes: index_ indicates if the string was allocated when
1680
+ // a string is stored.
1681
+
1682
+ Value::CZString::CZString( ArrayIndex index )
1683
+ : cstr_( 0 )
1684
+ , index_( index )
1685
+ {
1686
+ }
1687
+
1688
+ Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
1689
+ : cstr_( allocate == duplicate ? duplicateStringValue(cstr)
1690
+ : cstr )
1691
+ , index_( allocate )
1692
+ {
1693
+ }
1694
+
1695
+ Value::CZString::CZString( const CZString &other )
1696
+ : cstr_( other.index_ != noDuplication && other.cstr_ != 0
1697
+ ? duplicateStringValue( other.cstr_ )
1698
+ : other.cstr_ )
1699
+ , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
1700
+ : other.index_ )
1701
+ {
1702
+ }
1703
+
1704
+ Value::CZString::~CZString()
1705
+ {
1706
+ if ( cstr_ && index_ == duplicate )
1707
+ releaseStringValue( const_cast<char *>( cstr_ ) );
1708
+ }
1709
+
1710
+ void
1711
+ Value::CZString::swap( CZString &other )
1712
+ {
1713
+ std::swap( cstr_, other.cstr_ );
1714
+ std::swap( index_, other.index_ );
1715
+ }
1716
+
1717
+ Value::CZString &
1718
+ Value::CZString::operator =( const CZString &other )
1719
+ {
1720
+ CZString temp( other );
1721
+ swap( temp );
1722
+ return *this;
1723
+ }
1724
+
1725
+ bool
1726
+ Value::CZString::operator<( const CZString &other ) const
1727
+ {
1728
+ if ( cstr_ )
1729
+ return strcmp( cstr_, other.cstr_ ) < 0;
1730
+ return index_ < other.index_;
1731
+ }
1732
+
1733
+ bool
1734
+ Value::CZString::operator==( const CZString &other ) const
1735
+ {
1736
+ if ( cstr_ )
1737
+ return strcmp( cstr_, other.cstr_ ) == 0;
1738
+ return index_ == other.index_;
1739
+ }
1740
+
1741
+
1742
+ ArrayIndex
1743
+ Value::CZString::index() const
1744
+ {
1745
+ return index_;
1746
+ }
1747
+
1748
+
1749
+ const char *
1750
+ Value::CZString::c_str() const
1751
+ {
1752
+ return cstr_;
1753
+ }
1754
+
1755
+ bool
1756
+ Value::CZString::isStaticString() const
1757
+ {
1758
+ return index_ == noDuplication;
1759
+ }
1760
+
1761
+ #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
1762
+
1763
+
1764
+ // //////////////////////////////////////////////////////////////////
1765
+ // //////////////////////////////////////////////////////////////////
1766
+ // //////////////////////////////////////////////////////////////////
1767
+ // class Value::Value
1768
+ // //////////////////////////////////////////////////////////////////
1769
+ // //////////////////////////////////////////////////////////////////
1770
+ // //////////////////////////////////////////////////////////////////
1771
+
1772
+ /*! \internal Default constructor initialization must be equivalent to:
1773
+ * memset( this, 0, sizeof(Value) )
1774
+ * This optimization is used in ValueInternalMap fast allocator.
1775
+ */
1776
+ Value::Value( ValueType type )
1777
+ : type_( type )
1778
+ , allocated_( 0 )
1779
+ , comments_( 0 )
1780
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1781
+ , itemIsUsed_( 0 )
1782
+ #endif
1783
+ {
1784
+ switch ( type )
1785
+ {
1786
+ case nullValue:
1787
+ break;
1788
+ case intValue:
1789
+ case uintValue:
1790
+ value_.int_ = 0;
1791
+ break;
1792
+ case realValue:
1793
+ value_.real_ = 0.0;
1794
+ break;
1795
+ case stringValue:
1796
+ value_.string_ = 0;
1797
+ break;
1798
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1799
+ case arrayValue:
1800
+ case objectValue:
1801
+ value_.map_ = new ObjectValues();
1802
+ break;
1803
+ #else
1804
+ case arrayValue:
1805
+ value_.array_ = arrayAllocator()->newArray();
1806
+ break;
1807
+ case objectValue:
1808
+ value_.map_ = mapAllocator()->newMap();
1809
+ break;
1810
+ #endif
1811
+ case booleanValue:
1812
+ value_.bool_ = false;
1813
+ break;
1814
+ default:
1815
+ JSON_ASSERT_UNREACHABLE;
1816
+ }
1817
+ }
1818
+
1819
+
1820
+ #if defined(JSON_HAS_INT64)
1821
+ Value::Value( UInt value )
1822
+ : type_( uintValue )
1823
+ , comments_( 0 )
1824
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1825
+ , itemIsUsed_( 0 )
1826
+ #endif
1827
+ {
1828
+ value_.uint_ = value;
1829
+ }
1830
+
1831
+ Value::Value( Int value )
1832
+ : type_( intValue )
1833
+ , comments_( 0 )
1834
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1835
+ , itemIsUsed_( 0 )
1836
+ #endif
1837
+ {
1838
+ value_.int_ = value;
1839
+ }
1840
+
1841
+ #endif // if defined(JSON_HAS_INT64)
1842
+
1843
+
1844
+ Value::Value( Int64 value )
1845
+ : type_( intValue )
1846
+ , comments_( 0 )
1847
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1848
+ , itemIsUsed_( 0 )
1849
+ #endif
1850
+ {
1851
+ value_.int_ = value;
1852
+ }
1853
+
1854
+
1855
+ Value::Value( UInt64 value )
1856
+ : type_( uintValue )
1857
+ , comments_( 0 )
1858
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1859
+ , itemIsUsed_( 0 )
1860
+ #endif
1861
+ {
1862
+ value_.uint_ = value;
1863
+ }
1864
+
1865
+ Value::Value( double value )
1866
+ : type_( realValue )
1867
+ , comments_( 0 )
1868
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1869
+ , itemIsUsed_( 0 )
1870
+ #endif
1871
+ {
1872
+ value_.real_ = value;
1873
+ }
1874
+
1875
+ Value::Value( const char *value )
1876
+ : type_( stringValue )
1877
+ , allocated_( true )
1878
+ , comments_( 0 )
1879
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1880
+ , itemIsUsed_( 0 )
1881
+ #endif
1882
+ {
1883
+ value_.string_ = duplicateStringValue( value );
1884
+ }
1885
+
1886
+
1887
+ Value::Value( const char *beginValue,
1888
+ const char *endValue )
1889
+ : type_( stringValue )
1890
+ , allocated_( true )
1891
+ , comments_( 0 )
1892
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1893
+ , itemIsUsed_( 0 )
1894
+ #endif
1895
+ {
1896
+ value_.string_ = duplicateStringValue( beginValue,
1897
+ (unsigned int)(endValue - beginValue) );
1898
+ }
1899
+
1900
+
1901
+ Value::Value( const std::string &value )
1902
+ : type_( stringValue )
1903
+ , allocated_( true )
1904
+ , comments_( 0 )
1905
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1906
+ , itemIsUsed_( 0 )
1907
+ #endif
1908
+ {
1909
+ value_.string_ = duplicateStringValue( value.c_str(),
1910
+ (unsigned int)value.length() );
1911
+
1912
+ }
1913
+
1914
+ Value::Value( const StaticString &value )
1915
+ : type_( stringValue )
1916
+ , allocated_( false )
1917
+ , comments_( 0 )
1918
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1919
+ , itemIsUsed_( 0 )
1920
+ #endif
1921
+ {
1922
+ value_.string_ = const_cast<char *>( value.c_str() );
1923
+ }
1924
+
1925
+
1926
+ # ifdef JSON_USE_CPPTL
1927
+ Value::Value( const CppTL::ConstString &value )
1928
+ : type_( stringValue )
1929
+ , allocated_( true )
1930
+ , comments_( 0 )
1931
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1932
+ , itemIsUsed_( 0 )
1933
+ #endif
1934
+ {
1935
+ value_.string_ = duplicateStringValue( value, value.length() );
1936
+ }
1937
+ # endif
1938
+
1939
+ Value::Value( bool value )
1940
+ : type_( booleanValue )
1941
+ , comments_( 0 )
1942
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1943
+ , itemIsUsed_( 0 )
1944
+ #endif
1945
+ {
1946
+ value_.bool_ = value;
1947
+ }
1948
+
1949
+
1950
+ Value::Value( const Value &other )
1951
+ : type_( other.type_ )
1952
+ , comments_( 0 )
1953
+ # ifdef JSON_VALUE_USE_INTERNAL_MAP
1954
+ , itemIsUsed_( 0 )
1955
+ #endif
1956
+ {
1957
+ switch ( type_ )
1958
+ {
1959
+ case nullValue:
1960
+ case intValue:
1961
+ case uintValue:
1962
+ case realValue:
1963
+ case booleanValue:
1964
+ value_ = other.value_;
1965
+ break;
1966
+ case stringValue:
1967
+ if ( other.value_.string_ )
1968
+ {
1969
+ value_.string_ = duplicateStringValue( other.value_.string_ );
1970
+ allocated_ = true;
1971
+ }
1972
+ else
1973
+ value_.string_ = 0;
1974
+ break;
1975
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
1976
+ case arrayValue:
1977
+ case objectValue:
1978
+ value_.map_ = new ObjectValues( *other.value_.map_ );
1979
+ break;
1980
+ #else
1981
+ case arrayValue:
1982
+ value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
1983
+ break;
1984
+ case objectValue:
1985
+ value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
1986
+ break;
1987
+ #endif
1988
+ default:
1989
+ JSON_ASSERT_UNREACHABLE;
1990
+ }
1991
+ if ( other.comments_ )
1992
+ {
1993
+ comments_ = new CommentInfo[numberOfCommentPlacement];
1994
+ for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
1995
+ {
1996
+ const CommentInfo &otherComment = other.comments_[comment];
1997
+ if ( otherComment.comment_ )
1998
+ comments_[comment].setComment( otherComment.comment_ );
1999
+ }
2000
+ }
2001
+ }
2002
+
2003
+
2004
+ Value::~Value()
2005
+ {
2006
+ switch ( type_ )
2007
+ {
2008
+ case nullValue:
2009
+ case intValue:
2010
+ case uintValue:
2011
+ case realValue:
2012
+ case booleanValue:
2013
+ break;
2014
+ case stringValue:
2015
+ if ( allocated_ )
2016
+ releaseStringValue( value_.string_ );
2017
+ break;
2018
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
2019
+ case arrayValue:
2020
+ case objectValue:
2021
+ delete value_.map_;
2022
+ break;
2023
+ #else
2024
+ case arrayValue:
2025
+ arrayAllocator()->destructArray( value_.array_ );
2026
+ break;
2027
+ case objectValue:
2028
+ mapAllocator()->destructMap( value_.map_ );
2029
+ break;
2030
+ #endif
2031
+ default:
2032
+ JSON_ASSERT_UNREACHABLE;
2033
+ }
2034
+
2035
+ if ( comments_ )
2036
+ delete[] comments_;
2037
+ }
2038
+
2039
+ Value &
2040
+ Value::operator=( const Value &other )
2041
+ {
2042
+ Value temp( other );
2043
+ swap( temp );
2044
+ return *this;
2045
+ }
2046
+
2047
+ void
2048
+ Value::swap( Value &other )
2049
+ {
2050
+ ValueType temp = type_;
2051
+ type_ = other.type_;
2052
+ other.type_ = temp;
2053
+ std::swap( value_, other.value_ );
2054
+ int temp2 = allocated_;
2055
+ allocated_ = other.allocated_;
2056
+ other.allocated_ = temp2;
2057
+ }
2058
+
2059
+ ValueType
2060
+ Value::type() const
2061
+ {
2062
+ return type_;
2063
+ }
2064
+
2065
+
2066
+ int
2067
+ Value::compare( const Value &other ) const
2068
+ {
2069
+ if ( *this < other )
2070
+ return -1;
2071
+ if ( *this > other )
2072
+ return 1;
2073
+ return 0;
2074
+ }
2075
+
2076
+
2077
+ bool
2078
+ Value::operator <( const Value &other ) const
2079
+ {
2080
+ int typeDelta = type_ - other.type_;
2081
+ if ( typeDelta )
2082
+ return typeDelta < 0 ? true : false;
2083
+ switch ( type_ )
2084
+ {
2085
+ case nullValue:
2086
+ return false;
2087
+ case intValue:
2088
+ return value_.int_ < other.value_.int_;
2089
+ case uintValue:
2090
+ return value_.uint_ < other.value_.uint_;
2091
+ case realValue:
2092
+ return value_.real_ < other.value_.real_;
2093
+ case booleanValue:
2094
+ return value_.bool_ < other.value_.bool_;
2095
+ case stringValue:
2096
+ return ( value_.string_ == 0 && other.value_.string_ )
2097
+ || ( other.value_.string_
2098
+ && value_.string_
2099
+ && strcmp( value_.string_, other.value_.string_ ) < 0 );
2100
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
2101
+ case arrayValue:
2102
+ case objectValue:
2103
+ {
2104
+ int delta = int( value_.map_->size() - other.value_.map_->size() );
2105
+ if ( delta )
2106
+ return delta < 0;
2107
+ return (*value_.map_) < (*other.value_.map_);
2108
+ }
2109
+ #else
2110
+ case arrayValue:
2111
+ return value_.array_->compare( *(other.value_.array_) ) < 0;
2112
+ case objectValue:
2113
+ return value_.map_->compare( *(other.value_.map_) ) < 0;
2114
+ #endif
2115
+ default:
2116
+ JSON_ASSERT_UNREACHABLE;
2117
+ }
2118
+ return false; // unreachable
2119
+ }
2120
+
2121
+ bool
2122
+ Value::operator <=( const Value &other ) const
2123
+ {
2124
+ return !(other < *this);
2125
+ }
2126
+
2127
+ bool
2128
+ Value::operator >=( const Value &other ) const
2129
+ {
2130
+ return !(*this < other);
2131
+ }
2132
+
2133
+ bool
2134
+ Value::operator >( const Value &other ) const
2135
+ {
2136
+ return other < *this;
2137
+ }
2138
+
2139
+ bool
2140
+ Value::operator ==( const Value &other ) const
2141
+ {
2142
+ //if ( type_ != other.type_ )
2143
+ // GCC 2.95.3 says:
2144
+ // attempt to take address of bit-field structure member `Json::Value::type_'
2145
+ // Beats me, but a temp solves the problem.
2146
+ int temp = other.type_;
2147
+ if ( type_ != temp )
2148
+ return false;
2149
+ switch ( type_ )
2150
+ {
2151
+ case nullValue:
2152
+ return true;
2153
+ case intValue:
2154
+ return value_.int_ == other.value_.int_;
2155
+ case uintValue:
2156
+ return value_.uint_ == other.value_.uint_;
2157
+ case realValue:
2158
+ return value_.real_ == other.value_.real_;
2159
+ case booleanValue:
2160
+ return value_.bool_ == other.value_.bool_;
2161
+ case stringValue:
2162
+ return ( value_.string_ == other.value_.string_ )
2163
+ || ( other.value_.string_
2164
+ && value_.string_
2165
+ && strcmp( value_.string_, other.value_.string_ ) == 0 );
2166
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
2167
+ case arrayValue:
2168
+ case objectValue:
2169
+ return value_.map_->size() == other.value_.map_->size()
2170
+ && (*value_.map_) == (*other.value_.map_);
2171
+ #else
2172
+ case arrayValue:
2173
+ return value_.array_->compare( *(other.value_.array_) ) == 0;
2174
+ case objectValue:
2175
+ return value_.map_->compare( *(other.value_.map_) ) == 0;
2176
+ #endif
2177
+ default:
2178
+ JSON_ASSERT_UNREACHABLE;
2179
+ }
2180
+ return false; // unreachable
2181
+ }
2182
+
2183
+ bool
2184
+ Value::operator !=( const Value &other ) const
2185
+ {
2186
+ return !( *this == other );
2187
+ }
2188
+
2189
+ const char *
2190
+ Value::asCString() const
2191
+ {
2192
+ JSON_ASSERT( type_ == stringValue );
2193
+ return value_.string_;
2194
+ }
2195
+
2196
+
2197
+ std::string
2198
+ Value::asString() const
2199
+ {
2200
+ switch ( type_ )
2201
+ {
2202
+ case nullValue:
2203
+ return "";
2204
+ case stringValue:
2205
+ return value_.string_ ? value_.string_ : "";
2206
+ case booleanValue:
2207
+ return value_.bool_ ? "true" : "false";
2208
+ case intValue:
2209
+ case uintValue:
2210
+ case realValue:
2211
+ case arrayValue:
2212
+ case objectValue:
2213
+ JSON_FAIL_MESSAGE( "Type is not convertible to string" );
2214
+ default:
2215
+ JSON_ASSERT_UNREACHABLE;
2216
+ }
2217
+ return ""; // unreachable
2218
+ }
2219
+
2220
+ # ifdef JSON_USE_CPPTL
2221
+ CppTL::ConstString
2222
+ Value::asConstString() const
2223
+ {
2224
+ return CppTL::ConstString( asString().c_str() );
2225
+ }
2226
+ # endif
2227
+
2228
+
2229
+ Value::Int
2230
+ Value::asInt() const
2231
+ {
2232
+ switch ( type_ )
2233
+ {
2234
+ case nullValue:
2235
+ return 0;
2236
+ case intValue:
2237
+ JSON_ASSERT_MESSAGE( value_.int_ >= minInt && value_.int_ <= maxInt, "unsigned integer out of signed int range" );
2238
+ return Int(value_.int_);
2239
+ case uintValue:
2240
+ JSON_ASSERT_MESSAGE( value_.uint_ <= UInt(maxInt), "unsigned integer out of signed int range" );
2241
+ return Int(value_.uint_);
2242
+ case realValue:
2243
+ JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" );
2244
+ return Int( value_.real_ );
2245
+ case booleanValue:
2246
+ return value_.bool_ ? 1 : 0;
2247
+ case stringValue:
2248
+ case arrayValue:
2249
+ case objectValue:
2250
+ JSON_FAIL_MESSAGE( "Type is not convertible to int" );
2251
+ default:
2252
+ JSON_ASSERT_UNREACHABLE;
2253
+ }
2254
+ return 0; // unreachable;
2255
+ }
2256
+
2257
+
2258
+ Value::UInt
2259
+ Value::asUInt() const
2260
+ {
2261
+ switch ( type_ )
2262
+ {
2263
+ case nullValue:
2264
+ return 0;
2265
+ case intValue:
2266
+ JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
2267
+ JSON_ASSERT_MESSAGE( value_.int_ <= maxUInt, "signed integer out of UInt range" );
2268
+ return UInt(value_.int_);
2269
+ case uintValue:
2270
+ JSON_ASSERT_MESSAGE( value_.uint_ <= maxUInt, "unsigned integer out of UInt range" );
2271
+ return UInt(value_.uint_);
2272
+ case realValue:
2273
+ JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range" );
2274
+ return UInt( value_.real_ );
2275
+ case booleanValue:
2276
+ return value_.bool_ ? 1 : 0;
2277
+ case stringValue:
2278
+ case arrayValue:
2279
+ case objectValue:
2280
+ JSON_FAIL_MESSAGE( "Type is not convertible to uint" );
2281
+ default:
2282
+ JSON_ASSERT_UNREACHABLE;
2283
+ }
2284
+ return 0; // unreachable;
2285
+ }
2286
+
2287
+
2288
+ # if defined(JSON_HAS_INT64)
2289
+
2290
+ Value::Int64
2291
+ Value::asInt64() const
2292
+ {
2293
+ switch ( type_ )
2294
+ {
2295
+ case nullValue:
2296
+ return 0;
2297
+ case intValue:
2298
+ return value_.int_;
2299
+ case uintValue:
2300
+ JSON_ASSERT_MESSAGE( value_.uint_ <= UInt64(maxInt64), "unsigned integer out of Int64 range" );
2301
+ return value_.uint_;
2302
+ case realValue:
2303
+ JSON_ASSERT_MESSAGE( value_.real_ >= minInt64 && value_.real_ <= maxInt64, "Real out of Int64 range" );
2304
+ return Int( value_.real_ );
2305
+ case booleanValue:
2306
+ return value_.bool_ ? 1 : 0;
2307
+ case stringValue:
2308
+ case arrayValue:
2309
+ case objectValue:
2310
+ JSON_FAIL_MESSAGE( "Type is not convertible to Int64" );
2311
+ default:
2312
+ JSON_ASSERT_UNREACHABLE;
2313
+ }
2314
+ return 0; // unreachable;
2315
+ }
2316
+
2317
+
2318
+ Value::UInt64
2319
+ Value::asUInt64() const
2320
+ {
2321
+ switch ( type_ )
2322
+ {
2323
+ case nullValue:
2324
+ return 0;
2325
+ case intValue:
2326
+ JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to UInt64" );
2327
+ return value_.int_;
2328
+ case uintValue:
2329
+ return value_.uint_;
2330
+ case realValue:
2331
+ JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt64, "Real out of UInt64 range" );
2332
+ return UInt( value_.real_ );
2333
+ case booleanValue:
2334
+ return value_.bool_ ? 1 : 0;
2335
+ case stringValue:
2336
+ case arrayValue:
2337
+ case objectValue:
2338
+ JSON_FAIL_MESSAGE( "Type is not convertible to UInt64" );
2339
+ default:
2340
+ JSON_ASSERT_UNREACHABLE;
2341
+ }
2342
+ return 0; // unreachable;
2343
+ }
2344
+ # endif // if defined(JSON_HAS_INT64)
2345
+
2346
+
2347
+ LargestInt
2348
+ Value::asLargestInt() const
2349
+ {
2350
+ #if defined(JSON_NO_INT64)
2351
+ return asInt();
2352
+ #else
2353
+ return asInt64();
2354
+ #endif
2355
+ }
2356
+
2357
+
2358
+ LargestUInt
2359
+ Value::asLargestUInt() const
2360
+ {
2361
+ #if defined(JSON_NO_INT64)
2362
+ return asUInt();
2363
+ #else
2364
+ return asUInt64();
2365
+ #endif
2366
+ }
2367
+
2368
+
2369
+ double
2370
+ Value::asDouble() const
2371
+ {
2372
+ switch ( type_ )
2373
+ {
2374
+ case nullValue:
2375
+ return 0.0;
2376
+ case intValue:
2377
+ return static_cast<double>( value_.int_ );
2378
+ case uintValue:
2379
+ #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2380
+ return static_cast<double>( value_.uint_ );
2381
+ #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2382
+ return static_cast<double>( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1);
2383
+ #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2384
+ case realValue:
2385
+ return value_.real_;
2386
+ case booleanValue:
2387
+ return value_.bool_ ? 1.0 : 0.0;
2388
+ case stringValue:
2389
+ case arrayValue:
2390
+ case objectValue:
2391
+ JSON_FAIL_MESSAGE( "Type is not convertible to double" );
2392
+ default:
2393
+ JSON_ASSERT_UNREACHABLE;
2394
+ }
2395
+ return 0; // unreachable;
2396
+ }
2397
+
2398
+ float
2399
+ Value::asFloat() const
2400
+ {
2401
+ switch ( type_ )
2402
+ {
2403
+ case nullValue:
2404
+ return 0.0f;
2405
+ case intValue:
2406
+ return static_cast<float>( value_.int_ );
2407
+ case uintValue:
2408
+ #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2409
+ return static_cast<float>( value_.uint_ );
2410
+ #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2411
+ return static_cast<float>( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1);
2412
+ #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2413
+ case realValue:
2414
+ return static_cast<float>( value_.real_ );
2415
+ case booleanValue:
2416
+ return value_.bool_ ? 1.0f : 0.0f;
2417
+ case stringValue:
2418
+ case arrayValue:
2419
+ case objectValue:
2420
+ JSON_FAIL_MESSAGE( "Type is not convertible to float" );
2421
+ default:
2422
+ JSON_ASSERT_UNREACHABLE;
2423
+ }
2424
+ return 0.0f; // unreachable;
2425
+ }
2426
+
2427
+ bool
2428
+ Value::asBool() const
2429
+ {
2430
+ switch ( type_ )
2431
+ {
2432
+ case nullValue:
2433
+ return false;
2434
+ case intValue:
2435
+ case uintValue:
2436
+ return value_.int_ != 0;
2437
+ case realValue:
2438
+ return value_.real_ != 0.0;
2439
+ case booleanValue:
2440
+ return value_.bool_;
2441
+ case stringValue:
2442
+ return value_.string_ && value_.string_[0] != 0;
2443
+ case arrayValue:
2444
+ case objectValue:
2445
+ return value_.map_->size() != 0;
2446
+ default:
2447
+ JSON_ASSERT_UNREACHABLE;
2448
+ }
2449
+ return false; // unreachable;
2450
+ }
2451
+
2452
+
2453
+ bool
2454
+ Value::isConvertibleTo( ValueType other ) const
2455
+ {
2456
+ switch ( type_ )
2457
+ {
2458
+ case nullValue:
2459
+ return true;
2460
+ case intValue:
2461
+ return ( other == nullValue && value_.int_ == 0 )
2462
+ || other == intValue
2463
+ || ( other == uintValue && value_.int_ >= 0 )
2464
+ || other == realValue
2465
+ || other == stringValue
2466
+ || other == booleanValue;
2467
+ case uintValue:
2468
+ return ( other == nullValue && value_.uint_ == 0 )
2469
+ || ( other == intValue && value_.uint_ <= (unsigned)maxInt )
2470
+ || other == uintValue
2471
+ || other == realValue
2472
+ || other == stringValue
2473
+ || other == booleanValue;
2474
+ case realValue:
2475
+ return ( other == nullValue && value_.real_ == 0.0 )
2476
+ || ( other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt )
2477
+ || ( other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt )
2478
+ || other == realValue
2479
+ || other == stringValue
2480
+ || other == booleanValue;
2481
+ case booleanValue:
2482
+ return ( other == nullValue && value_.bool_ == false )
2483
+ || other == intValue
2484
+ || other == uintValue
2485
+ || other == realValue
2486
+ || other == stringValue
2487
+ || other == booleanValue;
2488
+ case stringValue:
2489
+ return other == stringValue
2490
+ || ( other == nullValue && (!value_.string_ || value_.string_[0] == 0) );
2491
+ case arrayValue:
2492
+ return other == arrayValue
2493
+ || ( other == nullValue && value_.map_->size() == 0 );
2494
+ case objectValue:
2495
+ return other == objectValue
2496
+ || ( other == nullValue && value_.map_->size() == 0 );
2497
+ default:
2498
+ JSON_ASSERT_UNREACHABLE;
2499
+ }
2500
+ return false; // unreachable;
2501
+ }
2502
+
2503
+
2504
+ /// Number of values in array or object
2505
+ ArrayIndex
2506
+ Value::size() const
2507
+ {
2508
+ switch ( type_ )
2509
+ {
2510
+ case nullValue:
2511
+ case intValue:
2512
+ case uintValue:
2513
+ case realValue:
2514
+ case booleanValue:
2515
+ case stringValue:
2516
+ return 0;
2517
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
2518
+ case arrayValue: // size of the array is highest index + 1
2519
+ if ( !value_.map_->empty() )
2520
+ {
2521
+ ObjectValues::const_iterator itLast = value_.map_->end();
2522
+ --itLast;
2523
+ return (*itLast).first.index()+1;
2524
+ }
2525
+ return 0;
2526
+ case objectValue:
2527
+ return ArrayIndex( value_.map_->size() );
2528
+ #else
2529
+ case arrayValue:
2530
+ return Int( value_.array_->size() );
2531
+ case objectValue:
2532
+ return Int( value_.map_->size() );
2533
+ #endif
2534
+ default:
2535
+ JSON_ASSERT_UNREACHABLE;
2536
+ }
2537
+ return 0; // unreachable;
2538
+ }
2539
+
2540
+
2541
+ bool
2542
+ Value::empty() const
2543
+ {
2544
+ if ( isNull() || isArray() || isObject() )
2545
+ return size() == 0u;
2546
+ else
2547
+ return false;
2548
+ }
2549
+
2550
+
2551
+ bool
2552
+ Value::operator!() const
2553
+ {
2554
+ return isNull();
2555
+ }
2556
+
2557
+
2558
+ void
2559
+ Value::clear()
2560
+ {
2561
+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue );
2562
+
2563
+ switch ( type_ )
2564
+ {
2565
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
2566
+ case arrayValue:
2567
+ case objectValue:
2568
+ value_.map_->clear();
2569
+ break;
2570
+ #else
2571
+ case arrayValue:
2572
+ value_.array_->clear();
2573
+ break;
2574
+ case objectValue:
2575
+ value_.map_->clear();
2576
+ break;
2577
+ #endif
2578
+ default:
2579
+ break;
2580
+ }
2581
+ }
2582
+
2583
+ void
2584
+ Value::resize( ArrayIndex newSize )
2585
+ {
2586
+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
2587
+ if ( type_ == nullValue )
2588
+ *this = Value( arrayValue );
2589
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
2590
+ ArrayIndex oldSize = size();
2591
+ if ( newSize == 0 )
2592
+ clear();
2593
+ else if ( newSize > oldSize )
2594
+ (*this)[ newSize - 1 ];
2595
+ else
2596
+ {
2597
+ for ( ArrayIndex index = newSize; index < oldSize; ++index )
2598
+ {
2599
+ value_.map_->erase( index );
2600
+ }
2601
+ assert( size() == newSize );
2602
+ }
2603
+ #else
2604
+ value_.array_->resize( newSize );
2605
+ #endif
2606
+ }
2607
+
2608
+
2609
+ Value &
2610
+ Value::operator[]( ArrayIndex index )
2611
+ {
2612
+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
2613
+ if ( type_ == nullValue )
2614
+ *this = Value( arrayValue );
2615
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
2616
+ CZString key( index );
2617
+ ObjectValues::iterator it = value_.map_->lower_bound( key );
2618
+ if ( it != value_.map_->end() && (*it).first == key )
2619
+ return (*it).second;
2620
+
2621
+ ObjectValues::value_type defaultValue( key, null );
2622
+ it = value_.map_->insert( it, defaultValue );
2623
+ return (*it).second;
2624
+ #else
2625
+ return value_.array_->resolveReference( index );
2626
+ #endif
2627
+ }
2628
+
2629
+
2630
+ Value &
2631
+ Value::operator[]( int index )
2632
+ {
2633
+ JSON_ASSERT( index >= 0 );
2634
+ return (*this)[ ArrayIndex(index) ];
2635
+ }
2636
+
2637
+
2638
+ const Value &
2639
+ Value::operator[]( ArrayIndex index ) const
2640
+ {
2641
+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
2642
+ if ( type_ == nullValue )
2643
+ return null;
2644
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
2645
+ CZString key( index );
2646
+ ObjectValues::const_iterator it = value_.map_->find( key );
2647
+ if ( it == value_.map_->end() )
2648
+ return null;
2649
+ return (*it).second;
2650
+ #else
2651
+ Value *value = value_.array_->find( index );
2652
+ return value ? *value : null;
2653
+ #endif
2654
+ }
2655
+
2656
+
2657
+ const Value &
2658
+ Value::operator[]( int index ) const
2659
+ {
2660
+ JSON_ASSERT( index >= 0 );
2661
+ return (*this)[ ArrayIndex(index) ];
2662
+ }
2663
+
2664
+
2665
+ Value &
2666
+ Value::operator[]( const char *key )
2667
+ {
2668
+ return resolveReference( key, false );
2669
+ }
2670
+
2671
+
2672
+ Value &
2673
+ Value::resolveReference( const char *key,
2674
+ bool isStatic )
2675
+ {
2676
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
2677
+ if ( type_ == nullValue )
2678
+ *this = Value( objectValue );
2679
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
2680
+ CZString actualKey( key, isStatic ? CZString::noDuplication
2681
+ : CZString::duplicateOnCopy );
2682
+ ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
2683
+ if ( it != value_.map_->end() && (*it).first == actualKey )
2684
+ return (*it).second;
2685
+
2686
+ ObjectValues::value_type defaultValue( actualKey, null );
2687
+ it = value_.map_->insert( it, defaultValue );
2688
+ Value &value = (*it).second;
2689
+ return value;
2690
+ #else
2691
+ return value_.map_->resolveReference( key, isStatic );
2692
+ #endif
2693
+ }
2694
+
2695
+
2696
+ Value
2697
+ Value::get( ArrayIndex index,
2698
+ const Value &defaultValue ) const
2699
+ {
2700
+ const Value *value = &((*this)[index]);
2701
+ return value == &null ? defaultValue : *value;
2702
+ }
2703
+
2704
+
2705
+ bool
2706
+ Value::isValidIndex( ArrayIndex index ) const
2707
+ {
2708
+ return index < size();
2709
+ }
2710
+
2711
+
2712
+
2713
+ const Value &
2714
+ Value::operator[]( const char *key ) const
2715
+ {
2716
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
2717
+ if ( type_ == nullValue )
2718
+ return null;
2719
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
2720
+ CZString actualKey( key, CZString::noDuplication );
2721
+ ObjectValues::const_iterator it = value_.map_->find( actualKey );
2722
+ if ( it == value_.map_->end() )
2723
+ return null;
2724
+ return (*it).second;
2725
+ #else
2726
+ const Value *value = value_.map_->find( key );
2727
+ return value ? *value : null;
2728
+ #endif
2729
+ }
2730
+
2731
+
2732
+ Value &
2733
+ Value::operator[]( const std::string &key )
2734
+ {
2735
+ return (*this)[ key.c_str() ];
2736
+ }
2737
+
2738
+
2739
+ const Value &
2740
+ Value::operator[]( const std::string &key ) const
2741
+ {
2742
+ return (*this)[ key.c_str() ];
2743
+ }
2744
+
2745
+ Value &
2746
+ Value::operator[]( const StaticString &key )
2747
+ {
2748
+ return resolveReference( key, true );
2749
+ }
2750
+
2751
+
2752
+ # ifdef JSON_USE_CPPTL
2753
+ Value &
2754
+ Value::operator[]( const CppTL::ConstString &key )
2755
+ {
2756
+ return (*this)[ key.c_str() ];
2757
+ }
2758
+
2759
+
2760
+ const Value &
2761
+ Value::operator[]( const CppTL::ConstString &key ) const
2762
+ {
2763
+ return (*this)[ key.c_str() ];
2764
+ }
2765
+ # endif
2766
+
2767
+
2768
+ Value &
2769
+ Value::append( const Value &value )
2770
+ {
2771
+ return (*this)[size()] = value;
2772
+ }
2773
+
2774
+
2775
+ Value
2776
+ Value::get( const char *key,
2777
+ const Value &defaultValue ) const
2778
+ {
2779
+ const Value *value = &((*this)[key]);
2780
+ return value == &null ? defaultValue : *value;
2781
+ }
2782
+
2783
+
2784
+ Value
2785
+ Value::get( const std::string &key,
2786
+ const Value &defaultValue ) const
2787
+ {
2788
+ return get( key.c_str(), defaultValue );
2789
+ }
2790
+
2791
+ Value
2792
+ Value::removeMember( const char* key )
2793
+ {
2794
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
2795
+ if ( type_ == nullValue )
2796
+ return null;
2797
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
2798
+ CZString actualKey( key, CZString::noDuplication );
2799
+ ObjectValues::iterator it = value_.map_->find( actualKey );
2800
+ if ( it == value_.map_->end() )
2801
+ return null;
2802
+ Value old(it->second);
2803
+ value_.map_->erase(it);
2804
+ return old;
2805
+ #else
2806
+ Value *value = value_.map_->find( key );
2807
+ if (value){
2808
+ Value old(*value);
2809
+ value_.map_.remove( key );
2810
+ return old;
2811
+ } else {
2812
+ return null;
2813
+ }
2814
+ #endif
2815
+ }
2816
+
2817
+ Value
2818
+ Value::removeMember( const std::string &key )
2819
+ {
2820
+ return removeMember( key.c_str() );
2821
+ }
2822
+
2823
+ # ifdef JSON_USE_CPPTL
2824
+ Value
2825
+ Value::get( const CppTL::ConstString &key,
2826
+ const Value &defaultValue ) const
2827
+ {
2828
+ return get( key.c_str(), defaultValue );
2829
+ }
2830
+ # endif
2831
+
2832
+ bool
2833
+ Value::isMember( const char *key ) const
2834
+ {
2835
+ const Value *value = &((*this)[key]);
2836
+ return value != &null;
2837
+ }
2838
+
2839
+
2840
+ bool
2841
+ Value::isMember( const std::string &key ) const
2842
+ {
2843
+ return isMember( key.c_str() );
2844
+ }
2845
+
2846
+
2847
+ # ifdef JSON_USE_CPPTL
2848
+ bool
2849
+ Value::isMember( const CppTL::ConstString &key ) const
2850
+ {
2851
+ return isMember( key.c_str() );
2852
+ }
2853
+ #endif
2854
+
2855
+ Value::Members
2856
+ Value::getMemberNames() const
2857
+ {
2858
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
2859
+ if ( type_ == nullValue )
2860
+ return Value::Members();
2861
+ Members members;
2862
+ members.reserve( value_.map_->size() );
2863
+ #ifndef JSON_VALUE_USE_INTERNAL_MAP
2864
+ ObjectValues::const_iterator it = value_.map_->begin();
2865
+ ObjectValues::const_iterator itEnd = value_.map_->end();
2866
+ for ( ; it != itEnd; ++it )
2867
+ members.push_back( std::string( (*it).first.c_str() ) );
2868
+ #else
2869
+ ValueInternalMap::IteratorState it;
2870
+ ValueInternalMap::IteratorState itEnd;
2871
+ value_.map_->makeBeginIterator( it );
2872
+ value_.map_->makeEndIterator( itEnd );
2873
+ for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
2874
+ members.push_back( std::string( ValueInternalMap::key( it ) ) );
2875
+ #endif
2876
+ return members;
2877
+ }
2878
+ //
2879
+ //# ifdef JSON_USE_CPPTL
2880
+ //EnumMemberNames
2881
+ //Value::enumMemberNames() const
2882
+ //{
2883
+ // if ( type_ == objectValue )
2884
+ // {
2885
+ // return CppTL::Enum::any( CppTL::Enum::transform(
2886
+ // CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
2887
+ // MemberNamesTransform() ) );
2888
+ // }
2889
+ // return EnumMemberNames();
2890
+ //}
2891
+ //
2892
+ //
2893
+ //EnumValues
2894
+ //Value::enumValues() const
2895
+ //{
2896
+ // if ( type_ == objectValue || type_ == arrayValue )
2897
+ // return CppTL::Enum::anyValues( *(value_.map_),
2898
+ // CppTL::Type<const Value &>() );
2899
+ // return EnumValues();
2900
+ //}
2901
+ //
2902
+ //# endif
2903
+
2904
+
2905
+ bool
2906
+ Value::isNull() const
2907
+ {
2908
+ return type_ == nullValue;
2909
+ }
2910
+
2911
+
2912
+ bool
2913
+ Value::isBool() const
2914
+ {
2915
+ return type_ == booleanValue;
2916
+ }
2917
+
2918
+
2919
+ bool
2920
+ Value::isInt() const
2921
+ {
2922
+ return type_ == intValue;
2923
+ }
2924
+
2925
+
2926
+ bool
2927
+ Value::isUInt() const
2928
+ {
2929
+ return type_ == uintValue;
2930
+ }
2931
+
2932
+
2933
+ bool
2934
+ Value::isIntegral() const
2935
+ {
2936
+ return type_ == intValue
2937
+ || type_ == uintValue
2938
+ || type_ == booleanValue;
2939
+ }
2940
+
2941
+
2942
+ bool
2943
+ Value::isDouble() const
2944
+ {
2945
+ return type_ == realValue;
2946
+ }
2947
+
2948
+
2949
+ bool
2950
+ Value::isNumeric() const
2951
+ {
2952
+ return isIntegral() || isDouble();
2953
+ }
2954
+
2955
+
2956
+ bool
2957
+ Value::isString() const
2958
+ {
2959
+ return type_ == stringValue;
2960
+ }
2961
+
2962
+
2963
+ bool
2964
+ Value::isArray() const
2965
+ {
2966
+ return type_ == nullValue || type_ == arrayValue;
2967
+ }
2968
+
2969
+
2970
+ bool
2971
+ Value::isObject() const
2972
+ {
2973
+ return type_ == nullValue || type_ == objectValue;
2974
+ }
2975
+
2976
+
2977
+ void
2978
+ Value::setComment( const char *comment,
2979
+ CommentPlacement placement )
2980
+ {
2981
+ if ( !comments_ )
2982
+ comments_ = new CommentInfo[numberOfCommentPlacement];
2983
+ comments_[placement].setComment( comment );
2984
+ }
2985
+
2986
+
2987
+ void
2988
+ Value::setComment( const std::string &comment,
2989
+ CommentPlacement placement )
2990
+ {
2991
+ setComment( comment.c_str(), placement );
2992
+ }
2993
+
2994
+
2995
+ bool
2996
+ Value::hasComment( CommentPlacement placement ) const
2997
+ {
2998
+ return comments_ != 0 && comments_[placement].comment_ != 0;
2999
+ }
3000
+
3001
+ std::string
3002
+ Value::getComment( CommentPlacement placement ) const
3003
+ {
3004
+ if ( hasComment(placement) )
3005
+ return comments_[placement].comment_;
3006
+ return "";
3007
+ }
3008
+
3009
+
3010
+ std::string
3011
+ Value::toStyledString() const
3012
+ {
3013
+ StyledWriter writer;
3014
+ return writer.write( *this );
3015
+ }
3016
+
3017
+
3018
+ Value::const_iterator
3019
+ Value::begin() const
3020
+ {
3021
+ switch ( type_ )
3022
+ {
3023
+ #ifdef JSON_VALUE_USE_INTERNAL_MAP
3024
+ case arrayValue:
3025
+ if ( value_.array_ )
3026
+ {
3027
+ ValueInternalArray::IteratorState it;
3028
+ value_.array_->makeBeginIterator( it );
3029
+ return const_iterator( it );
3030
+ }
3031
+ break;
3032
+ case objectValue:
3033
+ if ( value_.map_ )
3034
+ {
3035
+ ValueInternalMap::IteratorState it;
3036
+ value_.map_->makeBeginIterator( it );
3037
+ return const_iterator( it );
3038
+ }
3039
+ break;
3040
+ #else
3041
+ case arrayValue:
3042
+ case objectValue:
3043
+ if ( value_.map_ )
3044
+ return const_iterator( value_.map_->begin() );
3045
+ break;
3046
+ #endif
3047
+ default:
3048
+ break;
3049
+ }
3050
+ return const_iterator();
3051
+ }
3052
+
3053
+ Value::const_iterator
3054
+ Value::end() const
3055
+ {
3056
+ switch ( type_ )
3057
+ {
3058
+ #ifdef JSON_VALUE_USE_INTERNAL_MAP
3059
+ case arrayValue:
3060
+ if ( value_.array_ )
3061
+ {
3062
+ ValueInternalArray::IteratorState it;
3063
+ value_.array_->makeEndIterator( it );
3064
+ return const_iterator( it );
3065
+ }
3066
+ break;
3067
+ case objectValue:
3068
+ if ( value_.map_ )
3069
+ {
3070
+ ValueInternalMap::IteratorState it;
3071
+ value_.map_->makeEndIterator( it );
3072
+ return const_iterator( it );
3073
+ }
3074
+ break;
3075
+ #else
3076
+ case arrayValue:
3077
+ case objectValue:
3078
+ if ( value_.map_ )
3079
+ return const_iterator( value_.map_->end() );
3080
+ break;
3081
+ #endif
3082
+ default:
3083
+ break;
3084
+ }
3085
+ return const_iterator();
3086
+ }
3087
+
3088
+
3089
+ Value::iterator
3090
+ Value::begin()
3091
+ {
3092
+ switch ( type_ )
3093
+ {
3094
+ #ifdef JSON_VALUE_USE_INTERNAL_MAP
3095
+ case arrayValue:
3096
+ if ( value_.array_ )
3097
+ {
3098
+ ValueInternalArray::IteratorState it;
3099
+ value_.array_->makeBeginIterator( it );
3100
+ return iterator( it );
3101
+ }
3102
+ break;
3103
+ case objectValue:
3104
+ if ( value_.map_ )
3105
+ {
3106
+ ValueInternalMap::IteratorState it;
3107
+ value_.map_->makeBeginIterator( it );
3108
+ return iterator( it );
3109
+ }
3110
+ break;
3111
+ #else
3112
+ case arrayValue:
3113
+ case objectValue:
3114
+ if ( value_.map_ )
3115
+ return iterator( value_.map_->begin() );
3116
+ break;
3117
+ #endif
3118
+ default:
3119
+ break;
3120
+ }
3121
+ return iterator();
3122
+ }
3123
+
3124
+ Value::iterator
3125
+ Value::end()
3126
+ {
3127
+ switch ( type_ )
3128
+ {
3129
+ #ifdef JSON_VALUE_USE_INTERNAL_MAP
3130
+ case arrayValue:
3131
+ if ( value_.array_ )
3132
+ {
3133
+ ValueInternalArray::IteratorState it;
3134
+ value_.array_->makeEndIterator( it );
3135
+ return iterator( it );
3136
+ }
3137
+ break;
3138
+ case objectValue:
3139
+ if ( value_.map_ )
3140
+ {
3141
+ ValueInternalMap::IteratorState it;
3142
+ value_.map_->makeEndIterator( it );
3143
+ return iterator( it );
3144
+ }
3145
+ break;
3146
+ #else
3147
+ case arrayValue:
3148
+ case objectValue:
3149
+ if ( value_.map_ )
3150
+ return iterator( value_.map_->end() );
3151
+ break;
3152
+ #endif
3153
+ default:
3154
+ break;
3155
+ }
3156
+ return iterator();
3157
+ }
3158
+
3159
+
3160
+ // class PathArgument
3161
+ // //////////////////////////////////////////////////////////////////
3162
+
3163
+ PathArgument::PathArgument()
3164
+ : kind_( kindNone )
3165
+ {
3166
+ }
3167
+
3168
+
3169
+ PathArgument::PathArgument( ArrayIndex index )
3170
+ : index_( index )
3171
+ , kind_( kindIndex )
3172
+ {
3173
+ }
3174
+
3175
+
3176
+ PathArgument::PathArgument( const char *key )
3177
+ : key_( key )
3178
+ , kind_( kindKey )
3179
+ {
3180
+ }
3181
+
3182
+
3183
+ PathArgument::PathArgument( const std::string &key )
3184
+ : key_( key.c_str() )
3185
+ , kind_( kindKey )
3186
+ {
3187
+ }
3188
+
3189
+ // class Path
3190
+ // //////////////////////////////////////////////////////////////////
3191
+
3192
+ Path::Path( const std::string &path,
3193
+ const PathArgument &a1,
3194
+ const PathArgument &a2,
3195
+ const PathArgument &a3,
3196
+ const PathArgument &a4,
3197
+ const PathArgument &a5 )
3198
+ {
3199
+ InArgs in;
3200
+ in.push_back( &a1 );
3201
+ in.push_back( &a2 );
3202
+ in.push_back( &a3 );
3203
+ in.push_back( &a4 );
3204
+ in.push_back( &a5 );
3205
+ makePath( path, in );
3206
+ }
3207
+
3208
+
3209
+ void
3210
+ Path::makePath( const std::string &path,
3211
+ const InArgs &in )
3212
+ {
3213
+ const char *current = path.c_str();
3214
+ const char *end = current + path.length();
3215
+ InArgs::const_iterator itInArg = in.begin();
3216
+ while ( current != end )
3217
+ {
3218
+ if ( *current == '[' )
3219
+ {
3220
+ ++current;
3221
+ if ( *current == '%' )
3222
+ addPathInArg( path, in, itInArg, PathArgument::kindIndex );
3223
+ else
3224
+ {
3225
+ ArrayIndex index = 0;
3226
+ for ( ; current != end && *current >= '0' && *current <= '9'; ++current )
3227
+ index = index * 10 + ArrayIndex(*current - '0');
3228
+ args_.push_back( index );
3229
+ }
3230
+ if ( current == end || *current++ != ']' )
3231
+ invalidPath( path, int(current - path.c_str()) );
3232
+ }
3233
+ else if ( *current == '%' )
3234
+ {
3235
+ addPathInArg( path, in, itInArg, PathArgument::kindKey );
3236
+ ++current;
3237
+ }
3238
+ else if ( *current == '.' )
3239
+ {
3240
+ ++current;
3241
+ }
3242
+ else
3243
+ {
3244
+ const char *beginName = current;
3245
+ while ( current != end && !strchr( "[.", *current ) )
3246
+ ++current;
3247
+ args_.push_back( std::string( beginName, current ) );
3248
+ }
3249
+ }
3250
+ }
3251
+
3252
+
3253
+ void
3254
+ Path::addPathInArg( const std::string &path,
3255
+ const InArgs &in,
3256
+ InArgs::const_iterator &itInArg,
3257
+ PathArgument::Kind kind )
3258
+ {
3259
+ if ( itInArg == in.end() )
3260
+ {
3261
+ // Error: missing argument %d
3262
+ }
3263
+ else if ( (*itInArg)->kind_ != kind )
3264
+ {
3265
+ // Error: bad argument type
3266
+ }
3267
+ else
3268
+ {
3269
+ args_.push_back( **itInArg );
3270
+ }
3271
+ }
3272
+
3273
+
3274
+ void
3275
+ Path::invalidPath( const std::string &path,
3276
+ int location )
3277
+ {
3278
+ // Error: invalid path.
3279
+ }
3280
+
3281
+
3282
+ const Value &
3283
+ Path::resolve( const Value &root ) const
3284
+ {
3285
+ const Value *node = &root;
3286
+ for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
3287
+ {
3288
+ const PathArgument &arg = *it;
3289
+ if ( arg.kind_ == PathArgument::kindIndex )
3290
+ {
3291
+ if ( !node->isArray() || node->isValidIndex( arg.index_ ) )
3292
+ {
3293
+ // Error: unable to resolve path (array value expected at position...
3294
+ }
3295
+ node = &((*node)[arg.index_]);
3296
+ }
3297
+ else if ( arg.kind_ == PathArgument::kindKey )
3298
+ {
3299
+ if ( !node->isObject() )
3300
+ {
3301
+ // Error: unable to resolve path (object value expected at position...)
3302
+ }
3303
+ node = &((*node)[arg.key_]);
3304
+ if ( node == &Value::null )
3305
+ {
3306
+ // Error: unable to resolve path (object has no member named '' at position...)
3307
+ }
3308
+ }
3309
+ }
3310
+ return *node;
3311
+ }
3312
+
3313
+
3314
+ Value
3315
+ Path::resolve( const Value &root,
3316
+ const Value &defaultValue ) const
3317
+ {
3318
+ const Value *node = &root;
3319
+ for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
3320
+ {
3321
+ const PathArgument &arg = *it;
3322
+ if ( arg.kind_ == PathArgument::kindIndex )
3323
+ {
3324
+ if ( !node->isArray() || node->isValidIndex( arg.index_ ) )
3325
+ return defaultValue;
3326
+ node = &((*node)[arg.index_]);
3327
+ }
3328
+ else if ( arg.kind_ == PathArgument::kindKey )
3329
+ {
3330
+ if ( !node->isObject() )
3331
+ return defaultValue;
3332
+ node = &((*node)[arg.key_]);
3333
+ if ( node == &Value::null )
3334
+ return defaultValue;
3335
+ }
3336
+ }
3337
+ return *node;
3338
+ }
3339
+
3340
+
3341
+ Value &
3342
+ Path::make( Value &root ) const
3343
+ {
3344
+ Value *node = &root;
3345
+ for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
3346
+ {
3347
+ const PathArgument &arg = *it;
3348
+ if ( arg.kind_ == PathArgument::kindIndex )
3349
+ {
3350
+ if ( !node->isArray() )
3351
+ {
3352
+ // Error: node is not an array at position ...
3353
+ }
3354
+ node = &((*node)[arg.index_]);
3355
+ }
3356
+ else if ( arg.kind_ == PathArgument::kindKey )
3357
+ {
3358
+ if ( !node->isObject() )
3359
+ {
3360
+ // Error: node is not an object at position...
3361
+ }
3362
+ node = &((*node)[arg.key_]);
3363
+ }
3364
+ }
3365
+ return *node;
3366
+ }
3367
+
3368
+
3369
+ } // namespace Json
3370
+
3371
+ // //////////////////////////////////////////////////////////////////////
3372
+ // End of content of file: src/lib_json/json_value.cpp
3373
+ // //////////////////////////////////////////////////////////////////////
3374
+
3375
+
3376
+
3377
+
3378
+
3379
+
3380
+ // //////////////////////////////////////////////////////////////////////
3381
+ // Beginning of content of file: src/lib_json/json_writer.cpp
3382
+ // //////////////////////////////////////////////////////////////////////
3383
+
3384
+ // Copyright 2007-2010 Baptiste Lepilleur
3385
+ // Distributed under MIT license, or public domain if desired and
3386
+ // recognized in your jurisdiction.
3387
+ // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
3388
+
3389
+ #if !defined(JSON_IS_AMALGAMATION)
3390
+ # include <json/writer.h>
3391
+ # include "json_tool.h"
3392
+ #endif // if !defined(JSON_IS_AMALGAMATION)
3393
+ #include <utility>
3394
+ #include <assert.h>
3395
+ #include <stdio.h>
3396
+ #include <string.h>
3397
+ #include <iostream>
3398
+ #include <sstream>
3399
+ #include <iomanip>
3400
+
3401
+ #if _MSC_VER >= 1400 // VC++ 8.0
3402
+ #pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
3403
+ #endif
3404
+
3405
+ namespace Json {
3406
+
3407
+ static bool containsControlCharacter( const char* str )
3408
+ {
3409
+ while ( *str )
3410
+ {
3411
+ if ( isControlCharacter( *(str++) ) )
3412
+ return true;
3413
+ }
3414
+ return false;
3415
+ }
3416
+
3417
+
3418
+ std::string valueToString( LargestInt value )
3419
+ {
3420
+ UIntToStringBuffer buffer;
3421
+ char *current = buffer + sizeof(buffer);
3422
+ bool isNegative = value < 0;
3423
+ if ( isNegative )
3424
+ value = -value;
3425
+ uintToString( LargestUInt(value), current );
3426
+ if ( isNegative )
3427
+ *--current = '-';
3428
+ assert( current >= buffer );
3429
+ return current;
3430
+ }
3431
+
3432
+
3433
+ std::string valueToString( LargestUInt value )
3434
+ {
3435
+ UIntToStringBuffer buffer;
3436
+ char *current = buffer + sizeof(buffer);
3437
+ uintToString( value, current );
3438
+ assert( current >= buffer );
3439
+ return current;
3440
+ }
3441
+
3442
+ #if defined(JSON_HAS_INT64)
3443
+
3444
+ std::string valueToString( Int value )
3445
+ {
3446
+ return valueToString( LargestInt(value) );
3447
+ }
3448
+
3449
+
3450
+ std::string valueToString( UInt value )
3451
+ {
3452
+ return valueToString( LargestUInt(value) );
3453
+ }
3454
+
3455
+ #endif // # if defined(JSON_HAS_INT64)
3456
+
3457
+
3458
+ std::string valueToString( double value )
3459
+ {
3460
+ char buffer[32];
3461
+ #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
3462
+ sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
3463
+ #else
3464
+ sprintf(buffer, "%#.16g", value);
3465
+ #endif
3466
+ char* ch = buffer + strlen(buffer) - 1;
3467
+ if (*ch != '0') return buffer; // nothing to truncate, so save time
3468
+ while(ch > buffer && *ch == '0'){
3469
+ --ch;
3470
+ }
3471
+ char* last_nonzero = ch;
3472
+ while(ch >= buffer){
3473
+ switch(*ch){
3474
+ case '0':
3475
+ case '1':
3476
+ case '2':
3477
+ case '3':
3478
+ case '4':
3479
+ case '5':
3480
+ case '6':
3481
+ case '7':
3482
+ case '8':
3483
+ case '9':
3484
+ --ch;
3485
+ continue;
3486
+ case '.':
3487
+ // Truncate zeroes to save bytes in output, but keep one.
3488
+ *(last_nonzero+2) = '\0';
3489
+ return buffer;
3490
+ default:
3491
+ return buffer;
3492
+ }
3493
+ }
3494
+ return buffer;
3495
+ }
3496
+
3497
+
3498
+ std::string valueToString( bool value )
3499
+ {
3500
+ return value ? "true" : "false";
3501
+ }
3502
+
3503
+ std::string valueToQuotedString( const char *value )
3504
+ {
3505
+ // Not sure how to handle unicode...
3506
+ if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
3507
+ return std::string("\"") + value + "\"";
3508
+ // We have to walk value and escape any special characters.
3509
+ // Appending to std::string is not efficient, but this should be rare.
3510
+ // (Note: forward slashes are *not* rare, but I am not escaping them.)
3511
+ std::string::size_type maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
3512
+ std::string result;
3513
+ result.reserve(maxsize); // to avoid lots of mallocs
3514
+ result += "\"";
3515
+ for (const char* c=value; *c != 0; ++c)
3516
+ {
3517
+ switch(*c)
3518
+ {
3519
+ case '\"':
3520
+ result += "\\\"";
3521
+ break;
3522
+ case '\\':
3523
+ result += "\\\\";
3524
+ break;
3525
+ case '\b':
3526
+ result += "\\b";
3527
+ break;
3528
+ case '\f':
3529
+ result += "\\f";
3530
+ break;
3531
+ case '\n':
3532
+ result += "\\n";
3533
+ break;
3534
+ case '\r':
3535
+ result += "\\r";
3536
+ break;
3537
+ case '\t':
3538
+ result += "\\t";
3539
+ break;
3540
+ //case '/':
3541
+ // Even though \/ is considered a legal escape in JSON, a bare
3542
+ // slash is also legal, so I see no reason to escape it.
3543
+ // (I hope I am not misunderstanding something.
3544
+ // blep notes: actually escaping \/ may be useful in javascript to avoid </
3545
+ // sequence.
3546
+ // Should add a flag to allow this compatibility mode and prevent this
3547
+ // sequence from occurring.
3548
+ default:
3549
+ if ( isControlCharacter( *c ) )
3550
+ {
3551
+ std::ostringstream oss;
3552
+ oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
3553
+ result += oss.str();
3554
+ }
3555
+ else
3556
+ {
3557
+ result += *c;
3558
+ }
3559
+ break;
3560
+ }
3561
+ }
3562
+ result += "\"";
3563
+ return result;
3564
+ }
3565
+
3566
+ // Class Writer
3567
+ // //////////////////////////////////////////////////////////////////
3568
+ Writer::~Writer()
3569
+ {
3570
+ }
3571
+
3572
+
3573
+ // Class FastWriter
3574
+ // //////////////////////////////////////////////////////////////////
3575
+
3576
+ FastWriter::FastWriter()
3577
+ : yamlCompatiblityEnabled_( false )
3578
+ {
3579
+ }
3580
+
3581
+
3582
+ void
3583
+ FastWriter::enableYAMLCompatibility()
3584
+ {
3585
+ yamlCompatiblityEnabled_ = true;
3586
+ }
3587
+
3588
+
3589
+ std::string
3590
+ FastWriter::write( const Value &root )
3591
+ {
3592
+ document_ = "";
3593
+ writeValue( root );
3594
+ document_ += "\n";
3595
+ return document_;
3596
+ }
3597
+
3598
+
3599
+ void
3600
+ FastWriter::writeValue( const Value &value )
3601
+ {
3602
+ switch ( value.type() )
3603
+ {
3604
+ case nullValue:
3605
+ document_ += "null";
3606
+ break;
3607
+ case intValue:
3608
+ document_ += valueToString( value.asLargestInt() );
3609
+ break;
3610
+ case uintValue:
3611
+ document_ += valueToString( value.asLargestUInt() );
3612
+ break;
3613
+ case realValue:
3614
+ document_ += valueToString( value.asDouble() );
3615
+ break;
3616
+ case stringValue:
3617
+ document_ += valueToQuotedString( value.asCString() );
3618
+ break;
3619
+ case booleanValue:
3620
+ document_ += valueToString( value.asBool() );
3621
+ break;
3622
+ case arrayValue:
3623
+ {
3624
+ document_ += "[";
3625
+ int size = value.size();
3626
+ for ( int index =0; index < size; ++index )
3627
+ {
3628
+ if ( index > 0 )
3629
+ document_ += ",";
3630
+ writeValue( value[index] );
3631
+ }
3632
+ document_ += "]";
3633
+ }
3634
+ break;
3635
+ case objectValue:
3636
+ {
3637
+ Value::Members members( value.getMemberNames() );
3638
+ document_ += "{";
3639
+ for ( Value::Members::iterator it = members.begin();
3640
+ it != members.end();
3641
+ ++it )
3642
+ {
3643
+ const std::string &name = *it;
3644
+ if ( it != members.begin() )
3645
+ document_ += ",";
3646
+ document_ += valueToQuotedString( name.c_str() );
3647
+ document_ += yamlCompatiblityEnabled_ ? ": "
3648
+ : ":";
3649
+ writeValue( value[name] );
3650
+ }
3651
+ document_ += "}";
3652
+ }
3653
+ break;
3654
+ }
3655
+ }
3656
+
3657
+
3658
+ // Class StyledWriter
3659
+ // //////////////////////////////////////////////////////////////////
3660
+
3661
+ StyledWriter::StyledWriter()
3662
+ : rightMargin_( 74 )
3663
+ , indentSize_( 3 )
3664
+ {
3665
+ }
3666
+
3667
+
3668
+ std::string
3669
+ StyledWriter::write( const Value &root )
3670
+ {
3671
+ document_ = "";
3672
+ addChildValues_ = false;
3673
+ indentString_ = "";
3674
+ writeCommentBeforeValue( root );
3675
+ writeValue( root );
3676
+ writeCommentAfterValueOnSameLine( root );
3677
+ document_ += "\n";
3678
+ return document_;
3679
+ }
3680
+
3681
+
3682
+ void
3683
+ StyledWriter::writeValue( const Value &value )
3684
+ {
3685
+ switch ( value.type() )
3686
+ {
3687
+ case nullValue:
3688
+ pushValue( "null" );
3689
+ break;
3690
+ case intValue:
3691
+ pushValue( valueToString( value.asLargestInt() ) );
3692
+ break;
3693
+ case uintValue:
3694
+ pushValue( valueToString( value.asLargestUInt() ) );
3695
+ break;
3696
+ case realValue:
3697
+ pushValue( valueToString( value.asDouble() ) );
3698
+ break;
3699
+ case stringValue:
3700
+ pushValue( valueToQuotedString( value.asCString() ) );
3701
+ break;
3702
+ case booleanValue:
3703
+ pushValue( valueToString( value.asBool() ) );
3704
+ break;
3705
+ case arrayValue:
3706
+ writeArrayValue( value);
3707
+ break;
3708
+ case objectValue:
3709
+ {
3710
+ Value::Members members( value.getMemberNames() );
3711
+ if ( members.empty() )
3712
+ pushValue( "{}" );
3713
+ else
3714
+ {
3715
+ writeWithIndent( "{" );
3716
+ indent();
3717
+ Value::Members::iterator it = members.begin();
3718
+ for (;;)
3719
+ {
3720
+ const std::string &name = *it;
3721
+ const Value &childValue = value[name];
3722
+ writeCommentBeforeValue( childValue );
3723
+ writeWithIndent( valueToQuotedString( name.c_str() ) );
3724
+ document_ += " : ";
3725
+ writeValue( childValue );
3726
+ if ( ++it == members.end() )
3727
+ {
3728
+ writeCommentAfterValueOnSameLine( childValue );
3729
+ break;
3730
+ }
3731
+ document_ += ",";
3732
+ writeCommentAfterValueOnSameLine( childValue );
3733
+ }
3734
+ unindent();
3735
+ writeWithIndent( "}" );
3736
+ }
3737
+ }
3738
+ break;
3739
+ }
3740
+ }
3741
+
3742
+
3743
+ void
3744
+ StyledWriter::writeArrayValue( const Value &value )
3745
+ {
3746
+ unsigned size = value.size();
3747
+ if ( size == 0 )
3748
+ pushValue( "[]" );
3749
+ else
3750
+ {
3751
+ bool isArrayMultiLine = isMultineArray( value );
3752
+ if ( isArrayMultiLine )
3753
+ {
3754
+ writeWithIndent( "[" );
3755
+ indent();
3756
+ bool hasChildValue = !childValues_.empty();
3757
+ unsigned index =0;
3758
+ for (;;)
3759
+ {
3760
+ const Value &childValue = value[index];
3761
+ writeCommentBeforeValue( childValue );
3762
+ if ( hasChildValue )
3763
+ writeWithIndent( childValues_[index] );
3764
+ else
3765
+ {
3766
+ writeIndent();
3767
+ writeValue( childValue );
3768
+ }
3769
+ if ( ++index == size )
3770
+ {
3771
+ writeCommentAfterValueOnSameLine( childValue );
3772
+ break;
3773
+ }
3774
+ document_ += ",";
3775
+ writeCommentAfterValueOnSameLine( childValue );
3776
+ }
3777
+ unindent();
3778
+ writeWithIndent( "]" );
3779
+ }
3780
+ else // output on a single line
3781
+ {
3782
+ assert( childValues_.size() == size );
3783
+ document_ += "[ ";
3784
+ for ( unsigned index =0; index < size; ++index )
3785
+ {
3786
+ if ( index > 0 )
3787
+ document_ += ", ";
3788
+ document_ += childValues_[index];
3789
+ }
3790
+ document_ += " ]";
3791
+ }
3792
+ }
3793
+ }
3794
+
3795
+
3796
+ bool
3797
+ StyledWriter::isMultineArray( const Value &value )
3798
+ {
3799
+ int size = value.size();
3800
+ bool isMultiLine = size*3 >= rightMargin_ ;
3801
+ childValues_.clear();
3802
+ for ( int index =0; index < size && !isMultiLine; ++index )
3803
+ {
3804
+ const Value &childValue = value[index];
3805
+ isMultiLine = isMultiLine ||
3806
+ ( (childValue.isArray() || childValue.isObject()) &&
3807
+ childValue.size() > 0 );
3808
+ }
3809
+ if ( !isMultiLine ) // check if line length > max line length
3810
+ {
3811
+ childValues_.reserve( size );
3812
+ addChildValues_ = true;
3813
+ int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
3814
+ for ( int index =0; index < size && !isMultiLine; ++index )
3815
+ {
3816
+ writeValue( value[index] );
3817
+ lineLength += int( childValues_[index].length() );
3818
+ isMultiLine = isMultiLine && hasCommentForValue( value[index] );
3819
+ }
3820
+ addChildValues_ = false;
3821
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
3822
+ }
3823
+ return isMultiLine;
3824
+ }
3825
+
3826
+
3827
+ void
3828
+ StyledWriter::pushValue( const std::string &value )
3829
+ {
3830
+ if ( addChildValues_ )
3831
+ childValues_.push_back( value );
3832
+ else
3833
+ document_ += value;
3834
+ }
3835
+
3836
+
3837
+ void
3838
+ StyledWriter::writeIndent()
3839
+ {
3840
+ if ( !document_.empty() )
3841
+ {
3842
+ char last = document_[document_.length()-1];
3843
+ if ( last == ' ' ) // already indented
3844
+ return;
3845
+ if ( last != '\n' ) // Comments may add new-line
3846
+ document_ += '\n';
3847
+ }
3848
+ document_ += indentString_;
3849
+ }
3850
+
3851
+
3852
+ void
3853
+ StyledWriter::writeWithIndent( const std::string &value )
3854
+ {
3855
+ writeIndent();
3856
+ document_ += value;
3857
+ }
3858
+
3859
+
3860
+ void
3861
+ StyledWriter::indent()
3862
+ {
3863
+ indentString_ += std::string( indentSize_, ' ' );
3864
+ }
3865
+
3866
+
3867
+ void
3868
+ StyledWriter::unindent()
3869
+ {
3870
+ assert( int(indentString_.size()) >= indentSize_ );
3871
+ indentString_.resize( indentString_.size() - indentSize_ );
3872
+ }
3873
+
3874
+
3875
+ void
3876
+ StyledWriter::writeCommentBeforeValue( const Value &root )
3877
+ {
3878
+ if ( !root.hasComment( commentBefore ) )
3879
+ return;
3880
+ document_ += normalizeEOL( root.getComment( commentBefore ) );
3881
+ document_ += "\n";
3882
+ }
3883
+
3884
+
3885
+ void
3886
+ StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
3887
+ {
3888
+ if ( root.hasComment( commentAfterOnSameLine ) )
3889
+ document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
3890
+
3891
+ if ( root.hasComment( commentAfter ) )
3892
+ {
3893
+ document_ += "\n";
3894
+ document_ += normalizeEOL( root.getComment( commentAfter ) );
3895
+ document_ += "\n";
3896
+ }
3897
+ }
3898
+
3899
+
3900
+ bool
3901
+ StyledWriter::hasCommentForValue( const Value &value )
3902
+ {
3903
+ return value.hasComment( commentBefore )
3904
+ || value.hasComment( commentAfterOnSameLine )
3905
+ || value.hasComment( commentAfter );
3906
+ }
3907
+
3908
+
3909
+ std::string
3910
+ StyledWriter::normalizeEOL( const std::string &text )
3911
+ {
3912
+ std::string normalized;
3913
+ normalized.reserve( text.length() );
3914
+ const char *begin = text.c_str();
3915
+ const char *end = begin + text.length();
3916
+ const char *current = begin;
3917
+ while ( current != end )
3918
+ {
3919
+ char c = *current++;
3920
+ if ( c == '\r' ) // mac or dos EOL
3921
+ {
3922
+ if ( *current == '\n' ) // convert dos EOL
3923
+ ++current;
3924
+ normalized += '\n';
3925
+ }
3926
+ else // handle unix EOL & other char
3927
+ normalized += c;
3928
+ }
3929
+ return normalized;
3930
+ }
3931
+
3932
+
3933
+ // Class StyledStreamWriter
3934
+ // //////////////////////////////////////////////////////////////////
3935
+
3936
+ StyledStreamWriter::StyledStreamWriter( std::string indentation )
3937
+ : document_(NULL)
3938
+ , rightMargin_( 74 )
3939
+ , indentation_( indentation )
3940
+ {
3941
+ }
3942
+
3943
+
3944
+ void
3945
+ StyledStreamWriter::write( std::ostream &out, const Value &root )
3946
+ {
3947
+ document_ = &out;
3948
+ addChildValues_ = false;
3949
+ indentString_ = "";
3950
+ writeCommentBeforeValue( root );
3951
+ writeValue( root );
3952
+ writeCommentAfterValueOnSameLine( root );
3953
+ *document_ << "\n";
3954
+ document_ = NULL; // Forget the stream, for safety.
3955
+ }
3956
+
3957
+
3958
+ void
3959
+ StyledStreamWriter::writeValue( const Value &value )
3960
+ {
3961
+ switch ( value.type() )
3962
+ {
3963
+ case nullValue:
3964
+ pushValue( "null" );
3965
+ break;
3966
+ case intValue:
3967
+ pushValue( valueToString( value.asLargestInt() ) );
3968
+ break;
3969
+ case uintValue:
3970
+ pushValue( valueToString( value.asLargestUInt() ) );
3971
+ break;
3972
+ case realValue:
3973
+ pushValue( valueToString( value.asDouble() ) );
3974
+ break;
3975
+ case stringValue:
3976
+ pushValue( valueToQuotedString( value.asCString() ) );
3977
+ break;
3978
+ case booleanValue:
3979
+ pushValue( valueToString( value.asBool() ) );
3980
+ break;
3981
+ case arrayValue:
3982
+ writeArrayValue( value);
3983
+ break;
3984
+ case objectValue:
3985
+ {
3986
+ Value::Members members( value.getMemberNames() );
3987
+ if ( members.empty() )
3988
+ pushValue( "{}" );
3989
+ else
3990
+ {
3991
+ writeWithIndent( "{" );
3992
+ indent();
3993
+ Value::Members::iterator it = members.begin();
3994
+ for (;;)
3995
+ {
3996
+ const std::string &name = *it;
3997
+ const Value &childValue = value[name];
3998
+ writeCommentBeforeValue( childValue );
3999
+ writeWithIndent( valueToQuotedString( name.c_str() ) );
4000
+ *document_ << " : ";
4001
+ writeValue( childValue );
4002
+ if ( ++it == members.end() )
4003
+ {
4004
+ writeCommentAfterValueOnSameLine( childValue );
4005
+ break;
4006
+ }
4007
+ *document_ << ",";
4008
+ writeCommentAfterValueOnSameLine( childValue );
4009
+ }
4010
+ unindent();
4011
+ writeWithIndent( "}" );
4012
+ }
4013
+ }
4014
+ break;
4015
+ }
4016
+ }
4017
+
4018
+
4019
+ void
4020
+ StyledStreamWriter::writeArrayValue( const Value &value )
4021
+ {
4022
+ unsigned size = value.size();
4023
+ if ( size == 0 )
4024
+ pushValue( "[]" );
4025
+ else
4026
+ {
4027
+ bool isArrayMultiLine = isMultineArray( value );
4028
+ if ( isArrayMultiLine )
4029
+ {
4030
+ writeWithIndent( "[" );
4031
+ indent();
4032
+ bool hasChildValue = !childValues_.empty();
4033
+ unsigned index =0;
4034
+ for (;;)
4035
+ {
4036
+ const Value &childValue = value[index];
4037
+ writeCommentBeforeValue( childValue );
4038
+ if ( hasChildValue )
4039
+ writeWithIndent( childValues_[index] );
4040
+ else
4041
+ {
4042
+ writeIndent();
4043
+ writeValue( childValue );
4044
+ }
4045
+ if ( ++index == size )
4046
+ {
4047
+ writeCommentAfterValueOnSameLine( childValue );
4048
+ break;
4049
+ }
4050
+ *document_ << ",";
4051
+ writeCommentAfterValueOnSameLine( childValue );
4052
+ }
4053
+ unindent();
4054
+ writeWithIndent( "]" );
4055
+ }
4056
+ else // output on a single line
4057
+ {
4058
+ assert( childValues_.size() == size );
4059
+ *document_ << "[ ";
4060
+ for ( unsigned index =0; index < size; ++index )
4061
+ {
4062
+ if ( index > 0 )
4063
+ *document_ << ", ";
4064
+ *document_ << childValues_[index];
4065
+ }
4066
+ *document_ << " ]";
4067
+ }
4068
+ }
4069
+ }
4070
+
4071
+
4072
+ bool
4073
+ StyledStreamWriter::isMultineArray( const Value &value )
4074
+ {
4075
+ int size = value.size();
4076
+ bool isMultiLine = size*3 >= rightMargin_ ;
4077
+ childValues_.clear();
4078
+ for ( int index =0; index < size && !isMultiLine; ++index )
4079
+ {
4080
+ const Value &childValue = value[index];
4081
+ isMultiLine = isMultiLine ||
4082
+ ( (childValue.isArray() || childValue.isObject()) &&
4083
+ childValue.size() > 0 );
4084
+ }
4085
+ if ( !isMultiLine ) // check if line length > max line length
4086
+ {
4087
+ childValues_.reserve( size );
4088
+ addChildValues_ = true;
4089
+ int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
4090
+ for ( int index =0; index < size && !isMultiLine; ++index )
4091
+ {
4092
+ writeValue( value[index] );
4093
+ lineLength += int( childValues_[index].length() );
4094
+ isMultiLine = isMultiLine && hasCommentForValue( value[index] );
4095
+ }
4096
+ addChildValues_ = false;
4097
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
4098
+ }
4099
+ return isMultiLine;
4100
+ }
4101
+
4102
+
4103
+ void
4104
+ StyledStreamWriter::pushValue( const std::string &value )
4105
+ {
4106
+ if ( addChildValues_ )
4107
+ childValues_.push_back( value );
4108
+ else
4109
+ *document_ << value;
4110
+ }
4111
+
4112
+
4113
+ void
4114
+ StyledStreamWriter::writeIndent()
4115
+ {
4116
+ /*
4117
+ Some comments in this method would have been nice. ;-)
4118
+
4119
+ if ( !document_.empty() )
4120
+ {
4121
+ char last = document_[document_.length()-1];
4122
+ if ( last == ' ' ) // already indented
4123
+ return;
4124
+ if ( last != '\n' ) // Comments may add new-line
4125
+ *document_ << '\n';
4126
+ }
4127
+ */
4128
+ *document_ << '\n' << indentString_;
4129
+ }
4130
+
4131
+
4132
+ void
4133
+ StyledStreamWriter::writeWithIndent( const std::string &value )
4134
+ {
4135
+ writeIndent();
4136
+ *document_ << value;
4137
+ }
4138
+
4139
+
4140
+ void
4141
+ StyledStreamWriter::indent()
4142
+ {
4143
+ indentString_ += indentation_;
4144
+ }
4145
+
4146
+
4147
+ void
4148
+ StyledStreamWriter::unindent()
4149
+ {
4150
+ assert( indentString_.size() >= indentation_.size() );
4151
+ indentString_.resize( indentString_.size() - indentation_.size() );
4152
+ }
4153
+
4154
+
4155
+ void
4156
+ StyledStreamWriter::writeCommentBeforeValue( const Value &root )
4157
+ {
4158
+ if ( !root.hasComment( commentBefore ) )
4159
+ return;
4160
+ *document_ << normalizeEOL( root.getComment( commentBefore ) );
4161
+ *document_ << "\n";
4162
+ }
4163
+
4164
+
4165
+ void
4166
+ StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
4167
+ {
4168
+ if ( root.hasComment( commentAfterOnSameLine ) )
4169
+ *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
4170
+
4171
+ if ( root.hasComment( commentAfter ) )
4172
+ {
4173
+ *document_ << "\n";
4174
+ *document_ << normalizeEOL( root.getComment( commentAfter ) );
4175
+ *document_ << "\n";
4176
+ }
4177
+ }
4178
+
4179
+
4180
+ bool
4181
+ StyledStreamWriter::hasCommentForValue( const Value &value )
4182
+ {
4183
+ return value.hasComment( commentBefore )
4184
+ || value.hasComment( commentAfterOnSameLine )
4185
+ || value.hasComment( commentAfter );
4186
+ }
4187
+
4188
+
4189
+ std::string
4190
+ StyledStreamWriter::normalizeEOL( const std::string &text )
4191
+ {
4192
+ std::string normalized;
4193
+ normalized.reserve( text.length() );
4194
+ const char *begin = text.c_str();
4195
+ const char *end = begin + text.length();
4196
+ const char *current = begin;
4197
+ while ( current != end )
4198
+ {
4199
+ char c = *current++;
4200
+ if ( c == '\r' ) // mac or dos EOL
4201
+ {
4202
+ if ( *current == '\n' ) // convert dos EOL
4203
+ ++current;
4204
+ normalized += '\n';
4205
+ }
4206
+ else // handle unix EOL & other char
4207
+ normalized += c;
4208
+ }
4209
+ return normalized;
4210
+ }
4211
+
4212
+
4213
+ std::ostream& operator<<( std::ostream &sout, const Value &root )
4214
+ {
4215
+ Json::StyledStreamWriter writer;
4216
+ writer.write(sout, root);
4217
+ return sout;
4218
+ }
4219
+
4220
+
4221
+ } // namespace Json
4222
+
4223
+ // //////////////////////////////////////////////////////////////////////
4224
+ // End of content of file: src/lib_json/json_writer.cpp
4225
+ // //////////////////////////////////////////////////////////////////////
4226
+
4227
+
4228
+
4229
+
4230
+