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.
- data/DEVELOPERS.TXT +4 -10
- data/NEWS +19 -27
- data/Rakefile +20 -19
- data/bin/passenger +3 -2
- data/bin/passenger-config +35 -5
- data/bin/passenger-install-apache2-module +12 -12
- data/bin/passenger-install-nginx-module +55 -38
- data/bin/passenger-memory-stats +3 -1
- data/bin/passenger-status +7 -35
- data/build/agents.rb +107 -21
- data/build/apache2.rb +11 -46
- data/build/basics.rb +61 -9
- data/build/common_library.rb +59 -142
- data/build/cxx_tests.rb +111 -110
- data/build/documentation.rb +33 -0
- data/build/misc.rb +30 -12
- data/build/nginx.rb +10 -39
- data/build/oxt_tests.rb +1 -0
- data/build/ruby_extension.rb +1 -5
- data/build/test_basics.rb +3 -2
- data/dev/copy_boost_headers.rb +2 -1
- data/doc/Architectural overview.html +49 -90
- data/doc/DebuggingAndStressTesting.txt.md +49 -0
- data/doc/Packaging.txt.md +254 -0
- data/doc/Security of user switching support.html +35 -66
- data/doc/Users guide Apache.html +588 -758
- data/doc/Users guide Apache.idmap.txt +253 -136
- data/doc/Users guide Apache.txt +154 -109
- data/doc/Users guide Nginx.html +544 -660
- data/doc/Users guide Nginx.idmap.txt +179 -91
- data/doc/Users guide Nginx.txt +192 -118
- data/doc/Users guide Standalone.html +65 -48
- data/doc/Users guide Standalone.idmap.txt +10 -2
- data/doc/Users guide Standalone.txt +4 -0
- data/doc/images/glyphicons-halflings-white.png +0 -0
- data/doc/images/glyphicons-halflings.png +0 -0
- data/doc/images/phusion_banner_small.png +0 -0
- data/doc/images/{smart-lv2.png → smart.png} +0 -0
- data/doc/images/{smart-lv2.svg → smart.svg} +0 -0
- data/doc/templates/bootstrap.min.css +397 -0
- data/doc/templates/markdown.html.erb +117 -0
- data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +2 -1
- data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +26 -48
- data/doc/users_guide_snippets/passenger_spawn_method.txt +18 -30
- data/doc/users_guide_snippets/support_information.txt +30 -0
- data/ext/apache2/Bucket.cpp +9 -26
- data/ext/apache2/Bucket.h +13 -10
- data/ext/apache2/Configuration.cpp +70 -58
- data/ext/apache2/Configuration.hpp +19 -47
- data/ext/apache2/DirectoryMapper.h +7 -7
- data/ext/apache2/Hooks.cpp +150 -313
- data/ext/boost/algorithm/string/detail/case_conv.hpp +4 -2
- data/ext/boost/algorithm/string/detail/find_format.hpp +20 -20
- data/ext/boost/algorithm/string/detail/find_format_all.hpp +23 -23
- data/ext/boost/algorithm/string/detail/find_format_store.hpp +2 -2
- data/ext/boost/algorithm/string/detail/formatter.hpp +25 -0
- data/ext/boost/algorithm/string/formatter.hpp +20 -3
- data/ext/boost/assert.hpp +85 -4
- data/ext/boost/bind/bind.hpp +1 -1
- data/ext/boost/concept/detail/backward_compatibility.hpp +1 -1
- data/ext/boost/concept_check.hpp +140 -64
- data/ext/boost/config.hpp +1 -1
- data/ext/boost/config/auto_link.hpp +8 -6
- data/ext/boost/config/compiler/borland.hpp +12 -2
- data/ext/boost/config/compiler/clang.hpp +89 -30
- data/ext/boost/config/compiler/codegear.hpp +3 -2
- data/ext/boost/config/compiler/common_edg.hpp +7 -5
- data/ext/boost/config/compiler/cray.hpp +61 -0
- data/ext/boost/config/compiler/digitalmars.hpp +9 -1
- data/ext/boost/config/compiler/gcc.hpp +33 -24
- data/ext/boost/config/compiler/gcc_xml.hpp +4 -0
- data/ext/boost/config/compiler/hp_acc.hpp +12 -1
- data/ext/boost/config/compiler/intel.hpp +78 -4
- data/ext/boost/config/compiler/metrowerks.hpp +4 -1
- data/ext/boost/config/compiler/mpw.hpp +4 -1
- data/ext/boost/config/compiler/nvcc.hpp +8 -66
- data/ext/boost/config/compiler/pathscale.hpp +80 -0
- data/ext/boost/config/compiler/pgi.hpp +5 -5
- data/ext/boost/config/compiler/sunpro_cc.hpp +4 -1
- data/ext/boost/config/compiler/vacpp.hpp +37 -13
- data/ext/boost/config/compiler/visualc.hpp +24 -11
- data/ext/boost/config/platform/bsd.hpp +1 -1
- data/ext/boost/config/platform/cray.hpp +18 -0
- data/ext/boost/config/platform/cygwin.hpp +10 -0
- data/ext/boost/config/platform/linux.hpp +5 -0
- data/ext/boost/config/platform/macos.hpp +5 -4
- data/ext/boost/config/platform/symbian.hpp +5 -2
- data/ext/boost/config/platform/vms.hpp +25 -0
- data/ext/boost/config/platform/win32.hpp +7 -1
- data/ext/boost/config/select_compiler_config.hpp +8 -25
- data/ext/boost/config/select_platform_config.hpp +8 -1
- data/ext/boost/config/select_stdlib_config.hpp +9 -1
- data/ext/boost/config/stdlib/dinkumware.hpp +6 -9
- data/ext/boost/config/stdlib/libcomo.hpp +1 -4
- data/ext/boost/config/stdlib/libcpp.hpp +36 -0
- data/ext/boost/config/stdlib/libstdcpp3.hpp +37 -11
- data/ext/boost/config/stdlib/modena.hpp +1 -4
- data/ext/boost/config/stdlib/msl.hpp +1 -4
- data/ext/boost/config/stdlib/roguewave.hpp +9 -6
- data/ext/boost/config/stdlib/sgi.hpp +12 -4
- data/ext/boost/config/stdlib/stlport.hpp +11 -4
- data/ext/boost/config/stdlib/vacpp.hpp +11 -4
- data/ext/boost/config/suffix.hpp +71 -6
- data/ext/boost/config/warning_disable.hpp +1 -1
- data/ext/boost/container/container_fwd.hpp +177 -0
- data/ext/boost/cstdint.hpp +17 -12
- data/ext/boost/current_function.hpp +2 -1
- data/ext/boost/date_time/c_time.hpp +17 -1
- data/ext/boost/date_time/compiler_config.hpp +13 -15
- data/ext/boost/date_time/date_formatting.hpp +7 -1
- data/ext/boost/date_time/filetime_functions.hpp +4 -4
- data/ext/boost/date_time/gregorian_calendar.ipp +2 -2
- data/ext/boost/date_time/strings_from_facet.hpp +3 -3
- data/ext/boost/date_time/time_facet.hpp +101 -101
- data/ext/boost/detail/endian.hpp +4 -2
- data/ext/boost/detail/fenv.hpp +74 -0
- data/ext/boost/detail/sp_typeinfo.hpp +6 -0
- data/ext/boost/exception/detail/clone_current_exception.hpp +47 -0
- data/ext/boost/exception/detail/exception_ptr.hpp +194 -122
- data/ext/boost/exception/detail/type_info.hpp +3 -3
- data/ext/boost/exception/diagnostic_information.hpp +37 -21
- data/ext/boost/exception/exception.hpp +21 -1
- data/ext/boost/exception/info.hpp +0 -1
- data/ext/boost/function.hpp +2 -2
- data/ext/boost/function/function_base.hpp +15 -9
- data/ext/boost/function/function_template.hpp +26 -48
- data/ext/boost/integer_fwd.hpp +0 -16
- data/ext/boost/integer_traits.hpp +2 -2
- data/ext/boost/iterator.hpp +1 -1
- data/ext/boost/iterator/iterator_adaptor.hpp +1 -7
- data/ext/boost/iterator/iterator_facade.hpp +13 -13
- data/ext/boost/iterator/transform_iterator.hpp +5 -20
- data/ext/boost/lexical_cast.hpp +1655 -673
- data/ext/boost/math/policies/policy.hpp +982 -0
- data/ext/boost/math/special_functions/detail/fp_traits.hpp +570 -0
- data/ext/boost/math/special_functions/detail/round_fwd.hpp +80 -0
- data/ext/boost/math/special_functions/fpclassify.hpp +533 -0
- data/ext/boost/math/special_functions/math_fwd.hpp +1070 -0
- data/ext/boost/math/special_functions/sign.hpp +145 -0
- data/ext/boost/math/tools/config.hpp +321 -0
- data/ext/boost/math/tools/promotion.hpp +150 -0
- data/ext/boost/math/tools/real_cast.hpp +29 -0
- data/ext/boost/math/tools/user.hpp +97 -0
- data/ext/boost/move/move.hpp +1222 -0
- data/ext/boost/mpl/O1_size.hpp +40 -0
- data/ext/boost/mpl/O1_size_fwd.hpp +24 -0
- data/ext/boost/mpl/advance.hpp +76 -0
- data/ext/boost/mpl/advance_fwd.hpp +28 -0
- data/ext/boost/mpl/at.hpp +52 -0
- data/ext/boost/mpl/at_fwd.hpp +24 -0
- data/ext/boost/mpl/aux_/O1_size_impl.hpp +87 -0
- data/ext/boost/mpl/aux_/advance_backward.hpp +128 -0
- data/ext/boost/mpl/aux_/advance_forward.hpp +127 -0
- data/ext/boost/mpl/aux_/arithmetic_op.hpp +92 -0
- data/ext/boost/mpl/aux_/at_impl.hpp +45 -0
- data/ext/boost/mpl/aux_/begin_end_impl.hpp +101 -0
- data/ext/boost/mpl/aux_/clear_impl.hpp +35 -0
- data/ext/boost/mpl/aux_/comparison_op.hpp +83 -0
- data/ext/boost/mpl/aux_/config/forwarding.hpp +27 -0
- data/ext/boost/mpl/aux_/config/typeof.hpp +38 -0
- data/ext/boost/mpl/aux_/contains_impl.hpp +61 -0
- data/ext/boost/mpl/aux_/find_if_pred.hpp +31 -0
- data/ext/boost/mpl/aux_/fold_impl.hpp +43 -0
- data/ext/boost/mpl/aux_/has_begin.hpp +23 -0
- data/ext/boost/mpl/aux_/has_size.hpp +23 -0
- data/ext/boost/mpl/aux_/has_tag.hpp +23 -0
- data/ext/boost/mpl/aux_/inserter_algorithm.hpp +159 -0
- data/ext/boost/mpl/aux_/is_msvc_eti_arg.hpp +64 -0
- data/ext/boost/mpl/aux_/iter_apply.hpp +47 -0
- data/ext/boost/mpl/aux_/iter_fold_if_impl.hpp +210 -0
- data/ext/boost/mpl/aux_/iter_fold_impl.hpp +42 -0
- data/ext/boost/mpl/aux_/lambda_spec.hpp +49 -0
- data/ext/boost/mpl/aux_/largest_int.hpp +63 -0
- data/ext/boost/mpl/aux_/msvc_eti_base.hpp +77 -0
- data/ext/boost/mpl/aux_/msvc_type.hpp +62 -0
- data/ext/boost/mpl/aux_/numeric_cast_utils.hpp +77 -0
- data/ext/boost/mpl/aux_/numeric_op.hpp +315 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/advance_backward.hpp +97 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/advance_forward.hpp +97 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/equal_to.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp +180 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/greater.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/greater_equal.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp +133 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_impl.hpp +180 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/less.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/less_equal.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/list.hpp +323 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/minus.hpp +146 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/not_equal_to.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/plus.hpp +146 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/reverse_fold_impl.hpp +231 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/times.hpp +146 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/vector.hpp +323 -0
- data/ext/boost/mpl/aux_/preprocessor/default_params.hpp +67 -0
- data/ext/boost/mpl/aux_/push_back_impl.hpp +70 -0
- data/ext/boost/mpl/aux_/push_front_impl.hpp +71 -0
- data/ext/boost/mpl/aux_/reverse_fold_impl.hpp +44 -0
- data/ext/boost/mpl/aux_/size_impl.hpp +52 -0
- data/ext/boost/mpl/aux_/traits_lambda_spec.hpp +63 -0
- data/ext/boost/mpl/back_fwd.hpp +24 -0
- data/ext/boost/mpl/back_inserter.hpp +34 -0
- data/ext/boost/mpl/begin_end.hpp +57 -0
- data/ext/boost/mpl/begin_end_fwd.hpp +27 -0
- data/ext/boost/mpl/clear.hpp +39 -0
- data/ext/boost/mpl/clear_fwd.hpp +24 -0
- data/ext/boost/mpl/comparison.hpp +24 -0
- data/ext/boost/mpl/contains.hpp +41 -0
- data/ext/boost/mpl/contains_fwd.hpp +25 -0
- data/ext/boost/mpl/deref.hpp +41 -0
- data/ext/boost/mpl/distance.hpp +78 -0
- data/ext/boost/mpl/distance_fwd.hpp +28 -0
- data/ext/boost/mpl/empty_fwd.hpp +24 -0
- data/ext/boost/mpl/equal_to.hpp +21 -0
- data/ext/boost/mpl/find.hpp +38 -0
- data/ext/boost/mpl/find_if.hpp +50 -0
- data/ext/boost/mpl/fold.hpp +48 -0
- data/ext/boost/mpl/front_fwd.hpp +24 -0
- data/ext/boost/mpl/front_inserter.hpp +33 -0
- data/ext/boost/mpl/greater.hpp +21 -0
- data/ext/boost/mpl/greater_equal.hpp +21 -0
- data/ext/boost/mpl/inserter.hpp +32 -0
- data/ext/boost/mpl/iter_fold.hpp +49 -0
- data/ext/boost/mpl/iter_fold_if.hpp +117 -0
- data/ext/boost/mpl/iterator_range.hpp +42 -0
- data/ext/boost/mpl/iterator_tags.hpp +27 -0
- data/ext/boost/mpl/less.hpp +21 -0
- data/ext/boost/mpl/less_equal.hpp +21 -0
- data/ext/boost/mpl/limits/list.hpp +21 -0
- data/ext/boost/mpl/limits/vector.hpp +21 -0
- data/ext/boost/mpl/list.hpp +57 -0
- data/ext/boost/mpl/list/aux_/O1_size.hpp +33 -0
- data/ext/boost/mpl/list/aux_/begin_end.hpp +44 -0
- data/ext/boost/mpl/list/aux_/clear.hpp +34 -0
- data/ext/boost/mpl/list/aux_/empty.hpp +34 -0
- data/ext/boost/mpl/list/aux_/front.hpp +33 -0
- data/ext/boost/mpl/list/aux_/include_preprocessed.hpp +35 -0
- data/ext/boost/mpl/list/aux_/item.hpp +55 -0
- data/ext/boost/mpl/list/aux_/iterator.hpp +76 -0
- data/ext/boost/mpl/list/aux_/pop_front.hpp +34 -0
- data/ext/boost/mpl/list/aux_/preprocessed/plain/list10.hpp +149 -0
- data/ext/boost/mpl/list/aux_/preprocessed/plain/list20.hpp +169 -0
- data/ext/boost/mpl/list/aux_/push_back.hpp +36 -0
- data/ext/boost/mpl/list/aux_/push_front.hpp +39 -0
- data/ext/boost/mpl/list/aux_/size.hpp +33 -0
- data/ext/boost/mpl/list/aux_/tag.hpp +24 -0
- data/ext/boost/mpl/list/list0.hpp +42 -0
- data/ext/boost/mpl/list/list10.hpp +43 -0
- data/ext/boost/mpl/list/list20.hpp +43 -0
- data/ext/boost/mpl/long.hpp +22 -0
- data/ext/boost/mpl/long_fwd.hpp +27 -0
- data/ext/boost/mpl/minus.hpp +21 -0
- data/ext/boost/mpl/multiplies.hpp +53 -0
- data/ext/boost/mpl/negate.hpp +81 -0
- data/ext/boost/mpl/not_equal_to.hpp +21 -0
- data/ext/boost/mpl/numeric_cast.hpp +41 -0
- data/ext/boost/mpl/pair.hpp +70 -0
- data/ext/boost/mpl/plus.hpp +21 -0
- data/ext/boost/mpl/pop_back_fwd.hpp +24 -0
- data/ext/boost/mpl/pop_front_fwd.hpp +24 -0
- data/ext/boost/mpl/prior.hpp +19 -0
- data/ext/boost/mpl/push_back.hpp +53 -0
- data/ext/boost/mpl/push_back_fwd.hpp +24 -0
- data/ext/boost/mpl/push_front.hpp +52 -0
- data/ext/boost/mpl/push_front_fwd.hpp +24 -0
- data/ext/boost/mpl/remove_if.hpp +83 -0
- data/ext/boost/mpl/reverse_fold.hpp +50 -0
- data/ext/boost/mpl/same_as.hpp +55 -0
- data/ext/boost/mpl/sequence_tag.hpp +124 -0
- data/ext/boost/mpl/sequence_tag_fwd.hpp +26 -0
- data/ext/boost/mpl/size.hpp +42 -0
- data/ext/boost/mpl/size_fwd.hpp +24 -0
- data/ext/boost/mpl/tag.hpp +52 -0
- data/ext/boost/mpl/times.hpp +21 -0
- data/ext/boost/mpl/vector.hpp +57 -0
- data/ext/boost/mpl/vector/aux_/O1_size.hpp +56 -0
- data/ext/boost/mpl/vector/aux_/at.hpp +116 -0
- data/ext/boost/mpl/vector/aux_/back.hpp +59 -0
- data/ext/boost/mpl/vector/aux_/begin_end.hpp +49 -0
- data/ext/boost/mpl/vector/aux_/clear.hpp +55 -0
- data/ext/boost/mpl/vector/aux_/empty.hpp +68 -0
- data/ext/boost/mpl/vector/aux_/front.hpp +56 -0
- data/ext/boost/mpl/vector/aux_/include_preprocessed.hpp +55 -0
- data/ext/boost/mpl/vector/aux_/item.hpp +103 -0
- data/ext/boost/mpl/vector/aux_/iterator.hpp +130 -0
- data/ext/boost/mpl/vector/aux_/pop_back.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/pop_front.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector10.hpp +829 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector20.hpp +1144 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10.hpp +139 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20.hpp +159 -0
- data/ext/boost/mpl/vector/aux_/push_back.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/push_front.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/size.hpp +49 -0
- data/ext/boost/mpl/vector/aux_/tag.hpp +32 -0
- data/ext/boost/mpl/vector/aux_/vector0.hpp +52 -0
- data/ext/boost/mpl/vector/vector0.hpp +34 -0
- data/ext/boost/mpl/vector/vector10.hpp +45 -0
- data/ext/boost/mpl/vector/vector20.hpp +45 -0
- data/ext/boost/none.hpp +1 -1
- data/ext/boost/numeric/conversion/bounds.hpp +24 -0
- data/ext/boost/numeric/conversion/cast.hpp +61 -0
- data/ext/boost/numeric/conversion/conversion_traits.hpp +39 -0
- data/ext/boost/numeric/conversion/converter.hpp +68 -0
- data/ext/boost/numeric/conversion/converter_policies.hpp +186 -0
- data/ext/boost/numeric/conversion/detail/bounds.hpp +58 -0
- data/ext/boost/numeric/conversion/detail/conversion_traits.hpp +97 -0
- data/ext/boost/numeric/conversion/detail/converter.hpp +602 -0
- data/ext/boost/numeric/conversion/detail/int_float_mixture.hpp +72 -0
- data/ext/boost/numeric/conversion/detail/is_subranged.hpp +234 -0
- data/ext/boost/numeric/conversion/detail/meta.hpp +120 -0
- data/ext/boost/numeric/conversion/detail/numeric_cast_traits.hpp +138 -0
- data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_common.hpp +1741 -0
- data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_long_long.hpp +347 -0
- data/ext/boost/numeric/conversion/detail/sign_mixture.hpp +72 -0
- data/ext/boost/numeric/conversion/detail/udt_builtin_mixture.hpp +69 -0
- data/ext/boost/numeric/conversion/int_float_mixture_enum.hpp +29 -0
- data/ext/boost/numeric/conversion/numeric_cast_traits.hpp +31 -0
- data/ext/boost/numeric/conversion/sign_mixture_enum.hpp +29 -0
- data/ext/boost/numeric/conversion/udt_builtin_mixture_enum.hpp +26 -0
- data/ext/boost/operators.hpp +3 -1
- data/ext/boost/optional/optional.hpp +146 -79
- data/ext/boost/optional/optional_fwd.hpp +8 -1
- data/ext/boost/preprocessor/cat.hpp +2 -2
- data/ext/boost/preprocessor/config/config.hpp +39 -4
- data/ext/boost/preprocessor/facilities/intercept.hpp +277 -0
- data/ext/boost/preprocessor/facilities/overload.hpp +25 -0
- data/ext/boost/preprocessor/iteration/detail/iter/forward1.hpp +3 -3
- data/ext/boost/preprocessor/iteration/iterate.hpp +3 -3
- data/ext/boost/preprocessor/punctuation/paren.hpp +23 -0
- data/ext/boost/preprocessor/repetition/enum_shifted_params.hpp +44 -0
- data/ext/boost/preprocessor/seq/cat.hpp +5 -4
- data/ext/boost/preprocessor/seq/size.hpp +0 -1
- data/ext/boost/preprocessor/tuple/eat.hpp +83 -34
- data/ext/boost/preprocessor/tuple/elem.hpp +161 -355
- data/ext/boost/preprocessor/tuple/rem.hpp +110 -48
- data/ext/boost/preprocessor/tuple/to_list.hpp +90 -36
- data/ext/boost/preprocessor/variadic/elem.hpp +94 -0
- data/ext/boost/preprocessor/variadic/size.hpp +30 -0
- data/ext/boost/range/begin.hpp +17 -6
- data/ext/boost/range/concepts.hpp +37 -2
- data/ext/boost/range/detail/safe_bool.hpp +72 -0
- data/ext/boost/range/end.hpp +14 -9
- data/ext/boost/range/iterator_range_core.hpp +120 -12
- data/ext/boost/range/size.hpp +21 -5
- data/ext/boost/smart_ptr/detail/shared_count.hpp +88 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base.hpp +3 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_aix.hpp +142 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +9 -0
- data/ext/boost/smart_ptr/detail/sp_counted_impl.hpp +10 -2
- data/ext/boost/smart_ptr/detail/sp_has_sync.hpp +5 -1
- data/ext/boost/smart_ptr/detail/spinlock.hpp +4 -1
- data/ext/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +20 -3
- data/ext/boost/smart_ptr/detail/spinlock_pool.hpp +4 -0
- data/ext/boost/smart_ptr/make_shared.hpp +591 -22
- data/ext/boost/smart_ptr/shared_array.hpp +29 -1
- data/ext/boost/smart_ptr/shared_ptr.hpp +29 -13
- data/ext/boost/smart_ptr/weak_ptr.hpp +24 -12
- data/ext/boost/src/pthread/once.cpp +9 -7
- data/ext/boost/src/pthread/thread.cpp +32 -28
- data/ext/boost/src/pthread/timeconv.inl +4 -5
- data/ext/boost/src/tss_null.cpp +5 -1
- data/ext/boost/static_assert.hpp +8 -2
- data/ext/boost/thread/detail/config.hpp +19 -4
- data/ext/boost/thread/detail/move.hpp +11 -5
- data/ext/boost/thread/detail/thread.hpp +59 -43
- data/ext/boost/thread/exceptions.hpp +9 -9
- data/ext/boost/thread/future.hpp +150 -82
- data/ext/boost/thread/locks.hpp +101 -60
- data/ext/boost/thread/pthread/condition_variable.hpp +79 -32
- data/ext/boost/thread/pthread/condition_variable_fwd.hpp +12 -3
- data/ext/boost/thread/pthread/mutex.hpp +17 -14
- data/ext/boost/thread/pthread/once.hpp +3 -4
- data/ext/boost/thread/pthread/pthread_mutex_scoped_lock.hpp +12 -2
- data/ext/boost/thread/pthread/recursive_mutex.hpp +19 -19
- data/ext/boost/thread/pthread/shared_mutex.hpp +13 -13
- data/ext/boost/thread/pthread/thread_data.hpp +40 -12
- data/ext/boost/thread/thread_time.hpp +5 -0
- data/ext/boost/throw_exception.hpp +1 -1
- data/ext/boost/token_functions.hpp +34 -10
- data/ext/boost/type_traits/add_rvalue_reference.hpp +66 -0
- data/ext/boost/type_traits/alignment_of.hpp +1 -1
- data/ext/boost/type_traits/detail/bool_trait_def.hpp +26 -3
- data/ext/boost/type_traits/detail/bool_trait_undef.hpp +3 -2
- data/ext/boost/type_traits/detail/cv_traits_impl.hpp +1 -1
- data/ext/boost/type_traits/detail/size_t_trait_def.hpp +6 -4
- data/ext/boost/type_traits/detail/type_trait_def.hpp +8 -2
- data/ext/boost/type_traits/function_traits.hpp +1 -1
- data/ext/boost/type_traits/has_nothrow_constructor.hpp +53 -0
- data/ext/boost/type_traits/has_nothrow_copy.hpp +19 -5
- data/ext/boost/type_traits/has_trivial_constructor.hpp +51 -0
- data/ext/boost/type_traits/has_trivial_copy.hpp +20 -5
- data/ext/boost/type_traits/has_trivial_destructor.hpp +12 -5
- data/ext/boost/type_traits/intrinsics.hpp +119 -71
- data/ext/boost/type_traits/is_const.hpp +5 -5
- data/ext/boost/type_traits/is_convertible.hpp +14 -13
- data/ext/boost/type_traits/is_enum.hpp +1 -1
- data/ext/boost/type_traits/is_floating_point.hpp +27 -0
- data/ext/boost/type_traits/is_function.hpp +3 -3
- data/ext/boost/type_traits/is_fundamental.hpp +1 -1
- data/ext/boost/type_traits/is_member_function_pointer.hpp +2 -2
- data/ext/boost/type_traits/is_member_pointer.hpp +2 -2
- data/ext/boost/type_traits/is_pod.hpp +11 -3
- data/ext/boost/type_traits/is_pointer.hpp +2 -2
- data/ext/boost/type_traits/is_signed.hpp +8 -3
- data/ext/boost/type_traits/is_union.hpp +8 -0
- data/ext/boost/type_traits/is_unsigned.hpp +9 -4
- data/ext/boost/type_traits/is_volatile.hpp +5 -5
- data/ext/boost/type_traits/remove_cv.hpp +4 -3
- data/ext/boost/type_traits/remove_pointer.hpp +51 -2
- data/ext/boost/type_traits/remove_reference.hpp +2 -2
- data/ext/boost/type_traits/type_with_alignment.hpp +8 -2
- data/ext/boost/utility/declval.hpp +44 -0
- data/ext/boost/utility/detail/in_place_factory_prefix.hpp +36 -0
- data/ext/boost/utility/detail/in_place_factory_suffix.hpp +23 -0
- data/ext/boost/utility/detail/result_of_iterate.hpp +142 -0
- data/ext/boost/utility/in_place_factory.hpp +88 -0
- data/ext/boost/utility/result_of.hpp +103 -0
- data/ext/boost/utility/swap.hpp +55 -0
- data/ext/common/AnsiColorConstants.h +36 -0
- data/ext/common/ApplicationPool2/Common.h +87 -0
- data/ext/common/ApplicationPool2/ComponentInfo.h +53 -0
- data/ext/common/ApplicationPool2/Group.h +648 -0
- data/ext/common/ApplicationPool2/Implementation.cpp +580 -0
- data/ext/common/ApplicationPool2/Options.h +576 -0
- data/ext/common/ApplicationPool2/PipeWatcher.h +61 -0
- data/ext/common/ApplicationPool2/Pool.h +1181 -0
- data/ext/common/ApplicationPool2/Process.h +425 -0
- data/ext/common/ApplicationPool2/README.md +96 -0
- data/ext/common/ApplicationPool2/Session.h +158 -0
- data/ext/common/ApplicationPool2/Socket.h +246 -0
- data/ext/common/ApplicationPool2/Spawner.h +2212 -0
- data/ext/common/ApplicationPool2/SuperGroup.h +749 -0
- data/ext/common/BackgroundEventLoop.cpp +129 -0
- data/ext/common/BackgroundEventLoop.h +61 -0
- data/ext/common/Constants.h +3 -1
- data/ext/common/EventedBufferedInput.h +331 -0
- data/ext/common/EventedMessageServer.h +17 -34
- data/ext/common/EventedServer.h +2 -2
- data/ext/common/Exceptions.h +71 -19
- data/ext/common/FileDescriptor.h +8 -6
- data/ext/common/HttpConstants.h +167 -0
- data/ext/common/IniFile.h +24 -0
- data/ext/common/Logging.h +62 -849
- data/ext/common/MessageReadersWriters.h +19 -0
- data/ext/common/MessageServer.h +11 -14
- data/ext/common/MultiLibeio.cpp +198 -0
- data/ext/common/MultiLibeio.h +67 -0
- data/ext/common/ResourceLocator.h +24 -41
- data/ext/common/SafeLibev.h +186 -14
- data/ext/common/StaticString.h +23 -3
- data/ext/common/UnionStation.h +972 -0
- data/ext/common/Utils.cpp +168 -24
- data/ext/common/Utils.h +25 -3
- data/ext/common/Utils/CachedFileStat.hpp +4 -3
- data/ext/common/Utils/FileChangeChecker.h +2 -2
- data/ext/common/Utils/HashMap.h +50 -0
- data/ext/common/Utils/IOUtils.cpp +229 -68
- data/ext/common/Utils/IOUtils.h +134 -3
- data/ext/common/Utils/Lock.h +28 -0
- data/ext/common/Utils/MemoryBarrier.h +52 -0
- data/ext/common/Utils/PriorityQueue.h +54 -0
- data/ext/common/Utils/ProcessMetricsCollector.h +9 -11
- data/ext/common/Utils/ScopeGuard.h +50 -1
- data/ext/common/Utils/SmallVector.h +653 -0
- data/ext/common/Utils/StrIntUtils.cpp +26 -2
- data/ext/common/Utils/StrIntUtils.h +18 -2
- data/ext/common/Utils/StringMap.h +125 -8
- data/ext/common/Utils/Template.h +212 -0
- data/ext/common/Utils/fib.c +699 -0
- data/ext/common/Utils/fib.h +101 -0
- data/ext/common/Utils/fibpriv.h +67 -0
- data/ext/common/Utils/json-forwards.h +249 -0
- data/ext/common/Utils/json.h +1855 -0
- data/ext/common/Utils/jsoncpp.cpp +4230 -0
- data/ext/common/agents/Base.cpp +1126 -0
- data/ext/common/{AgentBase.h → agents/Base.h} +5 -1
- data/ext/common/agents/EnvPrinter.c +16 -0
- data/ext/common/agents/HelperAgent/AgentOptions.h +81 -0
- data/ext/common/{HelperAgent → agents/HelperAgent}/BacktracesServer.h +3 -2
- data/ext/common/agents/HelperAgent/FileBackedPipe.h +732 -0
- data/ext/common/agents/HelperAgent/Main.cpp +497 -0
- data/ext/common/agents/HelperAgent/RequestHandler.cpp +283 -0
- data/ext/common/agents/HelperAgent/RequestHandler.h +2139 -0
- data/ext/common/agents/HelperAgent/ScgiRequestParser.h +451 -0
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/DataStoreId.h +1 -1
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.cpp +1 -1
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.h +0 -0
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/LoggingServer.h +18 -16
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/Main.cpp +15 -13
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/RemoteSender.h +6 -6
- data/ext/common/agents/SpawnPreparer.cpp +127 -0
- data/ext/common/{Watchdog.cpp → agents/Watchdog/Main.cpp} +63 -25
- data/ext/libeio/Changes +72 -0
- data/ext/{google/COPYING → libeio/LICENSE} +17 -9
- data/ext/libeio/Makefile.am +15 -0
- data/ext/libeio/Makefile.in +694 -0
- data/ext/libeio/aclocal.m4 +9418 -0
- data/ext/libeio/autogen.sh +3 -0
- data/ext/libeio/config.guess +1501 -0
- data/ext/libeio/config.h.in +136 -0
- data/ext/libeio/config.sub +1705 -0
- data/ext/libeio/configure +14822 -0
- data/ext/libeio/configure.ac +22 -0
- data/ext/libeio/demo.c +194 -0
- data/ext/libeio/ecb.h +457 -0
- data/ext/libeio/eio.c +2816 -0
- data/ext/libeio/eio.h +411 -0
- data/ext/libeio/install-sh +520 -0
- data/ext/libeio/libeio.m4 +211 -0
- data/ext/libeio/ltmain.sh +9636 -0
- data/ext/libeio/missing +376 -0
- data/ext/libeio/xthread.h +166 -0
- data/ext/libev/Changes +125 -7
- data/ext/libev/Makefile.am +5 -3
- data/ext/libev/Makefile.in +209 -120
- data/ext/libev/aclocal.m4 +6027 -4619
- data/ext/libev/autogen.sh +1 -4
- data/ext/libev/config.h.in +11 -7
- data/ext/libev/configure +7312 -14993
- data/ext/libev/configure.ac +12 -5
- data/ext/libev/depcomp +630 -0
- data/ext/libev/ev++.h +48 -32
- data/ext/libev/ev.c +1173 -391
- data/ext/libev/ev.h +315 -181
- data/ext/libev/ev_epoll.c +66 -15
- data/ext/libev/ev_kqueue.c +20 -18
- data/ext/libev/ev_poll.c +27 -23
- data/ext/libev/ev_port.c +39 -19
- data/ext/libev/ev_select.c +23 -17
- data/ext/libev/ev_vars.h +25 -8
- data/ext/libev/ev_win32.c +6 -6
- data/ext/libev/ev_wrap.h +22 -2
- data/ext/libev/event.c +18 -17
- data/ext/libev/event.h +16 -4
- data/ext/libev/libev.m4 +10 -6
- data/ext/libev/ltmain.sh +7353 -5811
- data/ext/nginx/Configuration.c +74 -42
- data/ext/nginx/Configuration.h +3 -5
- data/ext/nginx/ContentHandler.c +26 -83
- data/ext/nginx/ContentHandler.h +1 -1
- data/ext/nginx/config +13 -9
- data/ext/nginx/ngx_http_passenger_module.c +3 -7
- data/ext/oxt/detail/backtrace_enabled.hpp +5 -102
- data/ext/oxt/detail/context.hpp +90 -0
- data/ext/oxt/detail/spin_lock_darwin.hpp +4 -0
- data/ext/oxt/detail/spin_lock_gcc_x86.hpp +4 -0
- data/ext/oxt/detail/spin_lock_pthreads.hpp +14 -0
- data/ext/oxt/detail/tracable_exception_enabled.hpp +2 -2
- data/ext/oxt/dynamic_thread_group.hpp +27 -1
- data/ext/oxt/implementation.cpp +415 -0
- data/ext/oxt/{thread.cpp → initialize.hpp} +13 -6
- data/ext/oxt/macros.hpp +32 -1
- data/ext/oxt/spin_lock.hpp +6 -11
- data/ext/oxt/system_calls.cpp +204 -16
- data/ext/oxt/system_calls.hpp +85 -45
- data/ext/oxt/thread.hpp +13 -117
- data/ext/ruby/passenger_native_support.c +82 -237
- data/helper-scripts/backtrace-sanitizer.rb +114 -0
- data/helper-scripts/classic-rails-loader.rb +135 -0
- data/helper-scripts/classic-rails-preloader.rb +161 -0
- data/helper-scripts/node-loader.js +314 -0
- data/helper-scripts/rack-loader.rb +104 -0
- data/helper-scripts/rack-preloader.rb +132 -0
- data/helper-scripts/wsgi-loader.py +231 -0
- data/helper-scripts/wsgi-preloader.py +1 -0
- data/lib/phusion_passenger.rb +159 -61
- data/lib/phusion_passenger/abstract_installer.rb +182 -87
- data/lib/phusion_passenger/admin_tools/server_instance.rb +25 -19
- data/lib/phusion_passenger/analytics_logger.rb +5 -4
- data/lib/phusion_passenger/classic_rails/{request_handler.rb → thread_handler_extension.rb} +4 -40
- data/lib/phusion_passenger/classic_rails_extensions/init.rb +5 -3
- data/lib/phusion_passenger/common_library.rb +441 -0
- data/lib/phusion_passenger/console_text_template.rb +4 -16
- data/lib/phusion_passenger/constants.rb +1 -8
- data/lib/phusion_passenger/debug_logging.rb +5 -2
- data/lib/phusion_passenger/dependencies.rb +51 -13
- data/lib/phusion_passenger/loader_shared_helpers.rb +318 -0
- data/lib/phusion_passenger/message_channel.rb +3 -47
- data/lib/phusion_passenger/message_client.rb +2 -2
- data/lib/phusion_passenger/native_support.rb +36 -15
- data/lib/phusion_passenger/packaging.rb +8 -11
- data/lib/phusion_passenger/platform_info.rb +25 -17
- data/lib/phusion_passenger/platform_info/apache.rb +10 -7
- data/lib/phusion_passenger/platform_info/binary_compatibility.rb +10 -30
- data/lib/phusion_passenger/platform_info/compiler.rb +93 -34
- data/lib/phusion_passenger/platform_info/ruby.rb +37 -97
- data/lib/phusion_passenger/preloader_shared_helpers.rb +121 -0
- data/lib/phusion_passenger/public_api.rb +1 -4
- data/lib/phusion_passenger/rack/{request_handler.rb → thread_handler_extension.rb} +14 -63
- data/lib/phusion_passenger/rails3_extensions/init.rb +9 -8
- data/lib/phusion_passenger/request_handler.rb +500 -0
- data/lib/phusion_passenger/request_handler/thread_handler.rb +360 -0
- data/lib/phusion_passenger/ruby_core_enhancements.rb +142 -0
- data/lib/phusion_passenger/standalone/command.rb +36 -15
- data/lib/phusion_passenger/standalone/package_runtime_command.rb +16 -8
- data/lib/phusion_passenger/standalone/runtime_installer.rb +169 -72
- data/lib/phusion_passenger/standalone/start_command.rb +44 -39
- data/lib/phusion_passenger/standalone/utils.rb +5 -5
- data/lib/phusion_passenger/utils.rb +35 -914
- data/lib/phusion_passenger/utils/ansi_colors.rb +59 -0
- data/lib/phusion_passenger/utils/file_system_watcher.rb +1 -1
- data/lib/phusion_passenger/utils/robust_interruption.rb +134 -0
- data/lib/phusion_passenger/utils/tee_input.rb +174 -0
- data/lib/phusion_passenger/utils/tmpio.rb +33 -0
- data/lib/phusion_passenger/utils/unseekable_socket.rb +6 -0
- data/resources/mime.types +5 -1
- data/{lib/phusion_passenger/templates → resources}/standalone_default_root/index.html +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/config_snippets.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/deployment_example.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/no_write_permission_to_passenger_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/run_installer_as_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/welcome.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/error_layout.css +6 -0
- data/resources/templates/error_layout.html.template +89 -0
- data/resources/templates/general_error.html.template +1 -0
- data/resources/templates/general_error_with_html.html.template +1 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/ask_for_extra_configure_flags.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/cannot_write_to_dir.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets_inserted.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/confirm_extra_configure_flags.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/deployment_example.txt.erb +0 -0
- data/resources/templates/nginx/not_available_when_natively_packaged.txt.erb +8 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_downloaded.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_extracted.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/query_download_and_install.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/run_installer_as_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/welcome.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/cannot_write_to_dir.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/config.erb +26 -5
- data/{lib/phusion_passenger → resources}/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/run_installer_as_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/welcome.txt.erb +0 -0
- data/resources/templates/undisclosed_error.html.template +25 -0
- data/test/config.json.example +42 -0
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +86 -0
- data/test/cxx/ApplicationPool2/OptionsTest.cpp +44 -0
- data/test/cxx/ApplicationPool2/PoolTest.cpp +1234 -0
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +131 -0
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +229 -0
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +744 -0
- data/test/cxx/BufferedIOTest.cpp +7 -7
- data/test/cxx/CxxTestMain.cpp +65 -2
- data/test/cxx/FileBackedPipeTest.cpp +626 -0
- data/test/cxx/FileChangeCheckerTest.cpp +20 -18
- data/test/cxx/FilterSupportTest.cpp +5 -5
- data/test/cxx/IOUtilsTest.cpp +11 -4
- data/test/cxx/MessageReadersWritersTest.cpp +1 -1
- data/test/cxx/MessageServerTest.cpp +31 -30
- data/test/cxx/RequestHandlerTest.cpp +777 -0
- data/test/cxx/ScgiRequestParserTest.cpp +36 -16
- data/test/cxx/ServerInstanceDirTest.cpp +1 -1
- data/test/cxx/StringMapTest.cpp +61 -0
- data/test/cxx/TemplateTest.cpp +118 -0
- data/test/cxx/TestSupport.cpp +25 -68
- data/test/cxx/TestSupport.h +81 -41
- data/test/cxx/{LoggingTest.cpp → UnionStationTest.cpp} +79 -74
- data/test/cxx/UtilsTest.cpp +59 -5
- data/test/integration_tests/apache2_tests.rb +2 -2
- data/test/integration_tests/nginx_tests.rb +1 -1
- data/test/integration_tests/spec_helper.rb +7 -5
- data/test/oxt/oxt_test_main.cpp +2 -0
- data/test/oxt/syscall_interruption_test.cpp +1 -0
- data/test/ruby/classic_rails/loader_spec.rb +48 -0
- data/test/ruby/classic_rails/preloader_spec.rb +54 -0
- data/test/ruby/rack/loader_spec.rb +62 -0
- data/test/ruby/rack/preloader_spec.rb +74 -0
- data/test/ruby/{abstract_request_handler_spec.rb → request_handler_spec.rb} +31 -68
- data/test/ruby/shared/loader_spec.rb +241 -0
- data/test/ruby/shared/rails/analytics_logging_extensions_spec.rb +141 -182
- data/test/ruby/shared/ruby_loader_spec.rb +55 -0
- data/test/ruby/spec_helper.rb +8 -53
- data/test/ruby/utils/file_system_watcher_spec.rb +9 -1
- data/test/ruby/utils_spec.rb +10 -683
- data/test/stub/rack/config.ru +28 -3
- data/test/stub/rack/start.rb +47 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/Rakefile +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/application_controller.rb +0 -2
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_1.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_2.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/foo_controller.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/helpers/application_helper.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/boot.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/database.yml +3 -3
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environment.rb +5 -2
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/development.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/production.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/staging.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/inflections.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/mime_types.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/routes.rb +1 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/about +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/console +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/dbconsole +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/destroy +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/generate +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/benchmarker +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/profiler +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/request +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/plugin +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/inspector +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/reaper +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/spawner +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/runner +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/server +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/Gemfile +0 -0
- data/test/stub/rails3.0/Gemfile.lock +80 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/Rakefile +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/controllers/application_controller.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/helpers/application_helper.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/views/layouts/application.html.erb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config.ru +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/application.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/boot.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/database.yml +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environment.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/development.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/production.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/test.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/backtrace_silencers.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/inflections.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/mime_types.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/passenger.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/secret_token.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/session_store.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/locales/en.yml +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/routes.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/db/seeds.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/doc/README_FOR_APP +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/404.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/422.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/500.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/favicon.ico +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/index.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/robots.txt +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/script/rails +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/performance/browsing_test.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/test_helper.rb +0 -0
- data/test/stub/start_error.pl +24 -0
- data/test/stub/wsgi/passenger_wsgi.py +71 -3
- data/test/support/apache2_controller.rb +2 -2
- data/test/support/placebo-preloader.rb +88 -0
- data/test/support/test_helper.rb +1 -14
- data/test/tut/tut.h +11 -4
- metadata +590 -326
- data.tar.gz.asc +0 -12
- data/PACKAGING.TXT +0 -25
- data/build/config.rb +0 -46
- data/ext/apache2/HelperAgent.cpp +0 -364
- data/ext/boost/call_traits.hpp +0 -24
- data/ext/boost/detail/call_traits.hpp +0 -164
- data/ext/common/AbstractSpawnManager.h +0 -110
- data/ext/common/AgentBase.cpp +0 -432
- data/ext/common/ApplicationPool/Client.h +0 -788
- data/ext/common/ApplicationPool/Interface.h +0 -295
- data/ext/common/ApplicationPool/Pool.h +0 -1327
- data/ext/common/ApplicationPool/Server.h +0 -479
- data/ext/common/MessageChannel.h +0 -494
- data/ext/common/PoolOptions.h +0 -518
- data/ext/common/Process.h +0 -253
- data/ext/common/Session.h +0 -436
- data/ext/common/SpawnManager.h +0 -611
- data/ext/google/ChangeLog +0 -167
- data/ext/google/dense_hash_map +0 -310
- data/ext/google/dense_hash_set +0 -287
- data/ext/google/sparse_hash_map +0 -294
- data/ext/google/sparse_hash_set +0 -275
- data/ext/google/sparsehash/densehashtable.h +0 -1062
- data/ext/google/sparsehash/sparseconfig.h +0 -55
- data/ext/google/sparsehash/sparsehashtable.h +0 -1015
- data/ext/google/sparsetable +0 -1468
- data/ext/google/type_traits.h +0 -250
- data/ext/nginx/HelperAgent.cpp +0 -1355
- data/ext/nginx/ScgiRequestParser.h +0 -375
- data/ext/oxt/backtrace.cpp +0 -185
- data/ext/oxt/tracable_exception.cpp +0 -89
- data/helper-scripts/passenger-spawn-server +0 -106
- data/lib/phusion_passenger/abstract_request_handler.rb +0 -766
- data/lib/phusion_passenger/abstract_server.rb +0 -372
- data/lib/phusion_passenger/abstract_server_collection.rb +0 -335
- data/lib/phusion_passenger/app_process.rb +0 -174
- data/lib/phusion_passenger/classic_rails/application_spawner.rb +0 -344
- data/lib/phusion_passenger/classic_rails/framework_spawner.rb +0 -311
- data/lib/phusion_passenger/exceptions.rb +0 -103
- data/lib/phusion_passenger/html_template.rb +0 -107
- data/lib/phusion_passenger/rack/application_spawner.rb +0 -231
- data/lib/phusion_passenger/spawn_manager.rb +0 -359
- data/lib/phusion_passenger/templates/app_exited_during_initialization.html.erb +0 -38
- data/lib/phusion_passenger/templates/app_init_error.html.erb +0 -64
- data/lib/phusion_passenger/templates/database_error.html.erb +0 -66
- data/lib/phusion_passenger/templates/error_layout.html.erb +0 -39
- data/lib/phusion_passenger/templates/framework_init_error.html.erb +0 -39
- data/lib/phusion_passenger/templates/general_error.html.erb +0 -22
- data/lib/phusion_passenger/templates/load_error.html.erb +0 -46
- data/lib/phusion_passenger/templates/version_not_found.html.erb +0 -34
- data/lib/phusion_passenger/utils/rewindable_input.rb +0 -125
- data/lib/phusion_passenger/wsgi/application_spawner.rb +0 -108
- data/test/config.yml.example +0 -41
- data/test/cxx/ApplicationPool_PoolTest.cpp +0 -33
- data/test/cxx/ApplicationPool_PoolTestCases.cpp +0 -1029
- data/test/cxx/ApplicationPool_ServerTest.cpp +0 -308
- data/test/cxx/ApplicationPool_Server_PoolTest.cpp +0 -80
- data/test/cxx/MessageChannelTest.cpp +0 -557
- data/test/cxx/PoolOptionsTest.cpp +0 -116
- data/test/cxx/SpawnManagerTest.cpp +0 -161
- data/test/ruby/abstract_server_collection_spec.rb +0 -247
- data/test/ruby/abstract_server_spec.rb +0 -61
- data/test/ruby/app_process_spec.rb +0 -43
- data/test/ruby/classic_rails/application_spawner_spec.rb +0 -89
- data/test/ruby/classic_rails/framework_spawner_spec.rb +0 -92
- data/test/ruby/rack/application_spawner_spec.rb +0 -116
- data/test/ruby/shared/abstract_server_spec.rb +0 -23
- data/test/ruby/shared/spawners/classic_rails/framework_spawner_spec.rb +0 -38
- data/test/ruby/shared/spawners/classic_rails/lack_of_rails_gem_version_spec.rb +0 -19
- data/test/ruby/shared/spawners/classic_rails/spawner_spec.rb +0 -15
- data/test/ruby/shared/spawners/non_preloading_spawner_spec.rb +0 -27
- data/test/ruby/shared/spawners/preloading_spawner_spec.rb +0 -29
- data/test/ruby/shared/spawners/reload_all_spec.rb +0 -36
- data/test/ruby/shared/spawners/reload_single_spec.rb +0 -52
- data/test/ruby/shared/spawners/spawn_server_spec.rb +0 -28
- data/test/ruby/shared/spawners/spawner_spec.rb +0 -273
- data/test/ruby/shared/utils/pseudo_io_spec.rb +0 -60
- data/test/ruby/spawn_manager_spec.rb +0 -134
- data/test/ruby/wsgi/application_spawner_spec.rb +0 -50
- data/test/stub/message_channel.rb +0 -11
- data/test/stub/message_channel_2.rb +0 -12
- data/test/stub/message_channel_3.rb +0 -19
- data/test/stub/rails_apps/3.0/empty/Gemfile.lock +0 -73
- data/test/stub/spawn_server.rb +0 -22
- 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 *¤t )
|
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_ = ¤tValue();
|
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 ¤t,
|
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 ¤t,
|
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 ¤t )
|
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 ¤t )
|
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 ¤t )
|
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
|
+
|