├── .github └── workflows │ └── test.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake ├── hjson-config-version.cmake.in ├── hjson-config.cmake.in └── msvc_crt.cmake ├── include └── hjson │ └── hjson.h ├── performance ├── CMakeLists.txt ├── perf.cpp └── perf_multithread.cpp ├── src ├── CMakeLists.txt ├── hjson_decode.cpp ├── hjson_encode.cpp ├── hjson_parsenumber.cpp └── hjson_value.cpp └── test ├── CMakeLists.txt ├── assets ├── charconv │ ├── pass5_result.hjson │ └── pass5_result.json ├── charset2_result.hjson ├── charset2_result.json ├── charset2_test.hjson ├── charset_result.hjson ├── charset_result.json ├── charset_test.hjson ├── comments │ ├── charconv │ │ ├── pass5_result.hjson │ │ └── pass5_result.json │ ├── charset2_result.hjson │ ├── charset_result.hjson │ ├── comments2_result.hjson │ ├── comments3_result.hjson │ ├── comments4_result.hjson │ ├── comments5_result.hjson │ ├── comments6_result.hjson │ ├── comments7_result.hjson │ ├── comments_result.hjson │ ├── empty_result.hjson │ ├── int64_result.hjson │ ├── kan_result.hjson │ ├── keys_result.hjson │ ├── mltabs_result.hjson │ ├── oa_result.hjson │ ├── pass1_result.hjson │ ├── pass2_result.hjson │ ├── pass3_result.hjson │ ├── pass4_result.hjson │ ├── pass5_result.hjson │ ├── pass6_result.hjson │ ├── passSingle_result.hjson │ ├── root_result.hjson │ ├── stringify1_result.hjson │ ├── strings2_result.hjson │ ├── strings3_result.hjson │ ├── strings4_result.hjson │ ├── strings_result.hjson │ ├── trail_result.hjson │ └── windowseol_result.hjson ├── comments2 │ ├── charconv │ │ ├── pass5_result.hjson │ │ └── pass5_result.json │ ├── charset2_result.hjson │ ├── charset_result.hjson │ ├── comments2_result.hjson │ ├── comments3_result.hjson │ ├── comments4_result.hjson │ ├── comments5_result.hjson │ ├── comments6_result.hjson │ ├── comments7_result.hjson │ ├── comments_result.hjson │ ├── empty_result.hjson │ ├── int64_result.hjson │ ├── kan_result.hjson │ ├── keys_result.hjson │ ├── mltabs_result.hjson │ ├── oa_result.hjson │ ├── pass1_result.hjson │ ├── pass2_result.hjson │ ├── pass3_result.hjson │ ├── pass4_result.hjson │ ├── pass5_result.hjson │ ├── pass6_result.hjson │ ├── passSingle_result.hjson │ ├── root_result.hjson │ ├── stringify1_result.hjson │ ├── strings2_result.hjson │ ├── strings3_result.hjson │ ├── strings4_result.hjson │ ├── strings_result.hjson │ ├── trail_result.hjson │ └── windowseol_result.hjson ├── comments2_result.hjson ├── comments2_result.json ├── comments2_test.hjson ├── comments3 │ ├── charconv │ │ ├── pass5_result.hjson │ │ └── pass5_result.json │ ├── charset2_result.hjson │ ├── charset_result.hjson │ ├── comments2_result.hjson │ ├── comments3_result.hjson │ ├── comments4_result.hjson │ ├── comments5_result.hjson │ ├── comments6_result.hjson │ ├── comments7_result.hjson │ ├── comments_result.hjson │ ├── empty_result.hjson │ ├── int64_result.hjson │ ├── kan_result.hjson │ ├── keys_result.hjson │ ├── mltabs_result.hjson │ ├── oa_result.hjson │ ├── pass1_result.hjson │ ├── pass2_result.hjson │ ├── pass3_result.hjson │ ├── pass4_result.hjson │ ├── pass5_result.hjson │ ├── pass6_result.hjson │ ├── passSingle_result.hjson │ ├── root_result.hjson │ ├── stringify1_result.hjson │ ├── strings2_result.hjson │ ├── strings3_result.hjson │ ├── strings4_result.hjson │ ├── strings_result.hjson │ ├── trail_result.hjson │ └── windowseol_result.hjson ├── comments3_result.hjson ├── comments3_result.json ├── comments3_test.hjson ├── comments4_result.hjson ├── comments4_result.json ├── comments4_test.hjson ├── comments5_result.hjson ├── comments5_result.json ├── comments5_test.hjson ├── comments6_result.hjson ├── comments6_result.json ├── comments6_test.hjson ├── comments7_result.hjson ├── comments7_result.json ├── comments7_test.hjson ├── comments_result.hjson ├── comments_result.json ├── comments_test.hjson ├── empty_result.hjson ├── empty_result.json ├── empty_test.hjson ├── failCharset1_test.hjson ├── failJSON02_test.json ├── failJSON05_test.json ├── failJSON06_test.json ├── failJSON07_test.json ├── failJSON08_test.json ├── failJSON10_test.json ├── failJSON11_test.json ├── failJSON12_test.json ├── failJSON13_test.json ├── failJSON14_test.json ├── failJSON15_test.json ├── failJSON16_test.json ├── failJSON17_test.json ├── failJSON19_test.json ├── failJSON20_test.json ├── failJSON21_test.json ├── failJSON22_test.json ├── failJSON23_test.json ├── failJSON26_test.json ├── failJSON28_test.json ├── failJSON29_test.json ├── failJSON30_test.json ├── failJSON31_test.json ├── failJSON32_test.json ├── failJSON33_test.json ├── failJSON34_test.json ├── failKey1_test.hjson ├── failKey2_test.hjson ├── failKey3_test.hjson ├── failKey4_test.hjson ├── failKey5_test.hjson ├── failMLStr1_test.hjson ├── failObj1_test.hjson ├── failObj2_test.hjson ├── failObj3_test.hjson ├── failObj4_test.hjson ├── failStr1a_test.hjson ├── failStr1b_test.hjson ├── failStr1c_test.hjson ├── failStr1d_test.hjson ├── failStr2a_test.hjson ├── failStr2b_test.hjson ├── failStr2c_test.hjson ├── failStr2d_test.hjson ├── failStr3a_test.hjson ├── failStr3b_test.hjson ├── failStr3c_test.hjson ├── failStr3d_test.hjson ├── failStr4a_test.hjson ├── failStr4b_test.hjson ├── failStr4c_test.hjson ├── failStr4d_test.hjson ├── failStr5a_test.hjson ├── failStr5b_test.hjson ├── failStr5c_test.hjson ├── failStr5d_test.hjson ├── failStr6a_test.hjson ├── failStr6b_test.hjson ├── failStr6c_test.hjson ├── failStr6d_test.hjson ├── failStr7a_test.hjson ├── failStr8a_test.hjson ├── failStr9a_test.hjson ├── int64_result.hjson ├── int64_result.json ├── int64_test.hjson ├── kan_result.hjson ├── kan_result.json ├── kan_test.hjson ├── keys_result.hjson ├── keys_result.json ├── keys_test.hjson ├── mltabs_result.hjson ├── mltabs_result.json ├── mltabs_test.json ├── oa_result.hjson ├── oa_result.json ├── oa_test.hjson ├── pass1_result.hjson ├── pass1_result.json ├── pass1_test.json ├── pass2_result.hjson ├── pass2_result.json ├── pass2_test.json ├── pass3_result.hjson ├── pass3_result.json ├── pass3_test.json ├── pass4_result.hjson ├── pass4_result.json ├── pass4_test.json ├── pass5_result.hjson ├── pass5_result.json ├── pass5_test.hjson ├── pass6_result.hjson ├── pass6_result.json ├── pass6_test.hjson ├── passSingle_result.hjson ├── passSingle_result.json ├── passSingle_test.hjson ├── root_result.hjson ├── root_result.json ├── root_test.hjson ├── sorted │ ├── charconv │ │ ├── pass5_result.hjson │ │ └── pass5_result.json │ ├── charset2_result.hjson │ ├── charset2_result.json │ ├── charset_result.hjson │ ├── charset_result.json │ ├── comments2_result.hjson │ ├── comments2_result.json │ ├── comments3_result.hjson │ ├── comments3_result.json │ ├── comments4_result.hjson │ ├── comments4_result.json │ ├── comments5_result.hjson │ ├── comments5_result.json │ ├── comments6_result.hjson │ ├── comments6_result.json │ ├── comments7_result.hjson │ ├── comments7_result.json │ ├── comments_result.hjson │ ├── comments_result.json │ ├── empty_result.hjson │ ├── empty_result.json │ ├── int64_result.hjson │ ├── int64_result.json │ ├── kan_result.hjson │ ├── kan_result.json │ ├── keys_result.hjson │ ├── keys_result.json │ ├── mltabs_result.hjson │ ├── mltabs_result.json │ ├── oa_result.hjson │ ├── oa_result.json │ ├── pass1_result.hjson │ ├── pass1_result.json │ ├── pass2_result.hjson │ ├── pass2_result.json │ ├── pass3_result.hjson │ ├── pass3_result.json │ ├── pass4_result.hjson │ ├── pass4_result.json │ ├── pass5_result.hjson │ ├── pass5_result.json │ ├── pass6_result.hjson │ ├── pass6_result.json │ ├── passSingle_result.hjson │ ├── passSingle_result.json │ ├── root_result.hjson │ ├── root_result.json │ ├── stringify1_result.hjson │ ├── stringify1_result.json │ ├── strings2_result.hjson │ ├── strings2_result.json │ ├── strings3_result.hjson │ ├── strings3_result.json │ ├── strings4_result.hjson │ ├── strings4_result.json │ ├── strings_result.hjson │ ├── strings_result.json │ ├── trail_result.hjson │ ├── trail_result.json │ ├── windowseol_result.hjson │ └── windowseol_result.json ├── stringify1_result.hjson ├── stringify1_result.json ├── stringify1_test.hjson ├── strings2_result.hjson ├── strings2_result.json ├── strings2_test.hjson ├── strings3_result.hjson ├── strings3_result.json ├── strings3_test.hjson ├── strings4_result.hjson ├── strings4_result.json ├── strings4_test.hjson ├── strings_result.hjson ├── strings_result.json ├── strings_test.hjson ├── testlist.txt ├── trail_result.hjson ├── trail_result.json ├── trail_test.hjson ├── windowseol_result.hjson ├── windowseol_result.json └── windowseol_test.hjson ├── hjson_test.h ├── test.cpp ├── test_marshal.cpp └── test_value.cpp /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | test: 14 | name: ${{ matrix.name }} 15 | runs-on: ${{ matrix.os }} 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | include: 20 | - name: linux-prev-release 21 | os: ubuntu-22.04 22 | env: 23 | BUILD_TYPE: Release 24 | - name: linux-latest-debug 25 | os: ubuntu-latest 26 | env: 27 | BUILD_TYPE: Debug 28 | HJSON_CXX_FLAGS: "-g -fsanitize=address -fsanitize=leak -fno-omit-frame-pointer -fstack-protector-all -fsanitize=undefined -fno-sanitize-recover" 29 | - name: linux-latest-release 30 | os: ubuntu-latest 31 | env: 32 | BUILD_TYPE: Release 33 | - name: linux-strtod 34 | os: ubuntu-latest 35 | env: 36 | BUILD_TYPE: Release 37 | HJSON_NUMBER_PARSER: StrToD 38 | - name: mac-release 39 | os: macos-latest 40 | env: 41 | BUILD_TYPE: Release 42 | - name: mac-strtod 43 | os: macos-latest 44 | env: 45 | BUILD_TYPE: Release 46 | HJSON_NUMBER_PARSER: StrToD 47 | - name: windows-debug 48 | os: windows-latest 49 | env: {} 50 | - name: windows-strtod 51 | os: windows-latest 52 | env: 53 | HJSON_NUMBER_PARSER: StrToD 54 | - name: windows-charconv 55 | os: windows-latest 56 | env: 57 | HJSON_NUMBER_PARSER: CharConv 58 | env: ${{ matrix.env }} 59 | steps: 60 | - uses: actions/checkout@v4 61 | - run: mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DHJSON_ENABLE_TEST=ON -DCMAKE_VERBOSE_MAKEFILE=ON -DHJSON_NUMBER_PARSER=${HJSON_NUMBER_PARSER} -DCMAKE_CXX_FLAGS="${HJSON_CXX_FLAGS}" .. && cmake --build . --target runtest 62 | shell: bash 63 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | if(${CMAKE_VERSION} VERSION_LESS 3.15) 4 | cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) 5 | else() 6 | cmake_policy(VERSION 3.15) 7 | endif() 8 | 9 | include_guard(GLOBAL) 10 | 11 | project(hjson 12 | VERSION 2.6 13 | DESCRIPTION "Human readable JSON" 14 | LANGUAGES CXX) 15 | 16 | if(MSVC) 17 | set(BUILD_WITH_STATIC_CRT "Manual flags" CACHE STRING "Use statically linked CRT") 18 | set_property(CACHE BUILD_WITH_STATIC_CRT PROPERTY STRINGS "Manual flags" "Yes" "No") 19 | include(cmake/msvc_crt.cmake) 20 | endif(MSVC) 21 | 22 | option(HJSON_ENABLE_TEST "Enable testing" OFF) 23 | option(HJSON_ENABLE_PERFTEST "Enable performance testing" OFF) 24 | option(HJSON_ENABLE_INSTALL "Enable installation" OFF) 25 | option(HJSON_VERSIONED_INSTALL "Include version in installation path" OFF) 26 | set(HJSON_NUMBER_PARSER "StringStream" CACHE STRING "Which number parsing tool to use") 27 | set_property(CACHE HJSON_NUMBER_PARSER PROPERTY STRINGS "StringStream" "StrToD" "CharConv") 28 | option(BUILD_SHARED_LIBS "Build shared libraries" OFF) 29 | option(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS "Needed for shared libs on Windows" ON) 30 | 31 | if(HJSON_VERSIONED_INSTALL) 32 | set(include_dest "include/hjson-${PROJECT_VERSION}") 33 | set(cmake_dest "lib/hjson-${PROJECT_VERSION}") 34 | set(lib_dest "lib/hjson-${PROJECT_VERSION}") 35 | else() 36 | set(include_dest "include/hjson") 37 | set(cmake_dest "lib/hjson") 38 | set(lib_dest "lib") 39 | endif() 40 | 41 | add_subdirectory(src) 42 | if(HJSON_ENABLE_TEST) 43 | add_subdirectory(test) 44 | endif() 45 | if(HJSON_ENABLE_PERFTEST) 46 | add_subdirectory(performance) 47 | endif() 48 | 49 | configure_file(cmake/hjson-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/hjson-config.cmake @ONLY) 50 | configure_file(cmake/hjson-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/hjson-config-version.cmake @ONLY) 51 | 52 | export(TARGETS hjson FILE "${CMAKE_BINARY_DIR}/hjson.cmake") 53 | 54 | if(HJSON_ENABLE_INSTALL) 55 | install(FILES 56 | ${CMAKE_CURRENT_BINARY_DIR}/hjson-config.cmake 57 | ${CMAKE_CURRENT_BINARY_DIR}/hjson-config-version.cmake 58 | DESTINATION ${cmake_dest} 59 | ) 60 | 61 | install(EXPORT hjson DESTINATION ${cmake_dest}) 62 | endif() 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016, 2017 Christian Zangl, Fredrik Trobro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cmake/hjson-config-version.cmake.in: -------------------------------------------------------------------------------- 1 | # hjson-config-version.cmake - checks version: major must match, minor must be less than or equal 2 | 3 | set(PACKAGE_VERSION @PROJECT_VERSION@) 4 | 5 | if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "0") 6 | # Anything goes. 7 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 8 | elseif("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "@PROJECT_VERSION_MAJOR@") 9 | if ("${PACKAGE_FIND_VERSION_MINOR}" EQUAL "@PROJECT_VERSION_MINOR@") 10 | set(PACKAGE_VERSION_EXACT TRUE) 11 | elseif("${PACKAGE_FIND_VERSION_MINOR}" LESS "@PROJECT_VERSION_MINOR@") 12 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 13 | else() 14 | set(PACKAGE_VERSION_UNSUITABLE TRUE) 15 | endif() 16 | else() 17 | set(PACKAGE_VERSION_UNSUITABLE TRUE) 18 | endif() 19 | -------------------------------------------------------------------------------- /cmake/hjson-config.cmake.in: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/hjson.cmake) 2 | -------------------------------------------------------------------------------- /cmake/msvc_crt.cmake: -------------------------------------------------------------------------------- 1 | if(NOT MSVC) 2 | message(FATAL_ERROR "CRT options are available only for MSVC") 3 | endif() 4 | 5 | if(${BUILD_WITH_STATIC_CRT} MATCHES "Yes") 6 | foreach(flag_var 7 | CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE 8 | CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO 9 | CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE 10 | CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) 11 | if(${flag_var} MATCHES "/MD") 12 | string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") 13 | endif() 14 | if(${flag_var} MATCHES "/MDd") 15 | string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}") 16 | endif() 17 | set(${flag_var} "${${flag_var}}" CACHE STRING "" FORCE) 18 | endforeach(flag_var) 19 | 20 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcrtd.lib") 21 | set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:libcmt.lib") 22 | set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:libcmtd.lib") 23 | elseif(${BUILD_WITH_STATIC_CRT} MATCHES "No") 24 | foreach(flag_var 25 | CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE 26 | CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO 27 | CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE 28 | CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) 29 | if(${flag_var} MATCHES "/MT") 30 | string(REGEX REPLACE "/MT" "/MD" ${flag_var} "${${flag_var}}") 31 | endif() 32 | if(${flag_var} MATCHES "/MTd") 33 | string(REGEX REPLACE "/MTd" "/MDd" ${flag_var} "${${flag_var}}") 34 | endif() 35 | set(${flag_var} "${${flag_var}}" CACHE STRING "" FORCE) 36 | endforeach(flag_var) 37 | endif() 38 | -------------------------------------------------------------------------------- /include/hjson/hjson.h: -------------------------------------------------------------------------------- 1 | #ifndef HJSON_AFOWENFOWANEFWOAFNLL 2 | #define HJSON_AFOWENFOWANEFWOAFNLL 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define HJSON_OP_DECL_VAL(_T, _O) \ 11 | friend Value operator _O(_T, const Value&); \ 12 | friend Value operator _O(const Value&, _T); 13 | 14 | #define HJSON_OP_DECL_BOOL(_T, _O) \ 15 | friend bool operator _O(_T, const Value&); \ 16 | friend bool operator _O(const Value&, _T); 17 | 18 | #define HJSON_OP_DECL_ASS(_T, _O) \ 19 | Value& operator _O(_T); 20 | 21 | #define HJSON_OPERATORS_DECLARATION_A(_T) \ 22 | HJSON_OP_DECL_BOOL(_T, <) \ 23 | HJSON_OP_DECL_BOOL(_T, >) \ 24 | HJSON_OP_DECL_BOOL(_T, <=) \ 25 | HJSON_OP_DECL_BOOL(_T, >=) \ 26 | HJSON_OP_DECL_BOOL(_T, ==) \ 27 | HJSON_OP_DECL_BOOL(_T, !=) \ 28 | HJSON_OP_DECL_ASS(_T, +=) 29 | 30 | #define HJSON_OPERATORS_DECLARATION_B(_T) \ 31 | HJSON_OPERATORS_DECLARATION_A(_T) \ 32 | HJSON_OP_DECL_VAL(_T, +) \ 33 | HJSON_OP_DECL_VAL(_T, -) \ 34 | HJSON_OP_DECL_VAL(_T, *) \ 35 | HJSON_OP_DECL_VAL(_T, /) \ 36 | HJSON_OP_DECL_ASS(_T, -=) \ 37 | HJSON_OP_DECL_ASS(_T, *=) \ 38 | HJSON_OP_DECL_ASS(_T, /=) 39 | 40 | #define HJSON_OPERATORS_DECLARATION_C(_T) \ 41 | HJSON_OPERATORS_DECLARATION_B(_T) \ 42 | HJSON_OP_DECL_VAL(_T, %) \ 43 | HJSON_OP_DECL_ASS(_T, %=) 44 | 45 | 46 | namespace Hjson { 47 | 48 | 49 | class type_mismatch : public std::logic_error { 50 | using std::logic_error::logic_error; 51 | }; 52 | 53 | 54 | class index_out_of_bounds : public std::out_of_range { 55 | using std::out_of_range::out_of_range; 56 | }; 57 | 58 | 59 | class syntax_error : public std::runtime_error { 60 | using std::runtime_error::runtime_error; 61 | }; 62 | 63 | 64 | class file_error : public std::runtime_error { 65 | using std::runtime_error::runtime_error; 66 | }; 67 | 68 | 69 | enum class Type { 70 | Undefined, 71 | Null, 72 | Bool, 73 | Double, 74 | Int64, 75 | String, 76 | Vector, 77 | Map 78 | }; 79 | 80 | 81 | // DecoderOptions defines options for decoding from Hjson. 82 | struct DecoderOptions { 83 | // Keep all comments from the Hjson input, store them in 84 | // the Hjson::Value objects. 85 | bool comments = true; 86 | // Store all whitespace and comments in the Hjson::Value objects so that 87 | // linefeeds and custom indentation is kept. The "comments" option is 88 | // ignored if this option is true. 89 | bool whitespaceAsComments = false; 90 | // If true, an Hjson::syntax_error exception is thrown from the unmarshal 91 | // functions if a map contains duplicate keys. 92 | bool duplicateKeyException = false; 93 | }; 94 | 95 | 96 | // EncoderOptions defines options for encoding to Hjson. 97 | struct EncoderOptions { 98 | // End of line, should be either \n or \r\n 99 | std::string eol = "\n"; 100 | // Place braces on the same line 101 | bool bracesSameLine = true; 102 | // Always place string values in double quotation marks ("), and escape 103 | // any special chars inside the string value 104 | bool quoteAlways = false; 105 | // Always place keys in quotes 106 | bool quoteKeys = false; 107 | // Indent string 108 | std::string indentBy = " "; 109 | // Allow the -0 value (unlike ES6) 110 | bool allowMinusZero = false; 111 | // Encode unknown values as 'null' 112 | bool unknownAsNull = false; 113 | // Output a comma separator between elements. If true, always place strings 114 | // in quotes (overriding the "quoteAlways" setting). 115 | bool separator = false; 116 | // Only affects the order of elements in objects. If true, the key/value 117 | // pairs for all objects will be placed in the same order as they were added. 118 | // If false, the key/value pairs are placed in alphabetical key order. 119 | bool preserveInsertionOrder = true; 120 | // If true, omits root braces. 121 | bool omitRootBraces = false; 122 | // Write comments, if any are found in the Hjson::Value objects. 123 | bool comments = true; 124 | }; 125 | 126 | 127 | class MapProxy; 128 | 129 | 130 | class Value { 131 | friend class MapProxy; 132 | 133 | private: 134 | class ValueImpl; 135 | class Comments; 136 | 137 | std::shared_ptr prv; 138 | std::shared_ptr cm; 139 | 140 | Value(std::shared_ptr, std::shared_ptr); 141 | 142 | public: 143 | Value(); 144 | Value(bool); 145 | Value(float); 146 | Value(double); 147 | Value(long double); 148 | Value(char); 149 | Value(unsigned char); 150 | Value(short); 151 | Value(unsigned short); 152 | Value(int); 153 | Value(unsigned int); 154 | Value(long); 155 | Value(unsigned long); 156 | Value(long long); 157 | Value(unsigned long long); 158 | Value(const char*); 159 | Value(const std::string&); 160 | Value(Type); 161 | Value(const Value&); 162 | Value(Value&&); 163 | Value(MapProxy&&); 164 | virtual ~Value(); 165 | 166 | Value& operator =(const Value&); 167 | Value& operator =(Value&&); 168 | 169 | const Value operator[](const std::string&) const; 170 | MapProxy operator[](const std::string&); 171 | const Value operator[](const char*) const; 172 | MapProxy operator[](const char*); 173 | const Value operator[](char*) const; 174 | MapProxy operator[](char*); 175 | const Value& operator[](int) const; 176 | Value& operator[](int); 177 | 178 | bool operator ==(bool) const; 179 | bool operator !=(bool) const; 180 | 181 | friend std::string operator +(const char*, const Value&); 182 | friend std::string operator +(const Value&, const char*); 183 | friend std::string operator +(const std::string&, const Value&); 184 | friend std::string operator +(const Value&, const std::string&); 185 | 186 | HJSON_OPERATORS_DECLARATION_A(const char*) 187 | HJSON_OPERATORS_DECLARATION_A(const std::string&) 188 | HJSON_OPERATORS_DECLARATION_B(float) 189 | HJSON_OPERATORS_DECLARATION_B(double) 190 | HJSON_OPERATORS_DECLARATION_B(long double) 191 | HJSON_OPERATORS_DECLARATION_C(char) 192 | HJSON_OPERATORS_DECLARATION_C(unsigned char) 193 | HJSON_OPERATORS_DECLARATION_C(short) 194 | HJSON_OPERATORS_DECLARATION_C(unsigned short) 195 | HJSON_OPERATORS_DECLARATION_C(int) 196 | HJSON_OPERATORS_DECLARATION_C(unsigned int) 197 | HJSON_OPERATORS_DECLARATION_C(long) 198 | HJSON_OPERATORS_DECLARATION_C(unsigned long) 199 | HJSON_OPERATORS_DECLARATION_C(long long) 200 | HJSON_OPERATORS_DECLARATION_C(unsigned long long) 201 | HJSON_OPERATORS_DECLARATION_C(const Value&) 202 | 203 | Value operator +() const; 204 | Value operator -() const; 205 | Value& operator ++(); 206 | Value& operator --(); 207 | Value operator ++(int); 208 | Value operator --(int); 209 | 210 | explicit operator bool() const; 211 | operator float() const; 212 | operator double() const; 213 | operator long double() const; 214 | operator char() const; 215 | operator unsigned char() const; 216 | operator short() const; 217 | operator unsigned short() const; 218 | operator int() const; 219 | operator unsigned int() const; 220 | operator long() const; 221 | operator unsigned long() const; 222 | operator long long() const; 223 | operator unsigned long long() const; 224 | operator const char*() const; 225 | operator std::string() const; 226 | 227 | // Like `Marshal(Value)` but outputs the result to the stream. 228 | friend std::ostream& operator <<(std::ostream&, const Value&); 229 | // Like `Unmarshal(std::string)` but from the stream. 230 | friend std::istream& operator >>(std::istream&, Value&); 231 | 232 | // Returns the type of this Value. 233 | Type type() const; 234 | // Returns true if the type of this Value is anything else than Undefined. 235 | bool defined() const; 236 | // Returns true if this Value is of type Vector or Map and has zero child 237 | // elements. Returns true if this Value is of type String and contains 238 | // zero characters. Returns true if this Value is of type Undefined or Null. 239 | // Returns false in all other cases. 240 | bool empty() const; 241 | // Returns true if the type of this Value is Vector or Map. 242 | bool is_container() const; 243 | // Returns true if the type of this Value is Double or Int64. 244 | bool is_numeric() const; 245 | // Returns true if the entire tree for which this Value is the root is equal 246 | // to the entire tree for which the Value parameter is root. Comments are 247 | // ignored in the comparison. 248 | bool deep_equal(const Value&) const; 249 | // Returns a full clone of the tree for which this Value is the root. 250 | Value clone() const; 251 | 252 | // -- Vector and Map specific functions 253 | // Removes all child elements from this Value if it is of type Vector or Map. 254 | // Does nothing if this Value is of any other type. 255 | void clear(); 256 | // Removes one child element from a Value of type Vector or Map. For a 257 | // Vector, the input argument is the index in the vector for the value 258 | // that should be erased. For a Map, the input argument is the index in the 259 | // insertion order of the MAP for the value that should be erased. Throws 260 | // Hjson::index_out_of_bounds if the index is out of bounds and this Value 261 | // is of type Undefined, Vector or Map. Throws Hjson::type_mismatch if this 262 | // Value is of any other type. 263 | void erase(int); 264 | // Move value on index `from` to index `to`. If `from` is less than `to` the 265 | // element will actually end up at index `to - 1`. For an Hjson::Value of 266 | // type Map, calling this function changes the insertion order but does not 267 | // affect the iteration order, since iterations are always done in 268 | // alphabetical key order. Throws Hjson::index_out_of_bounds if the index is 269 | // out of bounds and this Value is of type Undefined, Vector or Map. Throws 270 | // Hjson::type_mismatch if this Value is of any other type. 271 | void move(int from, int to); 272 | // Returns the number of child elements contained in this Value if this Value 273 | // is of type Vector or Map. Returns 0 if this Value is of any other type. 274 | size_t size() const; 275 | 276 | // -- Vector specific function 277 | // Increases the size of this Vector by adding a Value at the end. Throws 278 | // Hjson::type_mismatch if this Value is of any other type than Vector or 279 | // Undefined. 280 | void push_back(const Value&); 281 | 282 | // -- Map specific functions 283 | // Get key by its zero-based insertion index. Throws 284 | // Hjson::index_out_of_bounds if the index is out of bounds and this Value is 285 | // of type Undefined or Map. Throws Hjson::type_mismatch if this Value is of 286 | // any other type. 287 | std::string key(int) const; 288 | // Returns a reference to the Value specified by the key parameter. Throws 289 | // Hjson::index_out_of_bounds if this Value does not contain the specified 290 | // key and this Value is of type Undefined or Map. Throws 291 | // Hjson::type_mismatch if this Value is of any other type. 292 | const Value& at(const std::string& key) const; 293 | Value& at(const std::string& key); 294 | const Value& at(const char *key) const; 295 | Value& at(const char *key); 296 | // Iterations are always done in alphabetical key order. Returns a default 297 | // constructed iterator if this Value is of any other type than Map. 298 | std::map::iterator begin(); 299 | std::map::iterator end(); 300 | std::map::const_iterator begin() const; 301 | std::map::const_iterator end() const; 302 | // Removes the child element specified by the input key if this Value is of 303 | // type Map. Returns the number of erased elements (0 or 1). Throws 304 | // Hjson::type_mismatch if this Value is of any other type than Map or 305 | // Undefined. 306 | size_t erase(const std::string&); 307 | size_t erase(const char*); 308 | 309 | // These functions throw an error if used on Vector or Map, but will return 310 | // 0 or 0.0 for the types Undefined and Null. Will parse strings to numbers 311 | // and print numbers to strings if necessary. 312 | double to_double() const; 313 | std::int64_t to_int64() const; 314 | std::string to_string() const; 315 | 316 | // Sets comment shown before this Value. If this Value is an element in a 317 | // Map, the comment is shown before the key. 318 | void set_comment_before(const std::string&); 319 | std::string get_comment_before() const; 320 | // Sets comment shown between the key and this Value. If this Value is 321 | // not an element in a Map, the comment is shown between the "before" 322 | // comment and this Value. 323 | void set_comment_key(const std::string&); 324 | std::string get_comment_key() const; 325 | // Sets comment shown right after "[" if this Value is a Vector, or right 326 | // after "{" if this Value is a Map. The comment is not shown if this Value 327 | // is of any other type than Vector or Map. 328 | void set_comment_inside(const std::string&); 329 | std::string get_comment_inside() const; 330 | // Sets comment shown after this Value. 331 | void set_comment_after(const std::string&); 332 | std::string get_comment_after() const; 333 | 334 | // Copies all comments from the other Hjson::Value. 335 | void set_comments(const Value&); 336 | // Removes all comments from this Value. 337 | void clear_comments(); 338 | // A combination of the assignment operator (=) and set_comments(). The 339 | // normal assignment operator (=) will not change any comments, unless the 340 | // receiving Value is of type Undefined. 341 | Value& assign_with_comments(const Value&); 342 | Value& assign_with_comments(Value&&); 343 | }; 344 | 345 | 346 | // MapProxy is only used for temporary references to elements in a Map. It is 347 | // not possible to store a MapProxy in a variable. It only exists to make it 348 | // possible to check for the existence of a specific key in a Map without 349 | // creating an empty element in the Map with that key. 350 | class MapProxy : public Value { 351 | friend class Value; 352 | 353 | private: 354 | std::shared_ptr parentPrv; 355 | std::string key; 356 | Value *pTarget; 357 | // True if an explicit assignment has been made to this MapProxy. 358 | bool wasAssigned; 359 | 360 | MapProxy(std::shared_ptr parent, const std::string& key, 361 | Value *pTarget); 362 | 363 | // Make the copy constructor private in order to avoid accidental creation of 364 | // MapProxy variables like this: 365 | // auto myVal = val["one"]; 366 | MapProxy(const MapProxy&) = default; 367 | MapProxy(Value&&); 368 | 369 | public: 370 | ~MapProxy() override; 371 | MapProxy& operator =(const MapProxy&); 372 | MapProxy& operator =(const Value&); 373 | MapProxy& operator =(Value&&); 374 | MapProxy& assign_with_comments(const MapProxy&); 375 | MapProxy& assign_with_comments(const Value&); 376 | MapProxy& assign_with_comments(Value&&); 377 | }; 378 | 379 | 380 | class StreamEncoder { 381 | public: 382 | const Value& v; 383 | const EncoderOptions& o; 384 | 385 | StreamEncoder(const Value&, const EncoderOptions&); 386 | 387 | // Like `Marshal(Value, EncoderOptions)` but outputs the result to the stream. 388 | friend std::ostream& operator <<(std::ostream&, const StreamEncoder&); 389 | }; 390 | 391 | 392 | class StreamDecoder { 393 | public: 394 | Value& v; 395 | const DecoderOptions& o; 396 | 397 | StreamDecoder(Value&, const DecoderOptions&); 398 | 399 | // Like `Unmarshal(std::string, DecoderOptions)` but from a stream. 400 | friend std::istream& operator >>(std::istream&, StreamDecoder&); 401 | // Like `Unmarshal(std::string, DecoderOptions)` but from a stream. 402 | friend std::istream& operator >>(std::istream&, StreamDecoder&&); 403 | }; 404 | 405 | 406 | // Returns a properly indented text representation of the input value tree. 407 | // Extra options can be specified in the input parameter "options". 408 | std::string Marshal(const Value& v, const EncoderOptions& options = EncoderOptions()); 409 | 410 | // Writes (in binary mode, so using Unix EOL) a properly indented text 411 | // representation of the input value tree to the file specified by the input 412 | // parameter "path". Extra options can be specified in the input parameter 413 | // "options". Throws Hjson::file_error if the file cannot be opened for writing. 414 | void MarshalToFile(const Value& v, const std::string& path, 415 | const EncoderOptions& options = EncoderOptions()); 416 | 417 | // Returns a properly indented JSON text representation of the input value 418 | // tree. 419 | std::string MarshalJson(const Value&); 420 | 421 | // Creates a Value tree from input text. 422 | Value Unmarshal(const char *data, size_t dataSize, 423 | const DecoderOptions& options = DecoderOptions()); 424 | 425 | // Creates a Value tree from input text. 426 | // The input parameter "data" must be null-terminated. 427 | Value Unmarshal(const char *data, const DecoderOptions& options = DecoderOptions()); 428 | 429 | // Creates a Value tree from input text. 430 | Value Unmarshal(const std::string& data, 431 | const DecoderOptions& options = DecoderOptions()); 432 | 433 | // Reads the entire file (in binary mode) and unmarshals it. Throws 434 | // Hjson::file_error if the file cannot be opened for reading. 435 | Value UnmarshalFromFile(const std::string& path, 436 | const DecoderOptions& options = DecoderOptions()); 437 | 438 | // Returns a Value tree that is a combination of the input parameters "base" 439 | // and "ext". 440 | // 441 | // If "base" and "ext" contain a map on the same place in the tree, the 442 | // returned tree will on that place have a map containing a combination of 443 | // all keys from the "base" and "ext" maps. If a key existed in both "base" 444 | // and "ext", the value from "ext" is used. Except for if the value in "ext" 445 | // is of type Undefined: then the value from "base" is used. 446 | // 447 | // Vectors are not merged: if a vector exists in the same place in the "base" 448 | // and "ext" trees, the one from "ext" will be used in the returned tree. 449 | // 450 | // Maps and vectors are cloned, not copied. Therefore changes in the returned 451 | // tree will not affect the input variables "base" and "ext. 452 | // 453 | // If "ext" is of type Undefined, a clone of "base" is returned. 454 | // 455 | Value Merge(const Value& base, const Value& ext); 456 | 457 | 458 | } 459 | 460 | 461 | #endif 462 | -------------------------------------------------------------------------------- /performance/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Threads REQUIRED) 2 | 3 | add_executable(perfbin 4 | perf.cpp 5 | perf_multithread.cpp 6 | ) 7 | 8 | target_compile_features(perfbin PUBLIC cxx_std_11) 9 | 10 | target_link_libraries(perfbin hjson Threads::Threads) 11 | 12 | add_custom_target(runperf 13 | COMMAND perfbin 14 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} 15 | ) 16 | -------------------------------------------------------------------------------- /performance/perf.cpp: -------------------------------------------------------------------------------- 1 | void perf_multithread(); 2 | 3 | 4 | int main() { 5 | perf_multithread(); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /performance/perf_multithread.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | static int _run_test() { 11 | int loopCount = 0; 12 | 13 | std::string inString = R"( 14 | { 15 | # the comma forces a whitespace check 16 | numbers: 17 | [ 18 | 0 19 | 0 , 20 | -0 21 | 42 , 22 | 42.1 , 23 | -5 24 | -5.1 25 | 17.01e2 26 | -17.01e2 27 | 12345e-3 , 28 | -12345e-3 , 29 | ] 30 | native: 31 | [ 32 | true , 33 | true 34 | false , 35 | false 36 | null , 37 | null 38 | ] 39 | strings: 40 | [ 41 | x 0 42 | .0 43 | 00 44 | 01 45 | 0 0 0 46 | 42 x 47 | 42.1 asdf 48 | 1.2.3 49 | -5 0 - 50 | -5.1 -- 51 | 17.01e2 + 52 | -17.01e2 : 53 | 12345e-3 @ 54 | -12345e-3 $ 55 | true true 56 | x true 57 | false false 58 | x false 59 | null null 60 | x null 61 | ] 62 | } 63 | )"; 64 | 65 | for (int a = 0; a < 10000; ++a) { 66 | auto root = Hjson::Unmarshal(inString); 67 | 68 | // Fewer marshals, because it is slower. 69 | if ((a & 0x11) == 0x11) { 70 | auto str = Hjson::Marshal(root); 71 | if (str.at(0) == '{') { 72 | ++loopCount; 73 | } 74 | } else if (!root.empty()) { 75 | ++loopCount; 76 | } 77 | } 78 | 79 | return loopCount; 80 | } 81 | 82 | 83 | void perf_multithread() { 84 | std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); 85 | std::vector > futures; 86 | int loopCount = 0; 87 | 88 | for (int a = 0; a < 16; ++a) { 89 | futures.push_back(std::async(_run_test)); 90 | } 91 | 92 | for (auto &fut : futures) { 93 | loopCount += fut.get(); 94 | } 95 | 96 | std::chrono::steady_clock::time_point stop = std::chrono::steady_clock::now(); 97 | 98 | std::cout << "Runtime: " << std::chrono::duration(stop - 99 | start).count() << " seconds" << std::endl; 100 | 101 | // Also output total first level element count, to prove that the unmarshal 102 | // calls have not been optimized away. 103 | std::cout << "Total loop count: " << loopCount << std::endl; 104 | } 105 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(header_path "${PROJECT_SOURCE_DIR}/include/hjson") 2 | set(header ${header_path}/hjson.h) 3 | 4 | set(src 5 | hjson_decode.cpp 6 | hjson_encode.cpp 7 | hjson_parsenumber.cpp 8 | hjson_value.cpp 9 | ) 10 | 11 | add_library(hjson ${header} ${src}) 12 | 13 | target_include_directories(hjson PUBLIC 14 | $ 15 | $ 16 | ) 17 | 18 | if(${HJSON_NUMBER_PARSER} MATCHES "CharConv") 19 | target_compile_features(hjson PUBLIC cxx_std_17) 20 | target_compile_definitions(hjson PRIVATE HJSON_USE_CHARCONV=1) 21 | else() 22 | if(${HJSON_NUMBER_PARSER} MATCHES "StrToD") 23 | target_compile_definitions(hjson PRIVATE HJSON_USE_STRTOD=1) 24 | endif() 25 | 26 | target_compile_features(hjson PUBLIC cxx_std_11) 27 | endif() 28 | 29 | set_target_properties(hjson PROPERTIES 30 | VERSION ${PROJECT_VERSION} 31 | SOVERSION ${PROJECT_VERSION_MAJOR} 32 | DEBUG_POSTFIX "d" 33 | ) 34 | 35 | if(HJSON_ENABLE_INSTALL) 36 | install(TARGETS hjson EXPORT hjson DESTINATION ${lib_dest}) 37 | install(FILES ${header} DESTINATION ${include_dest}) 38 | endif() 39 | -------------------------------------------------------------------------------- /src/hjson_encode.cpp: -------------------------------------------------------------------------------- 1 | #include "hjson.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | namespace Hjson { 12 | 13 | 14 | enum class EncodeState { 15 | ValueBegin, 16 | ValueEnd, 17 | VectorElemBegin, 18 | MapElemBegin, 19 | }; 20 | 21 | 22 | class EncodeParent { 23 | public: 24 | EncodeParent(const Value *_pVal) : pVal(_pVal), index(0), isEmpty(true) {} 25 | const Value *pVal; 26 | int index; 27 | bool isEmpty; 28 | std::string commentAfter; 29 | std::map::const_iterator it; 30 | }; 31 | 32 | 33 | struct Encoder { 34 | EncoderOptions opt; 35 | std::ostream *os; 36 | std::locale loc; 37 | int indent; 38 | std::regex needsEscape, needsQuotes, needsEscapeML, startsWithKeyword, 39 | needsEscapeName, lineBreak; 40 | std::vector vState; 41 | std::vector vParent; 42 | }; 43 | 44 | 45 | bool startsWithNumber(const char *text, size_t textSize); 46 | 47 | 48 | // table of character substitutions 49 | static const char *_meta(char c) { 50 | switch (c) 51 | { 52 | case '\b': 53 | return "\\b"; 54 | case '\t': 55 | return "\\t"; 56 | case '\n': 57 | return "\\n"; 58 | case '\f': 59 | return "\\f"; 60 | case '\r': 61 | return "\\r"; 62 | case '"': 63 | return "\\\""; 64 | case '\\': 65 | return "\\\\"; 66 | } 67 | 68 | return 0; 69 | } 70 | 71 | 72 | static void _writeIndent(Encoder *e, int indent) { 73 | *e->os << e->opt.eol; 74 | 75 | if (!e->opt.indentBy.empty()) { 76 | for (int i = 0; i < indent; i++) { 77 | *e->os << e->opt.indentBy; 78 | } 79 | } 80 | } 81 | 82 | 83 | static int _fromUtf8(const unsigned char **ppC, size_t *pnS) { 84 | int nS, nRet; 85 | const unsigned char *pC = *ppC; 86 | 87 | if (!*pnS) { 88 | return -1; 89 | } 90 | 91 | if (*pC < 0x80) { 92 | nS = 1; 93 | nRet = *pC++; 94 | } else if (*pC < 0xc0) { 95 | return -1; 96 | } else if (*pC < 0xe0) { 97 | nS = 2; 98 | nRet = *pC++ & 0x1f; 99 | } else if (*pC < 0xf0) { 100 | nS = 3; 101 | nRet = *pC++ & 0xf; 102 | } else if (*pC < 0xf8) { 103 | nS = 4; 104 | nRet = *pC++ & 0x7; 105 | } else { 106 | return -1; 107 | } 108 | 109 | if (*pnS < nS) { 110 | return -1; 111 | } 112 | 113 | for (int a = nS - 1; a; --a) { 114 | if (*pC < 0x80) { 115 | return -1; 116 | } 117 | nRet = (nRet << 6) | (*pC++ & 0x3f); 118 | } 119 | 120 | pnS[0] -= nS; 121 | *ppC = pC; 122 | 123 | return nRet; 124 | } 125 | 126 | 127 | static void _quoteReplace(Encoder *e, const std::string& text) { 128 | size_t uIndexStart = 0; 129 | 130 | for (std::sregex_iterator it = std::sregex_iterator(text.begin(), text.end(), 131 | e->needsEscape); it != std::sregex_iterator(); ++it) 132 | { 133 | std::smatch match = *it; 134 | const char *szReplacement = _meta(match.str()[0]); 135 | 136 | if (size_t(match.position()) > uIndexStart) { 137 | // Append non-matching text. 138 | *e->os << text.substr(uIndexStart, match.position() - uIndexStart); 139 | } 140 | 141 | if (szReplacement) { 142 | *e->os << szReplacement; 143 | } else { 144 | const char *pC = text.data() + match.position(); 145 | size_t nS = match.length(); 146 | 147 | *e->os << std::hex << std::setfill('0'); 148 | while (nS) { 149 | int nRet = _fromUtf8((const unsigned char**) &pC, &nS); 150 | if (nRet < 0) { 151 | // Not UTF8. Just dump it. 152 | *e->os << std::string(pC, nS); 153 | break; 154 | } 155 | *e->os << "\\u" << std::setw(4) << nRet; 156 | } 157 | } 158 | 159 | uIndexStart = match.position() + match.length(); 160 | } 161 | 162 | if (uIndexStart < text.length()) { 163 | // Append remaining text. 164 | *e->os << text.substr(uIndexStart, text.length() - uIndexStart); 165 | } 166 | } 167 | 168 | 169 | // wrap the string into the ''' (multiline) format 170 | static void _mlString(Encoder *e, const std::string& value) { 171 | size_t uIndexStart = 0; 172 | std::sregex_iterator it = std::sregex_iterator(value.begin(), value.end(), 173 | e->lineBreak); 174 | 175 | if (it == std::sregex_iterator()) { 176 | if (e->vState.size() > 1 && e->vState[e->vState.size() - 2] == EncodeState::MapElemBegin && ( 177 | !e->opt.comments || e->vParent.back().pVal->get_comment_key().empty())) 178 | { 179 | *e->os << " "; 180 | } 181 | // The string contains only a single line. We still use the multiline 182 | // format as it avoids escaping the \ character (e.g. when used in a 183 | // regex). 184 | *e->os << "'''"; 185 | *e->os << value; 186 | } else { 187 | _writeIndent(e, e->indent + 1); 188 | *e->os << "'''"; 189 | 190 | do { 191 | std::smatch match = *it; 192 | auto indent = e->indent + 1; 193 | if (match.position() == uIndexStart) { 194 | indent = 0; 195 | } 196 | _writeIndent(e, indent); 197 | if (size_t(match.position()) > uIndexStart) { 198 | *e->os << value.substr(uIndexStart, match.position() - uIndexStart); 199 | } 200 | uIndexStart = match.position() + match.length(); 201 | ++it; 202 | } while (it != std::sregex_iterator()); 203 | 204 | if (uIndexStart < value.length()) { 205 | // Append remaining text. 206 | _writeIndent(e, e->indent + 1); 207 | *e->os << value.substr(uIndexStart, value.length() - uIndexStart); 208 | } else { 209 | // Trailing line feed. 210 | _writeIndent(e, 0); 211 | } 212 | 213 | _writeIndent(e, e->indent + 1); 214 | } 215 | 216 | *e->os << "'''"; 217 | } 218 | 219 | 220 | // Check if we can insert this string without quotes 221 | // see hjson syntax (must not parse as true, false, null or number) 222 | static void _quote(Encoder *e, const std::string& value, 223 | bool hasCommentAfter) 224 | { 225 | bool bSep = false; 226 | if (e->vState.size() > 1 && e->vState[e->vState.size() - 2] == EncodeState::MapElemBegin && ( 227 | !e->opt.comments || e->vParent.back().pVal->get_comment_key().empty())) 228 | { 229 | bSep = true; 230 | } 231 | 232 | if (value.size() == 0) { 233 | if (bSep) { 234 | *e->os << " "; 235 | } 236 | *e->os << "\"\""; 237 | } else if (e->opt.quoteAlways || 238 | std::regex_search(value, e->needsQuotes) || 239 | startsWithNumber(value.c_str(), value.size()) || 240 | std::regex_search(value, e->startsWithKeyword) || 241 | hasCommentAfter) 242 | { 243 | 244 | // If the string contains no control characters, no quote characters, and no 245 | // backslash characters, then we can safely slap some quotes around it. 246 | // Otherwise we first check if the string can be expressed in multiline 247 | // format or we must replace the offending characters with safe escape 248 | // sequences. 249 | 250 | if (!std::regex_search(value, e->needsEscape)) { 251 | if (bSep) { 252 | *e->os << " "; 253 | } 254 | *e->os << '"' << value << '"'; 255 | } else if (!e->opt.quoteAlways && !std::regex_search(value, 256 | e->needsEscapeML) && e->vParent.size() > 1) 257 | { 258 | _mlString(e, value); 259 | } else { 260 | if (bSep) { 261 | *e->os << " "; 262 | } 263 | *e->os << '"'; 264 | _quoteReplace(e, value); 265 | *e->os << '"'; 266 | } 267 | } else { 268 | if (bSep) { 269 | *e->os << " "; 270 | } 271 | // return without quotes 272 | *e->os << value; 273 | } 274 | } 275 | 276 | 277 | static void _quoteName(Encoder *e, const std::string& name) { 278 | if (name.empty()) { 279 | *e->os << "\"\""; 280 | } else if (e->opt.quoteKeys || std::regex_search(name, e->needsEscapeName) || 281 | std::regex_search(name, e->needsEscape)) 282 | { 283 | *e->os << '"'; 284 | _quoteReplace(e, name); 285 | *e->os << '"'; 286 | } else { 287 | // without quotes 288 | *e->os << name; 289 | } 290 | } 291 | 292 | 293 | static bool _quoteForComment(Encoder *e, const std::string& comment) { 294 | if (!e->opt.comments) { 295 | return false; 296 | } 297 | 298 | for (char ch : comment) { 299 | switch (ch) 300 | { 301 | case '\r': 302 | case '\n': 303 | return false; 304 | case '/': 305 | case '#': 306 | return true; 307 | default: 308 | break; 309 | } 310 | } 311 | 312 | return false; 313 | } 314 | 315 | 316 | // Returns true if we are inside a comment after outputting the string 317 | // (i.e. the string contains an unterminated line comment). 318 | // Also returns true for '/* # */' and similar, but that should be uncommon and 319 | // will only cause an unnecessary line feed after the comment. 320 | static bool _isInComment(const std::string& comment) { 321 | bool endsInsideComment = false; 322 | char prev = ' '; 323 | 324 | for (char ch : comment) { 325 | switch (ch) { 326 | case '\n': 327 | endsInsideComment = false; 328 | break; 329 | case '#': 330 | endsInsideComment = true; 331 | break; 332 | case '/': 333 | if (prev == '/') { 334 | endsInsideComment = true; 335 | } 336 | break; 337 | } 338 | prev = ch; 339 | } 340 | 341 | return endsInsideComment; 342 | } 343 | 344 | 345 | // Produce a string from value. 346 | static void _writeValueBegin(Encoder *e) { 347 | const Value &value = *e->vParent.back().pVal; 348 | 349 | if (e->opt.comments) { 350 | *e->os << value.get_comment_key(); 351 | } 352 | 353 | switch (value.type()) { 354 | case Type::Double: 355 | if (std::isnan(static_cast(value)) || std::isinf(static_cast(value))) { 356 | *e->os << Value(Type::Null).to_string(); 357 | } else if (!e->opt.allowMinusZero && value == 0 && std::signbit(static_cast(value))) { 358 | *e->os << Value(0).to_string(); 359 | } else { 360 | *e->os << value.to_string(); 361 | } 362 | break; 363 | 364 | case Type::String: 365 | _quote(e, value, _quoteForComment(e, value.get_comment_after())); 366 | break; 367 | 368 | case Type::Vector: 369 | *e->os << "["; 370 | e->indent++; 371 | e->vParent.back().commentAfter = value.get_comment_inside(); 372 | e->vState.back() = EncodeState::VectorElemBegin; 373 | return; 374 | 375 | case Type::Map: 376 | if (!e->opt.omitRootBraces || e->vParent.size() > 1 || value.empty()) { 377 | *e->os << "{"; 378 | e->indent++; 379 | } 380 | e->vParent.back().commentAfter = value.get_comment_inside(); 381 | e->vParent.back().it = value.begin(); 382 | e->vState.back() = EncodeState::MapElemBegin; 383 | return; 384 | 385 | default: 386 | *e->os << value.to_string(); 387 | } 388 | 389 | e->vState.back() = EncodeState::ValueEnd; 390 | } 391 | 392 | 393 | static void _writeValueEnd(Encoder *e) { 394 | e->vState.pop_back(); 395 | e->vParent.pop_back(); 396 | } 397 | 398 | 399 | static void _writeVectorElemBegin(Encoder *e) { 400 | EncodeParent &ep = e->vParent.back(); 401 | const Value &value = *ep.pVal; 402 | 403 | for (; ep.index < value.size(); ep.index++) { 404 | const Value &elem= value[ep.index]; 405 | if (elem.defined()) { 406 | bool shouldIndent = (!e->opt.comments || elem.get_comment_key().empty()); 407 | 408 | if (ep.isEmpty) { 409 | ep.isEmpty = false; 410 | 411 | if (e->opt.comments && !ep.commentAfter.empty()) { 412 | *e->os << ep.commentAfter; 413 | // This is the first element, so commentAfterPrevObj is the inner comment 414 | // of the parent vector. The inner comment probably expects "]" to come 415 | // after it and therefore needs one more level of indentation. 416 | *e->os << e->opt.indentBy; 417 | shouldIndent = false; 418 | } 419 | } else { 420 | if (e->opt.separator) { 421 | *e->os << ","; 422 | } 423 | 424 | if (e->opt.comments) { 425 | *e->os << ep.commentAfter; 426 | } 427 | } 428 | 429 | if (e->opt.comments && !elem.get_comment_before().empty()) { 430 | if (!e->opt.separator && 431 | elem.get_comment_before().find("\n") == std::string::npos) 432 | { 433 | _writeIndent(e, e->indent); 434 | } 435 | *e->os << elem.get_comment_before(); 436 | } else if (shouldIndent) { 437 | _writeIndent(e, e->indent); 438 | } 439 | 440 | ep.commentAfter = elem.get_comment_after(); 441 | ep.index++; 442 | // Invalidates ep 443 | e->vParent.push_back(EncodeParent(&elem)); 444 | e->vState.push_back(EncodeState::ValueBegin); 445 | return; 446 | } 447 | } 448 | if (e->opt.comments && !ep.commentAfter.empty()) { 449 | *e->os << ep.commentAfter; 450 | } 451 | if (!ep.isEmpty && (!e->opt.comments || ep.commentAfter.empty() || 452 | !e->opt.separator && ep.commentAfter.find("\n") == std::string::npos)) 453 | { 454 | _writeIndent(e, e->indent - 1); 455 | } 456 | 457 | *e->os << "]"; 458 | e->indent--; 459 | e->vState.back() = EncodeState::ValueEnd; 460 | } 461 | 462 | 463 | static void _objElem(Encoder *e, const std::string& key, const Value& value, bool *pIsFirst, 464 | const std::string& commentAfterPrevObj) 465 | { 466 | bool hasCommentBefore = (e->opt.comments && !value.get_comment_before().empty()); 467 | 468 | if (*pIsFirst) { 469 | *pIsFirst = false; 470 | bool shouldIndent = ((!e->opt.omitRootBraces || e->vParent.size() > 1) && !hasCommentBefore); 471 | 472 | if (e->opt.comments && !commentAfterPrevObj.empty()) { 473 | *e->os << commentAfterPrevObj; 474 | // This is the first element, so commentAfterPrevObj is the inner comment 475 | // of the parent map. The inner comment probably expects "}" to come 476 | // after it and therefore needs one more level of indentation, unless 477 | // this is the root object without braces. 478 | if (shouldIndent) { 479 | *e->os << e->opt.indentBy; 480 | } 481 | } else if (shouldIndent) { 482 | _writeIndent(e, e->indent); 483 | } 484 | } else { 485 | if (e->opt.separator) { 486 | *e->os << ","; 487 | } 488 | if (e->opt.comments) { 489 | *e->os << commentAfterPrevObj; 490 | } 491 | if (!hasCommentBefore || !e->opt.separator && 492 | value.get_comment_before().find("\n") == std::string::npos) 493 | { 494 | _writeIndent(e, e->indent); 495 | } 496 | } 497 | 498 | if (hasCommentBefore) { 499 | *e->os << value.get_comment_before(); 500 | } 501 | 502 | _quoteName(e, key); 503 | *e->os << ":"; 504 | if ( 505 | !e->opt.bracesSameLine 506 | && value.is_container() 507 | && ( 508 | !value.empty() 509 | || ( 510 | e->opt.comments 511 | && !value.get_comment_inside().empty() 512 | ) 513 | ) 514 | && ( 515 | !e->opt.comments 516 | || value.get_comment_key().empty() 517 | ) 518 | ) 519 | { 520 | _writeIndent(e, e->indent); 521 | } else if (value.type() != Type::String && (!e->opt.comments || value.get_comment_key().empty())) { 522 | *e->os << " "; 523 | } 524 | e->vParent.push_back(EncodeParent(&value)); 525 | e->vState.push_back(EncodeState::ValueBegin); 526 | } 527 | 528 | 529 | static void _writeMapElemBegin(Encoder *e) { 530 | EncodeParent &ep = e->vParent.back(); 531 | const Value &value = *ep.pVal; 532 | 533 | if (e->opt.preserveInsertionOrder) { 534 | for (; ep.index < value.size(); ++ep.index) { 535 | const Value &elem = value[ep.index]; 536 | if (elem.defined()) { 537 | int oldParentIndex = e->vParent.size() - 1; 538 | 539 | // Invalidates ep 540 | _objElem(e, value.key(ep.index), elem, &ep.isEmpty, ep.commentAfter); 541 | 542 | e->vParent[oldParentIndex].commentAfter = elem.get_comment_after(); 543 | ++e->vParent[oldParentIndex].index; 544 | return; 545 | } 546 | } 547 | } else { 548 | for (; ep.it != value.end(); ++ep.it) { 549 | if (ep.it->second.defined()) { 550 | int oldParentIndex = e->vParent.size() - 1; 551 | auto oldIt = ep.it; 552 | 553 | // Invalidates ep 554 | _objElem(e, oldIt->first, oldIt->second, &ep.isEmpty, ep.commentAfter); 555 | 556 | e->vParent[oldParentIndex].commentAfter = oldIt->second.get_comment_after(); 557 | ++e->vParent[oldParentIndex].it; 558 | return; 559 | } 560 | } 561 | } 562 | 563 | if (e->opt.comments && !ep.commentAfter.empty()) { 564 | *e->os << ep.commentAfter; 565 | } 566 | if (!ep.isEmpty && (!e->opt.omitRootBraces || e->vParent.size() > 1) && 567 | (!e->opt.comments || ep.commentAfter.empty() || 568 | !e->opt.separator && ep.commentAfter.find("\n") == std::string::npos)) 569 | { 570 | _writeIndent(e, e->indent - 1); 571 | } 572 | 573 | if (!e->opt.omitRootBraces || e->vParent.size() > 1 || value.empty()) { 574 | e->indent--; 575 | if (e->vParent.size() == 1 && e->opt.comments && !ep.commentAfter.empty() && 576 | _isInComment(ep.commentAfter)) 577 | { 578 | _writeIndent(e, e->indent); 579 | } 580 | *e->os << "}"; 581 | } 582 | 583 | e->vState.back() = EncodeState::ValueEnd; 584 | } 585 | 586 | 587 | static void _marshalLoop(Encoder *e, const Value &v) { 588 | while (!e->vState.empty()) { 589 | switch (e->vState.back()) { 590 | case EncodeState::ValueBegin: 591 | _writeValueBegin(e); 592 | break; 593 | case EncodeState::ValueEnd: 594 | _writeValueEnd(e); 595 | break; 596 | case EncodeState::VectorElemBegin: 597 | _writeVectorElemBegin(e); 598 | break; 599 | case EncodeState::MapElemBegin: 600 | _writeMapElemBegin(e); 601 | break; 602 | } 603 | } 604 | } 605 | 606 | 607 | static void _marshalStream(const Value& v, const EncoderOptions& options, 608 | std::ostream *pStream) 609 | { 610 | Encoder e; 611 | e.os = pStream; 612 | e.opt = options; 613 | e.indent = 0; 614 | 615 | if (e.opt.separator) { 616 | e.opt.quoteAlways = true; 617 | } 618 | 619 | // Regex should not be UTF8 aware, just treat the chars as values. 620 | e.loc = std::locale::classic(); 621 | 622 | std::string commonRange = R"(]|\xc2\xad|\xd8[\x80-\x84]|\xdc\x8f|\xe1\x9e[\xb4\xb5]|\xe2\x80[\x8c\x8f]|\xe2\x80[\xa8-\xaf]|\xe2\x81[\xa0-\xaf]|\xef\xbb\xbf|\xef\xbf[\xb0-\xbf])"; 623 | // needsEscape tests if the string can be written without escapes 624 | e.needsEscape.imbue(e.loc); 625 | e.needsEscape.assign(R"([\\\"\x00-\x1f)" + commonRange); 626 | // needsQuotes tests if the string can be written as a quoteless string (includes needsEscape but without \\ and \") 627 | e.needsQuotes.imbue(e.loc); 628 | e.needsQuotes.assign(R"(^\s|^"|^'|^#|^/\*|^//|^\{|^\}|^\[|^\]|^:|^,|\s$|[\x00-\x1f)" + commonRange); 629 | // needsEscapeML tests if the string can be written as a multiline string (like needsEscape but without \n, \r, \\, \", \t) 630 | e.needsEscapeML.imbue(e.loc); 631 | e.needsEscapeML.assign(R"('''|^[\s]+$|[\x00-\x08\x0b\x0c\x0e-\x1f)" + commonRange); 632 | // starts with a keyword and optionally is followed by a comment 633 | e.startsWithKeyword.imbue(e.loc); 634 | e.startsWithKeyword.assign(R"(^(true|false|null)\s*((,|\]|\}|#|//|/\*).*)?$)"); 635 | e.needsEscapeName.imbue(e.loc); 636 | e.needsEscapeName.assign(R"([,\{\[\}\]\s:#"']|//|/\*)"); 637 | e.lineBreak.assign(R"(\r|\n|\r\n)"); 638 | 639 | e.vParent.push_back(EncodeParent(&v)); 640 | e.vState.push_back(EncodeState::ValueBegin); 641 | if (e.opt.comments) { 642 | *e.os << v.get_comment_before(); 643 | } 644 | _marshalLoop(&e, v); 645 | if (e.opt.comments) { 646 | *e.os << v.get_comment_after(); 647 | } 648 | } 649 | 650 | 651 | // Marshal returns the Hjson encoding of v. 652 | // 653 | // Marshal traverses the value v recursively. 654 | // 655 | // Boolean values encode as JSON booleans. 656 | // 657 | // Floating point, integer, and Number values encode as JSON numbers. 658 | // 659 | // String values encode as Hjson strings (quoteless, multiline or 660 | // JSON). 661 | // 662 | // Array and slice values encode as JSON arrays. 663 | // 664 | // Map values encode as JSON objects. The map's key type must be a 665 | // string. The map keys are used as JSON object keys. 666 | // 667 | // JSON cannot represent cyclic data structures and Marshal does not 668 | // handle them. Passing cyclic structures to Marshal will result in 669 | // an infinite recursion. 670 | // 671 | std::string Marshal(const Value& v, const EncoderOptions& options) { 672 | std::ostringstream oss; 673 | 674 | _marshalStream(v, options, &oss); 675 | 676 | return oss.str(); 677 | } 678 | 679 | 680 | void MarshalToFile(const Value& v, const std::string &path, const EncoderOptions& options) { 681 | std::ofstream outputFile(path, std::ofstream::binary); 682 | if (!outputFile.is_open()) { 683 | throw file_error("Could not open file '" + path + "' for writing"); 684 | } 685 | _marshalStream(v, options, &outputFile); 686 | outputFile << options.eol; 687 | outputFile.close(); 688 | } 689 | 690 | 691 | // MarshalJson returns the Json encoding of v using 692 | // default options + "bracesSameLine", "quoteAlways", "quoteKeys" and 693 | // "separator". 694 | // 695 | // See Marshal. 696 | // 697 | std::string MarshalJson(const Value& v) { 698 | EncoderOptions opt; 699 | 700 | opt.bracesSameLine = true; 701 | opt.quoteAlways = true; 702 | opt.quoteKeys = true; 703 | opt.separator = true; 704 | opt.comments = false; 705 | 706 | return Marshal(v, opt); 707 | } 708 | 709 | 710 | std::ostream &operator <<(std::ostream& out, const Value& v) { 711 | _marshalStream(v, EncoderOptions(), &out); 712 | return out; 713 | } 714 | 715 | 716 | StreamEncoder::StreamEncoder(const Value& _v, const EncoderOptions& _o) 717 | : v(_v), o(_o) 718 | { 719 | } 720 | 721 | 722 | std::ostream &operator <<(std::ostream& out, const StreamEncoder& se) { 723 | _marshalStream(se.v, se.o, &out); 724 | return out; 725 | } 726 | 727 | 728 | } 729 | -------------------------------------------------------------------------------- /src/hjson_parsenumber.cpp: -------------------------------------------------------------------------------- 1 | #include "hjson.h" 2 | #include 3 | #if HJSON_USE_CHARCONV 4 | # include 5 | #elif HJSON_USE_STRTOD 6 | # include 7 | # include 8 | #else 9 | # include 10 | #endif 11 | 12 | 13 | namespace Hjson { 14 | 15 | 16 | struct NumberParser { 17 | const unsigned char *data; 18 | size_t dataSize; 19 | int indexNext; 20 | unsigned char ch; 21 | }; 22 | 23 | 24 | static bool _parseFloat(double *pNumber, const char *pCh, size_t nCh) { 25 | #if HJSON_USE_CHARCONV 26 | auto res = std::from_chars(pCh, pCh + nCh, *pNumber); 27 | 28 | return res.ptr == pCh + nCh && res.ec != std::errc::result_out_of_range && 29 | !std::isinf(*pNumber) && !std::isnan(*pNumber); 30 | #elif HJSON_USE_STRTOD 31 | char *endptr; 32 | errno = 0; 33 | *pNumber = std::strtod(pCh, &endptr); 34 | 35 | return !errno && endptr - pCh == nCh && !std::isinf(*pNumber) && !std::isnan(*pNumber); 36 | #else 37 | std::string str(pCh, nCh); 38 | std::stringstream ss(str); 39 | 40 | // Make sure we expect dot (not comma) as decimal point. 41 | ss.imbue(std::locale::classic()); 42 | 43 | ss >> *pNumber; 44 | 45 | return ss.eof() && !ss.fail() && !std::isinf(*pNumber) && !std::isnan(*pNumber); 46 | #endif 47 | } 48 | 49 | 50 | static bool _parseInt(std::int64_t *pNumber, const char *pCh, size_t nCh) { 51 | #if HJSON_USE_CHARCONV 52 | auto res = std::from_chars(pCh, pCh + nCh, *pNumber); 53 | 54 | return res.ptr == pCh + nCh && res.ec != std::errc::result_out_of_range; 55 | #elif HJSON_USE_STRTOD 56 | char *endptr; 57 | errno = 0; 58 | *pNumber = std::strtoll(pCh, &endptr, 0); 59 | 60 | return !errno && endptr - pCh == nCh; 61 | #else 62 | std::string str(pCh, nCh); 63 | std::stringstream ss(str); 64 | 65 | // Avoid localization surprises. 66 | ss.imbue(std::locale::classic()); 67 | 68 | ss >> *pNumber; 69 | 70 | return ss.eof() && !ss.fail(); 71 | #endif 72 | } 73 | 74 | 75 | static bool _next(NumberParser *p) { 76 | // get the next character. 77 | if (p->indexNext < p->dataSize) { 78 | p->ch = p->data[p->indexNext++]; 79 | return true; 80 | } 81 | 82 | if (p->indexNext == p->dataSize) { 83 | p->indexNext++; 84 | } 85 | 86 | p->ch = 0; 87 | 88 | return false; 89 | } 90 | 91 | 92 | // Parse a number value. The parameter "text" must be zero terminated. 93 | bool tryParseNumber(Value *pValue, const char *text, size_t textSize, bool stopAtNext) { 94 | NumberParser p = { 95 | (const unsigned char*) text, 96 | textSize, 97 | 0, 98 | ' ' 99 | }; 100 | 101 | int leadingZeros = 0; 102 | bool testLeading = true; 103 | 104 | _next(&p); 105 | 106 | if (p.ch == '-') { 107 | _next(&p); 108 | } 109 | 110 | while (p.ch >= '0' && p.ch <= '9') { 111 | if (testLeading) { 112 | if (p.ch == '0') { 113 | leadingZeros++; 114 | } else { 115 | testLeading = false; 116 | } 117 | } 118 | _next(&p); 119 | } 120 | 121 | if (testLeading) { 122 | leadingZeros--; 123 | } // single 0 is allowed 124 | 125 | if (p.ch == '.') { 126 | while (_next(&p) && p.ch >= '0' && p.ch <= '9') { 127 | } 128 | } 129 | if (p.ch == 'e' || p.ch == 'E') { 130 | _next(&p); 131 | if (p.ch == '-' || p.ch == '+') { 132 | _next(&p); 133 | } 134 | while (p.ch >= '0' && p.ch <= '9') { 135 | _next(&p); 136 | } 137 | } 138 | 139 | auto end = p.indexNext; 140 | 141 | // skip white/to (newline) 142 | while (p.ch > 0 && p.ch <= ' ') { 143 | _next(&p); 144 | } 145 | 146 | if (stopAtNext) { 147 | // end scan if we find a punctuator character like ,}] or a comment 148 | if (p.ch == ',' || p.ch == '}' || p.ch == ']' || 149 | p.ch == '#' || (p.indexNext < textSize && p.ch == '/' && 150 | (p.data[p.indexNext] == '/' || p.data[p.indexNext] == '*'))) 151 | { 152 | p.ch = 0; 153 | } 154 | } 155 | 156 | if (p.ch > 0 || leadingZeros != 0) { 157 | // Invalid number. 158 | return false; 159 | } 160 | 161 | std::int64_t i; 162 | if (_parseInt(&i, (char*) p.data, end - 1)) { 163 | *pValue = Value(i); 164 | return true; 165 | } else { 166 | double d; 167 | if (_parseFloat(&d, (char*) p.data, end - 1)) { 168 | *pValue = Value(d); 169 | return true; 170 | } 171 | } 172 | 173 | return false; 174 | } 175 | 176 | 177 | bool startsWithNumber(const char *text, size_t textSize) { 178 | Value number; 179 | return tryParseNumber(&number, text, textSize, true); 180 | } 181 | 182 | 183 | } 184 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(testbin 2 | hjson_test.h 3 | test.cpp 4 | test_marshal.cpp 5 | test_value.cpp 6 | ) 7 | 8 | target_compile_features(testbin PUBLIC cxx_std_11) 9 | 10 | if(${HJSON_NUMBER_PARSER} MATCHES "CharConv") 11 | target_compile_definitions(testbin PRIVATE HJSON_USE_CHARCONV=1) 12 | endif() 13 | 14 | target_link_libraries(testbin hjson) 15 | 16 | add_custom_target(runtest 17 | COMMAND testbin 18 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} 19 | ) 20 | -------------------------------------------------------------------------------- /test/assets/charconv/pass5_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigDouble: 9.223372036854776e+58 3 | bigInt: 9.223372036854776e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/charconv/pass5_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "bigDouble": 9.223372036854776e+58, 3 | "bigInt": 9.223372036854776e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/charset2_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | uescape: "\u0000,\u0001,\uffff" 3 | "um\u000blaut": äöüßÄÖÜ 4 | hex: ģ䕧覫췯ꯍ 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/charset2_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "uescape": "\u0000,\u0001,\uffff", 3 | "um\u000blaut": "äöüßÄÖÜ", 4 | "hex": "ģ䕧覫췯ꯍ" 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/charset2_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | uescape: "\u0000,\u0001,\uffff" 3 | "um\u000blaut": äöüßÄÖÜ 4 | hex: "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A" 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/charset_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 3 | js-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 4 | ml-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/charset_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "ql-ascii": "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 3 | "js-ascii": "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 4 | "ml-ascii": "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/charset_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 3 | js-ascii: "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" 4 | ml-ascii: 5 | ''' 6 | ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 7 | ''' 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/comments/charconv/pass5_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigDouble: 9.223372036854776e+58 3 | bigInt: 9.223372036854776e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/comments/charconv/pass5_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "bigDouble": 9.223372036854776e+58, 3 | "bigInt": 9.223372036854776e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/comments/charset2_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | uescape: "\u0000,\u0001,\uffff" 3 | "um\u000blaut": äöüßÄÖÜ 4 | hex: ģ䕧覫췯ꯍ 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/comments/charset_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 3 | js-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 4 | ml-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/comments/comments2_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ 3 // after1 3 | // after2 4 | -------------------------------------------------------------------------------- /test/assets/comments/comments3_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ a string value // still part of the string 3 | // after2 4 | -------------------------------------------------------------------------------- /test/assets/comments/comments4_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ [ #before1 3 | /*key1keycm*/a string value // still part of the string 4 | /* key2keycm */ "a string value" // not part of the string 5 | // map1before 6 | /* map1key */ 7 | {}//map2after 8 | {} 9 | { 10 | // map3 inner comment 11 | } 12 | [] 13 | // map4before 14 | /*map4key*/{ 15 | /* map4inner */ 16 | } // map4after 17 | //map5before 18 | /*map5key*/ { 19 | //map5ab4 20 | val5a: /* map5akey */ 1 // map5aAfter 21 | val5b: 2 /* map5bb4comma */ #map5bAfter 22 | #map5extra 23 | } /* map5after */ 24 | // vec1bbefore 25 | /* vec1bkey */ 26 | []//vec1bafter 27 | [] 28 | [ 29 | // vec3 inner comment 30 | ] 31 | // vec4before 32 | /*vec4key*/[ 33 | /* vec4inner */ 34 | ] // vec4after 35 | //vec5before 36 | /*vec5key*/ [ 37 | //vec5ab4 38 | 1 // vec5aAfter 39 | 2 /* vec5bb4comma */ #vec5bAfter 40 | #vec5extra 41 | ] /* map5after */ 42 | // before3 43 | 44 | 3 # after3 45 | # before4 46 | /*before4b*/4/*after4*/ 47 | #after4b 48 | ] 49 | // after2 50 | 51 | /* after3 */ 52 | -------------------------------------------------------------------------------- /test/assets/comments/comments5_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ { #before1 3 | key1:/*key1keycm*/a string value // still part of the string 4 | key2: /* key2keycm */ "a string value" // not part of the string 5 | // map1before 6 | map1: /* map1key */ 7 | {}//map2after 8 | map2: {} 9 | map3: 10 | { 11 | // map3 inner comment 12 | } 13 | vec1: [] 14 | // map4before 15 | map4:/*map4key*/{ 16 | /* map4inner */ 17 | } // map4after 18 | //map5before 19 | map5: /*map5key*/ { 20 | //map5ab4 21 | val5a: /* map5akey */ 1 // map5aAfter 22 | val5b: 2 /* map5bb4comma */ #map5bAfter 23 | #map5extra 24 | } /* map5after */ 25 | // vec1bbefore 26 | vec1b: /* vec1bkey */ 27 | []//vec1bafter 28 | vec2: [] 29 | vec3: 30 | [ 31 | // vec3 inner comment 32 | ] 33 | // vec4before 34 | vec4:/*vec4key*/[ 35 | /* vec4inner */ 36 | ] // vec4after 37 | //vec5before 38 | vec5: /*vec5key*/ [ 39 | //vec5ab4 40 | 1 // vec5aAfter 41 | 2 /* vec5bb4comma */ #vec5bAfter 42 | #vec5extra 43 | ] /* map5after */ 44 | // before3 45 | 46 | key3: 3 # after3 47 | # before4 48 | /*before4b*/key4: 4/*after4*/ 49 | #after4b 50 | } 51 | // after2 52 | 53 | /* after3 */ 54 | -------------------------------------------------------------------------------- /test/assets/comments/comments6_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ 3 // after1 3 | // after2 4 | 5 | -------------------------------------------------------------------------------- /test/assets/comments/comments7_result.hjson: -------------------------------------------------------------------------------- 1 | {# comment before 2 | b: /* key comment */ { 3 | sub1: 3 # comment after 4 | sub2: 4 # comment more after 5 | } # cm after obj 6 | // Comment B4 7 | a: 2 8 | /* Last comment */} 9 | -------------------------------------------------------------------------------- /test/assets/comments/comments_result.hjson: -------------------------------------------------------------------------------- 1 | // test 2 | # all 3 | // comment 4 | /* 5 | styles 6 | */ 7 | # with lf 8 | 9 | 10 | 11 | # ! 12 | 13 | { 14 | # hjson style comment 15 | foo1: This is a string value. # part of the string 16 | foo2: "This is a string value." # a comment 17 | 18 | // js style comment 19 | bar1: This is a string value. // part of the string 20 | bar2: "This is a string value." // a comment 21 | 22 | /* js block style comments */foobar1:/* more */This is a string value./* part of the string */ 23 | /* js block style comments */foobar2:/* more */"This is a string value."/* a comment */ 24 | rem1: "# test" 25 | rem2: "// test" 26 | rem3: "/* test */" 27 | num1: 0 # comment 28 | num2: 0.0 // comment 29 | num3: 2 /* comment */ 30 | true1: true # comment 31 | true2: true // comment 32 | true3: true /* comment */ 33 | false1: false # comment 34 | false2: false // comment 35 | false3: false /* comment */ 36 | null1: null # comment 37 | null2: null // comment 38 | null3: null /* comment */ 39 | str1: 00 # part of the string 40 | str2: 00.0 // part of the string 41 | str3: 02 /* part of the string */ 42 | } 43 | -------------------------------------------------------------------------------- /test/assets/comments/empty_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | "": empty 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/comments/int64_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigInt: 144115188075855873 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/comments/kan_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # the comma forces a whitespace check 3 | numbers: 4 | [ 5 | 0 6 | 0 7 | 0 8 | 42 9 | 42.1 10 | -5 11 | -5.1 12 | 1701.0 13 | -1701.0 14 | 12.345 15 | -12.345 16 | ] 17 | native: 18 | [ 19 | true 20 | true 21 | false 22 | false 23 | null 24 | null 25 | ] 26 | strings: 27 | [ 28 | x 0 29 | .0 30 | 00 31 | 01 32 | 0 0 0 33 | 42 x 34 | 42.1 asdf 35 | 1.2.3 36 | -5 0 - 37 | -5.1 -- 38 | 17.01e2 + 39 | -17.01e2 : 40 | 12345e-3 @ 41 | -12345e-3 $ 42 | true true 43 | x true 44 | false false 45 | x false 46 | null null 47 | x null 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /test/assets/comments/keys_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # unquoted keys 3 | unquoted_key: test 4 | _unquoted: test 5 | test-key: test 6 | -test: test 7 | .key: test 8 | # trailing spaces in key names are ignored 9 | trailing: test 10 | trailing2: test 11 | # comment char in key name 12 | "#c1": test 13 | "foo#bar": test 14 | "//bar": test 15 | "foo//bar": test 16 | "/*foo*/": test 17 | "foo/*foo*/bar": test 18 | "/*": test 19 | "foo/*bar": test 20 | # quotes in key name 21 | "\"": test 22 | "foo\"bar": test 23 | "'''": test 24 | "foo'''bar": test 25 | "'": test 26 | "'foo": test 27 | "foo'bar": test 28 | # control char in key name 29 | ":": test 30 | "foo:bar": test 31 | "{": test 32 | "foo{bar": test 33 | "}": test 34 | "foo}bar": test 35 | "[": test 36 | "foo[bar": test 37 | "]": test 38 | "foo]bar": test 39 | # newline 40 | nl1: test 41 | nl2: test 42 | nl3: test 43 | } 44 | -------------------------------------------------------------------------------- /test/assets/comments/mltabs_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | foo: 3 | ''' 4 | bar joe 5 | oki doki 6 | two tabs 7 | ''' 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/comments/oa_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | a 3 | {} 4 | {} 5 | [] 6 | [] 7 | { 8 | b: 1 9 | c: [] 10 | d: {} 11 | } 12 | [] 13 | ] 14 | -------------------------------------------------------------------------------- /test/assets/comments/pass1_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | JSON Test Pattern pass1 3 | { 4 | "object with 1 member": 5 | [ 6 | array with 1 element 7 | ] 8 | } 9 | {} 10 | [] 11 | -42 12 | true 13 | false 14 | null 15 | { 16 | integer: 1234567890 17 | real: -9876.54321 18 | e: 1.23456789e-13 19 | E: 1.23456789e+34 20 | -: 2.3456789012e+76 21 | zero: 0 22 | one: 1 23 | space: " " 24 | quote: '''"''' 25 | backslash: \ 26 | controls: "\b\f\n\r\t" 27 | slash: / & / 28 | alpha: abcdefghijklmnopqrstuvwyz 29 | ALPHA: ABCDEFGHIJKLMNOPQRSTUVWYZ 30 | digit: 0123456789 31 | 0123456789: digit 32 | special: `1~!@#$%^&*()_+-={':[,]}|;.? 33 | hex: ģ䕧覫췯ꯍ 34 | true: true 35 | false: false 36 | null: null 37 | array: [] 38 | object: {} 39 | address: 50 St. James Street 40 | url: http://www.JSON.org/ 41 | comment: "// /* */": " " 43 | " s p a c e d ": 44 | [ 45 | 1 46 | 2 47 | 3 48 | 4 49 | 5 50 | 6 51 | 7 52 | ] 53 | compact: 54 | [ 55 | 1 56 | 2 57 | 3 58 | 4 59 | 5 60 | 6 61 | 7 62 | ] 63 | jsontext: '''{"object with 1 member":["array with 1 element"]}''' 64 | quotes: " " %22 0x22 034 " 65 | "/\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?": A key can be any string 66 | } 67 | 0.5 68 | 98.6 69 | 99.44 70 | 1066 71 | 10.0 72 | 1.0 73 | 0.1 74 | 1.0 75 | 2.0 76 | 2.0 77 | rosebud 78 | ] 79 | -------------------------------------------------------------------------------- /test/assets/comments/pass2_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | [ 4 | [ 5 | [ 6 | [ 7 | [ 8 | [ 9 | [ 10 | [ 11 | [ 12 | [ 13 | [ 14 | [ 15 | [ 16 | [ 17 | [ 18 | [ 19 | [ 20 | Not too deep 21 | ] 22 | ] 23 | ] 24 | ] 25 | ] 26 | ] 27 | ] 28 | ] 29 | ] 30 | ] 31 | ] 32 | ] 33 | ] 34 | ] 35 | ] 36 | ] 37 | ] 38 | ] 39 | ] 40 | -------------------------------------------------------------------------------- /test/assets/comments/pass3_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | "JSON Test Pattern pass3": 3 | { 4 | "The outermost value": must be an object or array. 5 | "In this test": It is an object. 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/assets/comments/pass4_result.hjson: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /test/assets/comments/pass5_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigDouble: 9.22337203685478e+58 3 | bigInt: 9.22337203685478e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/comments/pass6_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | a: 1 3 | b: 2 4 | c: 3 5 | d: /*cm1*/ 4 6 | /*cm2 */ e: /* cm3*/ 5 /* cm 4 */ 7 | f: 6 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/comments/passSingle_result.hjson: -------------------------------------------------------------------------------- 1 | allow quoteless strings 2 | -------------------------------------------------------------------------------- /test/assets/comments/root_result.hjson: -------------------------------------------------------------------------------- 1 | {// a object with the root braces omitted 2 | database: 3 | { 4 | host: 127.0.0.1 5 | port: 555 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/assets/comments/stringify1_result.hjson: -------------------------------------------------------------------------------- 1 | // test if stringify produces correct output 2 | { 3 | quotes: 4 | { 5 | num1: "1,2" 6 | num2: "-1.1 ," 7 | num3: "1e10 ,2" 8 | num4: "-1e-10," 9 | kw1: "true," 10 | kw2: "false ," 11 | kw3: "null,123" 12 | close1: "1}" 13 | close1b: "1 }" 14 | close2: "1]" 15 | close2b: "1 ]" 16 | close3: "1," 17 | close3b: "1 ," 18 | comment1: "1#str" 19 | comment2: "1//str" 20 | comment3: "1/*str*/" 21 | punc1: "{" 22 | punc1b: "{foo" 23 | punc2: "}" 24 | punc2b: "}foo" 25 | punc3: "[" 26 | punc3b: "[foo" 27 | punc4: "]" 28 | punc4b: "]foo" 29 | punc5: "," 30 | punc5b: ",foo" 31 | punc6: ":" 32 | punc6b: ":foo" 33 | } 34 | noquotes: 35 | { 36 | num0: .1,2 37 | num1: 1.1.1,2 38 | num2: -.1, 39 | num3: 1e10e,2 40 | num4: -1e--10, 41 | kw1: true1, 42 | kw2: false0, 43 | kw3: null0, 44 | close1: a} 45 | close2: a] 46 | comment1: a#str 47 | comment2: a//str 48 | comment3: a/*str*/ 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /test/assets/comments/strings2_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # Hjson 3 allows the use of single quotes 3 | 4 | key1: a key in single quotes 5 | "key 2": a key in single quotes 6 | "key \"": a key in single quotes 7 | text: 8 | [ 9 | single quoted string 10 | '''You need quotes for escapes''' 11 | " untrimmed " 12 | "untrimmed " 13 | containing " double quotes 14 | containing " double quotes 15 | containing " double quotes 16 | '''"containing more " double quotes"''' 17 | containing ' single quotes 18 | containing ' single quotes 19 | containing ' single quotes 20 | "'containing more ' single quotes'" 21 | "'containing more ' single quotes'" 22 | "\n" 23 | " \n" 24 | "\n \n \n \n" 25 | "\t\n" 26 | ] 27 | 28 | # escapes/no escape 29 | 30 | foo3a: asdf''' 31 | foo3b: "'''asdf" 32 | foo4a: "asdf'''\nasdf" 33 | foo4b: "asdf\n'''asdf" 34 | } 35 | -------------------------------------------------------------------------------- /test/assets/comments/strings3_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | // Empty string 3 | a: "" 4 | // Unicode code points that require escape inside quotes. 5 | b: "\u00ad\u0600\u0604\u070f\u17b4\u17b5\u200c\u200f\u2028\u202f\u2060\u206f\ufeff\ufff0\uffff" 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/comments/strings4_result.hjson: -------------------------------------------------------------------------------- 1 | "" 2 | -------------------------------------------------------------------------------- /test/assets/comments/strings_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # simple 3 | 4 | text1: This is a valid string value. 5 | text2: a \ is just a \ 6 | text3: '''You need quotes for escapes''' 7 | text4a: " untrimmed " 8 | text4b: " untrimmed" 9 | text4c: "untrimmed " 10 | notml1: "\n" 11 | notml2: " \n" 12 | notml3: "\n \n \n \n" 13 | notml4: "\t\n" 14 | 15 | # multiline string 16 | 17 | multiline1: 18 | ''' 19 | first line 20 | indented line 21 | last line 22 | ''' 23 | multiline2: 24 | ''' 25 | first line 26 | indented line 27 | last line 28 | ''' 29 | multiline3: 30 | ''' 31 | first line 32 | indented line 33 | last line 34 | 35 | ''' # trailing lf 36 | multiline4: ←→±≠Я 37 | 38 | # escapes/no escape 39 | 40 | foo1a: asdf\"'a\s\w 41 | foo1b: asdf\"'a\s\w 42 | foo1c: asdf\"'a\s\w 43 | foo2a: '''"asdf"''' 44 | foo2b: '''"asdf"''' 45 | foo3a: asdf''' 46 | foo3b: "'''asdf" 47 | foo4a: "asdf'''\nasdf" 48 | foo4b: "asdf\n'''asdf" 49 | 50 | # in arrays 51 | arr: 52 | [ 53 | one 54 | two 55 | three 56 | four 57 | ] 58 | 59 | # not strings 60 | not: 61 | { 62 | number: 5 63 | negative: -4.2 64 | yes: true 65 | no: false 66 | null: null 67 | array: 68 | [ 69 | 1 70 | 2 71 | 3 72 | 4 73 | 5 74 | 6 75 | 7 76 | 8 77 | 9 78 | 0 79 | -1 80 | 0.5 81 | ] 82 | } 83 | 84 | # special quoted 85 | special: 86 | { 87 | true: "true" 88 | false: "false" 89 | null: "null" 90 | one: "1" 91 | two: "2" 92 | minus: "-3" 93 | zero: "0" 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /test/assets/comments/trail_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | // the following line contains trailing whitespace: 3 | foo: 0 -- this string starts at 0 and ends at 1, preceding and trailing whitespace is ignored -- 1 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/comments/windowseol_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 3 | js-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 4 | ml-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 5 | newline: 6 | ''' 7 | 1 8 | 2 9 | ''' 10 | } 11 | -------------------------------------------------------------------------------- /test/assets/comments2/charconv/pass5_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigDouble: 9.223372036854776e+58 3 | bigInt: 9.223372036854776e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/comments2/charconv/pass5_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "bigDouble": 9.223372036854776e+58, 3 | "bigInt": 9.223372036854776e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/comments2/charset2_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | uescape: "\u0000,\u0001,\uffff" 3 | "um\u000blaut": äöüßÄÖÜ 4 | hex: ģ䕧覫췯ꯍ 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/comments2/charset_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 3 | js-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 4 | ml-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/comments2/comments2_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ 3 // after1 3 | // after2 4 | -------------------------------------------------------------------------------- /test/assets/comments2/comments3_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ a string value // still part of the string 3 | // after2 4 | -------------------------------------------------------------------------------- /test/assets/comments2/comments4_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ [ #before1 3 | /*key1keycm*/a string value // still part of the string 4 | /* key2keycm */ "a string value" // not part of the string 5 | // map1before 6 | /* map1key */ 7 | {}//map2after 8 | {} 9 | { 10 | // map3 inner comment 11 | } 12 | [] 13 | // map4before 14 | /*map4key*/{ 15 | /* map4inner */ 16 | } // map4after 17 | //map5before 18 | /*map5key*/ { 19 | //map5ab4 20 | val5a: /* map5akey */ 1 // map5aAfter 21 | val5b: 2 /* map5bb4comma */ #map5bAfter 22 | #map5extra 23 | } /* map5after */ 24 | // vec1bbefore 25 | /* vec1bkey */ 26 | []//vec1bafter 27 | [] 28 | [ 29 | // vec3 inner comment 30 | ] 31 | // vec4before 32 | /*vec4key*/[ 33 | /* vec4inner */ 34 | ] // vec4after 35 | //vec5before 36 | /*vec5key*/ [ 37 | //vec5ab4 38 | 1 // vec5aAfter 39 | 2 /* vec5bb4comma */ #vec5bAfter 40 | #vec5extra 41 | ] /* map5after */ 42 | // before3 43 | 44 | 3 # after3 45 | # before4 46 | /*before4b*/4/*after4*/ 47 | #after4b 48 | ] 49 | // after2 50 | 51 | /* after3 */ 52 | -------------------------------------------------------------------------------- /test/assets/comments2/comments5_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ { #before1 3 | key1:/*key1keycm*/a string value // still part of the string 4 | key2: /* key2keycm */ "a string value" // not part of the string 5 | // map1before 6 | map1: /* map1key */ 7 | {}//map2after 8 | map2: {} 9 | map3: { 10 | // map3 inner comment 11 | } 12 | vec1: [] 13 | // map4before 14 | map4:/*map4key*/{ 15 | /* map4inner */ 16 | } // map4after 17 | //map5before 18 | map5: /*map5key*/ { 19 | //map5ab4 20 | val5a: /* map5akey */ 1 // map5aAfter 21 | val5b: 2 /* map5bb4comma */ #map5bAfter 22 | #map5extra 23 | } /* map5after */ 24 | // vec1bbefore 25 | vec1b: /* vec1bkey */ 26 | []//vec1bafter 27 | vec2: [] 28 | vec3: [ 29 | // vec3 inner comment 30 | ] 31 | // vec4before 32 | vec4:/*vec4key*/[ 33 | /* vec4inner */ 34 | ] // vec4after 35 | //vec5before 36 | vec5: /*vec5key*/ [ 37 | //vec5ab4 38 | 1 // vec5aAfter 39 | 2 /* vec5bb4comma */ #vec5bAfter 40 | #vec5extra 41 | ] /* map5after */ 42 | // before3 43 | 44 | key3: 3 # after3 45 | # before4 46 | /*before4b*/key4: 4/*after4*/ 47 | #after4b 48 | } 49 | // after2 50 | 51 | /* after3 */ 52 | -------------------------------------------------------------------------------- /test/assets/comments2/comments6_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ 3 // after1 3 | // after2 4 | 5 | -------------------------------------------------------------------------------- /test/assets/comments2/comments7_result.hjson: -------------------------------------------------------------------------------- 1 | {# comment before 2 | b: /* key comment */ { 3 | sub1: 3 # comment after 4 | sub2: 4 # comment more after 5 | } # cm after obj 6 | // Comment B4 7 | a: 2 8 | /* Last comment */} 9 | -------------------------------------------------------------------------------- /test/assets/comments2/comments_result.hjson: -------------------------------------------------------------------------------- 1 | // test 2 | # all 3 | // comment 4 | /* 5 | styles 6 | */ 7 | # with lf 8 | 9 | 10 | 11 | # ! 12 | 13 | { 14 | # hjson style comment 15 | foo1: This is a string value. # part of the string 16 | foo2: "This is a string value." # a comment 17 | 18 | // js style comment 19 | bar1: This is a string value. // part of the string 20 | bar2: "This is a string value." // a comment 21 | 22 | /* js block style comments */foobar1:/* more */This is a string value./* part of the string */ 23 | /* js block style comments */foobar2:/* more */"This is a string value."/* a comment */ 24 | rem1: "# test" 25 | rem2: "// test" 26 | rem3: "/* test */" 27 | num1: 0 # comment 28 | num2: 0.0 // comment 29 | num3: 2 /* comment */ 30 | true1: true # comment 31 | true2: true // comment 32 | true3: true /* comment */ 33 | false1: false # comment 34 | false2: false // comment 35 | false3: false /* comment */ 36 | null1: null # comment 37 | null2: null // comment 38 | null3: null /* comment */ 39 | str1: 00 # part of the string 40 | str2: 00.0 // part of the string 41 | str3: 02 /* part of the string */ 42 | } 43 | -------------------------------------------------------------------------------- /test/assets/comments2/empty_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | "": empty 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/comments2/int64_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigInt: 144115188075855873 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/comments2/kan_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # the comma forces a whitespace check 3 | numbers: [ 4 | 0 5 | 0 6 | 0 7 | 42 8 | 42.1 9 | -5 10 | -5.1 11 | 1701.0 12 | -1701.0 13 | 12.345 14 | -12.345 15 | ] 16 | native: [ 17 | true 18 | true 19 | false 20 | false 21 | null 22 | null 23 | ] 24 | strings: [ 25 | x 0 26 | .0 27 | 00 28 | 01 29 | 0 0 0 30 | 42 x 31 | 42.1 asdf 32 | 1.2.3 33 | -5 0 - 34 | -5.1 -- 35 | 17.01e2 + 36 | -17.01e2 : 37 | 12345e-3 @ 38 | -12345e-3 $ 39 | true true 40 | x true 41 | false false 42 | x false 43 | null null 44 | x null 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /test/assets/comments2/keys_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # unquoted keys 3 | unquoted_key: test 4 | _unquoted: test 5 | test-key: test 6 | -test: test 7 | .key: test 8 | # trailing spaces in key names are ignored 9 | trailing: test 10 | trailing2: test 11 | # comment char in key name 12 | "#c1": test 13 | "foo#bar": test 14 | "//bar": test 15 | "foo//bar": test 16 | "/*foo*/": test 17 | "foo/*foo*/bar": test 18 | "/*": test 19 | "foo/*bar": test 20 | # quotes in key name 21 | "\"": test 22 | "foo\"bar": test 23 | "'''": test 24 | "foo'''bar": test 25 | "'": test 26 | "'foo": test 27 | "foo'bar": test 28 | # control char in key name 29 | ":": test 30 | "foo:bar": test 31 | "{": test 32 | "foo{bar": test 33 | "}": test 34 | "foo}bar": test 35 | "[": test 36 | "foo[bar": test 37 | "]": test 38 | "foo]bar": test 39 | # newline 40 | nl1: test 41 | nl2: test 42 | nl3: test 43 | } 44 | -------------------------------------------------------------------------------- /test/assets/comments2/mltabs_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | foo: 3 | ''' 4 | bar joe 5 | oki doki 6 | two tabs 7 | ''' 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/comments2/oa_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | a 3 | {} 4 | {} 5 | [] 6 | [] 7 | { 8 | b: 1 9 | c: [] 10 | d: {} 11 | } 12 | [] 13 | ] 14 | -------------------------------------------------------------------------------- /test/assets/comments2/pass1_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | JSON Test Pattern pass1 3 | { 4 | "object with 1 member": [ 5 | array with 1 element 6 | ] 7 | } 8 | {} 9 | [] 10 | -42 11 | true 12 | false 13 | null 14 | { 15 | integer: 1234567890 16 | real: -9876.54321 17 | e: 1.23456789e-13 18 | E: 1.23456789e+34 19 | -: 2.3456789012e+76 20 | zero: 0 21 | one: 1 22 | space: " " 23 | quote: '''"''' 24 | backslash: \ 25 | controls: "\b\f\n\r\t" 26 | slash: / & / 27 | alpha: abcdefghijklmnopqrstuvwyz 28 | ALPHA: ABCDEFGHIJKLMNOPQRSTUVWYZ 29 | digit: 0123456789 30 | 0123456789: digit 31 | special: `1~!@#$%^&*()_+-={':[,]}|;.? 32 | hex: ģ䕧覫췯ꯍ 33 | true: true 34 | false: false 35 | null: null 36 | array: [] 37 | object: {} 38 | address: 50 St. James Street 39 | url: http://www.JSON.org/ 40 | comment: "// /* */": " " 42 | " s p a c e d ": [ 43 | 1 44 | 2 45 | 3 46 | 4 47 | 5 48 | 6 49 | 7 50 | ] 51 | compact: [ 52 | 1 53 | 2 54 | 3 55 | 4 56 | 5 57 | 6 58 | 7 59 | ] 60 | jsontext: '''{"object with 1 member":["array with 1 element"]}''' 61 | quotes: " " %22 0x22 034 " 62 | "/\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?": A key can be any string 63 | } 64 | 0.5 65 | 98.6 66 | 99.44 67 | 1066 68 | 10.0 69 | 1.0 70 | 0.1 71 | 1.0 72 | 2.0 73 | 2.0 74 | rosebud 75 | ] 76 | -------------------------------------------------------------------------------- /test/assets/comments2/pass2_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | [ 4 | [ 5 | [ 6 | [ 7 | [ 8 | [ 9 | [ 10 | [ 11 | [ 12 | [ 13 | [ 14 | [ 15 | [ 16 | [ 17 | [ 18 | [ 19 | [ 20 | Not too deep 21 | ] 22 | ] 23 | ] 24 | ] 25 | ] 26 | ] 27 | ] 28 | ] 29 | ] 30 | ] 31 | ] 32 | ] 33 | ] 34 | ] 35 | ] 36 | ] 37 | ] 38 | ] 39 | ] 40 | -------------------------------------------------------------------------------- /test/assets/comments2/pass3_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | "JSON Test Pattern pass3": { 3 | "The outermost value": must be an object or array. 4 | "In this test": It is an object. 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/comments2/pass4_result.hjson: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /test/assets/comments2/pass5_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigDouble: 9.22337203685478e+58 3 | bigInt: 9.22337203685478e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/comments2/pass6_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | a: 1 3 | b: 2 4 | c: 3 5 | d: /*cm1*/ 4 6 | /*cm2 */ e: /* cm3*/ 5 /* cm 4 */ 7 | f: 6 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/comments2/passSingle_result.hjson: -------------------------------------------------------------------------------- 1 | allow quoteless strings 2 | -------------------------------------------------------------------------------- /test/assets/comments2/root_result.hjson: -------------------------------------------------------------------------------- 1 | {// a object with the root braces omitted 2 | database: { 3 | host: 127.0.0.1 4 | port: 555 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/comments2/stringify1_result.hjson: -------------------------------------------------------------------------------- 1 | // test if stringify produces correct output 2 | { 3 | quotes: { 4 | num1: "1,2" 5 | num2: "-1.1 ," 6 | num3: "1e10 ,2" 7 | num4: "-1e-10," 8 | kw1: "true," 9 | kw2: "false ," 10 | kw3: "null,123" 11 | close1: "1}" 12 | close1b: "1 }" 13 | close2: "1]" 14 | close2b: "1 ]" 15 | close3: "1," 16 | close3b: "1 ," 17 | comment1: "1#str" 18 | comment2: "1//str" 19 | comment3: "1/*str*/" 20 | punc1: "{" 21 | punc1b: "{foo" 22 | punc2: "}" 23 | punc2b: "}foo" 24 | punc3: "[" 25 | punc3b: "[foo" 26 | punc4: "]" 27 | punc4b: "]foo" 28 | punc5: "," 29 | punc5b: ",foo" 30 | punc6: ":" 31 | punc6b: ":foo" 32 | } 33 | noquotes: { 34 | num0: .1,2 35 | num1: 1.1.1,2 36 | num2: -.1, 37 | num3: 1e10e,2 38 | num4: -1e--10, 39 | kw1: true1, 40 | kw2: false0, 41 | kw3: null0, 42 | close1: a} 43 | close2: a] 44 | comment1: a#str 45 | comment2: a//str 46 | comment3: a/*str*/ 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /test/assets/comments2/strings2_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # Hjson 3 allows the use of single quotes 3 | 4 | key1: a key in single quotes 5 | "key 2": a key in single quotes 6 | "key \"": a key in single quotes 7 | text: [ 8 | single quoted string 9 | '''You need quotes for escapes''' 10 | " untrimmed " 11 | "untrimmed " 12 | containing " double quotes 13 | containing " double quotes 14 | containing " double quotes 15 | '''"containing more " double quotes"''' 16 | containing ' single quotes 17 | containing ' single quotes 18 | containing ' single quotes 19 | "'containing more ' single quotes'" 20 | "'containing more ' single quotes'" 21 | "\n" 22 | " \n" 23 | "\n \n \n \n" 24 | "\t\n" 25 | ] 26 | 27 | # escapes/no escape 28 | 29 | foo3a: asdf''' 30 | foo3b: "'''asdf" 31 | foo4a: "asdf'''\nasdf" 32 | foo4b: "asdf\n'''asdf" 33 | } 34 | -------------------------------------------------------------------------------- /test/assets/comments2/strings3_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | // Empty string 3 | a: "" 4 | // Unicode code points that require escape inside quotes. 5 | b: "\u00ad\u0600\u0604\u070f\u17b4\u17b5\u200c\u200f\u2028\u202f\u2060\u206f\ufeff\ufff0\uffff" 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/comments2/strings4_result.hjson: -------------------------------------------------------------------------------- 1 | "" 2 | -------------------------------------------------------------------------------- /test/assets/comments2/strings_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # simple 3 | 4 | text1: This is a valid string value. 5 | text2: a \ is just a \ 6 | text3: '''You need quotes for escapes''' 7 | text4a: " untrimmed " 8 | text4b: " untrimmed" 9 | text4c: "untrimmed " 10 | notml1: "\n" 11 | notml2: " \n" 12 | notml3: "\n \n \n \n" 13 | notml4: "\t\n" 14 | 15 | # multiline string 16 | 17 | multiline1: 18 | ''' 19 | first line 20 | indented line 21 | last line 22 | ''' 23 | multiline2: 24 | ''' 25 | first line 26 | indented line 27 | last line 28 | ''' 29 | multiline3: 30 | ''' 31 | first line 32 | indented line 33 | last line 34 | 35 | ''' # trailing lf 36 | multiline4: ←→±≠Я 37 | 38 | # escapes/no escape 39 | 40 | foo1a: asdf\"'a\s\w 41 | foo1b: asdf\"'a\s\w 42 | foo1c: asdf\"'a\s\w 43 | foo2a: '''"asdf"''' 44 | foo2b: '''"asdf"''' 45 | foo3a: asdf''' 46 | foo3b: "'''asdf" 47 | foo4a: "asdf'''\nasdf" 48 | foo4b: "asdf\n'''asdf" 49 | 50 | # in arrays 51 | arr: [ 52 | one 53 | two 54 | three 55 | four 56 | ] 57 | 58 | # not strings 59 | not: { 60 | number: 5 61 | negative: -4.2 62 | yes: true 63 | no: false 64 | null: null 65 | array: [ 66 | 1 67 | 2 68 | 3 69 | 4 70 | 5 71 | 6 72 | 7 73 | 8 74 | 9 75 | 0 76 | -1 77 | 0.5 78 | ] 79 | } 80 | 81 | # special quoted 82 | special: { 83 | true: "true" 84 | false: "false" 85 | null: "null" 86 | one: "1" 87 | two: "2" 88 | minus: "-3" 89 | zero: "0" 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/assets/comments2/trail_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | // the following line contains trailing whitespace: 3 | foo: 0 -- this string starts at 0 and ends at 1, preceding and trailing whitespace is ignored -- 1 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/comments2/windowseol_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 3 | js-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 4 | ml-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 5 | newline: 6 | ''' 7 | 1 8 | 2 9 | ''' 10 | } 11 | -------------------------------------------------------------------------------- /test/assets/comments2_result.hjson: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /test/assets/comments2_result.json: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /test/assets/comments2_test.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ 3 // after1 3 | // after2 4 | -------------------------------------------------------------------------------- /test/assets/comments3/charconv/pass5_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigDouble: 9.223372036854776e+58 3 | bigInt: 9.223372036854776e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/comments3/charconv/pass5_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "bigDouble": 9.223372036854776e+58, 3 | "bigInt": 9.223372036854776e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/comments3/charset2_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | uescape: "\u0000,\u0001,\uffff" 3 | "um\u000blaut": äöüßÄÖÜ 4 | hex: ģ䕧覫췯ꯍ 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/comments3/charset_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 3 | js-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 4 | ml-ascii: 5 | ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/comments3/comments2_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ 3 // after1 3 | // after2 4 | -------------------------------------------------------------------------------- /test/assets/comments3/comments3_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ a string value // still part of the string 3 | // after2 4 | -------------------------------------------------------------------------------- /test/assets/comments3/comments4_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ [ #before1 3 | /*key1keycm*/a string value // still part of the string 4 | /* key2keycm */ "a string value" // not part of the string 5 | // map1before 6 | /* map1key */ 7 | {}//map2after 8 | {} 9 | { 10 | // map3 inner comment 11 | } 12 | [] 13 | // map4before 14 | /*map4key*/{ 15 | /* map4inner */ 16 | } // map4after 17 | //map5before 18 | /*map5key*/ { 19 | //map5ab4 20 | val5a: /* map5akey */ 1 // map5aAfter 21 | val5b: 2 /* map5bb4comma */ #map5bAfter 22 | #map5extra 23 | } /* map5after */ 24 | // vec1bbefore 25 | /* vec1bkey */ 26 | []//vec1bafter 27 | [] 28 | [ 29 | // vec3 inner comment 30 | ] 31 | // vec4before 32 | /*vec4key*/[ 33 | /* vec4inner */ 34 | ] // vec4after 35 | //vec5before 36 | /*vec5key*/ [ 37 | //vec5ab4 38 | 1 // vec5aAfter 39 | 2 /* vec5bb4comma */ #vec5bAfter 40 | #vec5extra 41 | ] /* map5after */ 42 | // before3 43 | 44 | 3 # after3 45 | # before4 46 | /*before4b*/4/*after4*/ 47 | #after4b 48 | ] 49 | // after2 50 | 51 | /* after3 */ 52 | -------------------------------------------------------------------------------- /test/assets/comments3/comments5_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ { #before1 3 | key1:/*key1keycm*/a string value // still part of the string 4 | key2: /* key2keycm */ "a string value" // not part of the string 5 | // map1before 6 | map1: /* map1key */ 7 | {}//map2after 8 | map2: {} 9 | map3: { 10 | // map3 inner comment 11 | } 12 | vec1: [] 13 | // map4before 14 | map4:/*map4key*/{ 15 | /* map4inner */ 16 | } // map4after 17 | //map5before 18 | map5: /*map5key*/ { 19 | //map5ab4 20 | val5a: /* map5akey */ 1 // map5aAfter 21 | val5b: 2 /* map5bb4comma */ #map5bAfter 22 | #map5extra 23 | } /* map5after */ 24 | // vec1bbefore 25 | vec1b: /* vec1bkey */ 26 | []//vec1bafter 27 | vec2: [] 28 | vec3: [ 29 | // vec3 inner comment 30 | ] 31 | // vec4before 32 | vec4:/*vec4key*/[ 33 | /* vec4inner */ 34 | ] // vec4after 35 | //vec5before 36 | vec5: /*vec5key*/ [ 37 | //vec5ab4 38 | 1 // vec5aAfter 39 | 2 /* vec5bb4comma */ #vec5bAfter 40 | #vec5extra 41 | ] /* map5after */ 42 | // before3 43 | 44 | key3: 3 # after3 45 | # before4 46 | /*before4b*/key4: 4/*after4*/ 47 | #after4b 48 | } 49 | // after2 50 | 51 | /* after3 */ 52 | -------------------------------------------------------------------------------- /test/assets/comments3/comments6_result.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ 3 // after1 3 | // after2 4 | 5 | -------------------------------------------------------------------------------- /test/assets/comments3/comments7_result.hjson: -------------------------------------------------------------------------------- 1 | {# comment before 2 | b: /* key comment */ { 3 | sub1: 3 # comment after 4 | sub2: 4 # comment more after 5 | } # cm after obj 6 | // Comment B4 7 | a: 2 8 | /* Last comment */} 9 | -------------------------------------------------------------------------------- /test/assets/comments3/comments_result.hjson: -------------------------------------------------------------------------------- 1 | // test 2 | # all 3 | // comment 4 | /* 5 | styles 6 | */ 7 | # with lf 8 | 9 | 10 | 11 | # ! 12 | 13 | { 14 | # hjson style comment 15 | foo1: This is a string value. # part of the string 16 | foo2: "This is a string value." # a comment 17 | 18 | // js style comment 19 | bar1: This is a string value. // part of the string 20 | bar2: "This is a string value." // a comment 21 | 22 | /* js block style comments */foobar1:/* more */This is a string value./* part of the string */ 23 | /* js block style comments */foobar2:/* more */"This is a string value."/* a comment */ 24 | 25 | rem1: "# test" 26 | rem2: "// test" 27 | rem3: "/* test */" 28 | 29 | num1: 0 # comment 30 | num2: 0.0 // comment 31 | num3: 2 /* comment */ 32 | 33 | true1: true # comment 34 | true2: true // comment 35 | true3: true /* comment */ 36 | 37 | false1: false # comment 38 | false2: false // comment 39 | false3: false /* comment */ 40 | 41 | null1: null # comment 42 | null2: null // comment 43 | null3: null /* comment */ 44 | 45 | str1: 00 # part of the string 46 | str2: 00.0 // part of the string 47 | str3: 02 /* part of the string */ 48 | } 49 | -------------------------------------------------------------------------------- /test/assets/comments3/empty_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | "": empty 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/comments3/int64_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigInt: 144115188075855873 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/comments3/kan_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # the comma forces a whitespace check 3 | numbers: 4 | [ 5 | 0 6 | 0 7 | 0 8 | 42 9 | 42.1 10 | -5 11 | -5.1 12 | 1701.0 13 | -1701.0 14 | 12.345 15 | -12.345 16 | ] 17 | native: 18 | [ 19 | true 20 | true 21 | false 22 | false 23 | null 24 | null 25 | ] 26 | strings: 27 | [ 28 | x 0 29 | .0 30 | 00 31 | 01 32 | 0 0 0 33 | 42 x 34 | 42.1 asdf 35 | 1.2.3 36 | -5 0 - 37 | -5.1 -- 38 | 17.01e2 + 39 | -17.01e2 : 40 | 12345e-3 @ 41 | -12345e-3 $ 42 | true true 43 | x true 44 | false false 45 | x false 46 | null null 47 | x null 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /test/assets/comments3/keys_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # unquoted keys 3 | unquoted_key: test 4 | _unquoted: test 5 | test-key: test 6 | -test: test 7 | .key: test 8 | # trailing spaces in key names are ignored 9 | trailing: test 10 | trailing2: test 11 | # comment char in key name 12 | "#c1": test 13 | "foo#bar": test 14 | "//bar": test 15 | "foo//bar": test 16 | "/*foo*/": test 17 | "foo/*foo*/bar": test 18 | "/*": test 19 | "foo/*bar": test 20 | # quotes in key name 21 | "\"": test 22 | "foo\"bar": test 23 | "'''": test 24 | "foo'''bar": test 25 | "'": test 26 | "'foo": test 27 | "foo'bar": test 28 | # control char in key name 29 | ":": test 30 | "foo:bar": test 31 | "{": test 32 | "foo{bar": test 33 | "}": test 34 | "foo}bar": test 35 | "[": test 36 | "foo[bar": test 37 | "]": test 38 | "foo]bar": test 39 | # newline 40 | nl1: 41 | test 42 | nl2: 43 | test 44 | 45 | nl3: 46 | 47 | test 48 | } 49 | -------------------------------------------------------------------------------- /test/assets/comments3/mltabs_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | foo: 3 | ''' 4 | bar joe 5 | oki doki 6 | two tabs 7 | ''' 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/comments3/oa_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | a 3 | {} 4 | {} 5 | [] 6 | [] 7 | { 8 | b: 1 9 | c: [] 10 | d: {} 11 | } 12 | [] 13 | ] 14 | -------------------------------------------------------------------------------- /test/assets/comments3/pass1_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | JSON Test Pattern pass1 3 | { 4 | "object with 1 member": [ 5 | array with 1 element 6 | ] 7 | } 8 | {} 9 | [] 10 | -42 11 | true 12 | false 13 | null 14 | { 15 | integer: 1234567890 16 | real: -9876.54321 17 | e: 1.23456789e-13 18 | E: 1.23456789e+34 19 | -: 2.3456789012e+76 20 | zero: 0 21 | one: 1 22 | space: " " 23 | quote: '''"''' 24 | backslash: \ 25 | controls: "\b\f\n\r\t" 26 | slash: / & / 27 | alpha: abcdefghijklmnopqrstuvwyz 28 | ALPHA: ABCDEFGHIJKLMNOPQRSTUVWYZ 29 | digit: 0123456789 30 | 0123456789: digit 31 | special: `1~!@#$%^&*()_+-={':[,]}|;.? 32 | hex: ģ䕧覫췯ꯍ 33 | true: true 34 | false: false 35 | null: null 36 | array: [ ] 37 | object: { } 38 | address: 50 St. James Street 39 | url: http://www.JSON.org/ 40 | comment: "// /* */": " " 42 | " s p a c e d ": [ 43 | 1 44 | 2 45 | 3 46 | 47 | 48 | 49 | 4 50 | 5 51 | 6 52 | 7 53 | ] 54 | compact: [ 55 | 1 56 | 2 57 | 3 58 | 4 59 | 5 60 | 6 61 | 7 62 | ] 63 | jsontext: '''{"object with 1 member":["array with 1 element"]}''' 64 | quotes: " " %22 0x22 034 " 65 | "/\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?": 66 | A key can be any string 67 | } 68 | 0.5 69 | 98.6 70 | 71 | 99.44 72 | 73 | 74 | 1066 75 | 10.0 76 | 1.0 77 | 0.1 78 | 1.0 79 | 2.0 80 | 2.0 81 | rosebud 82 | ] 83 | -------------------------------------------------------------------------------- /test/assets/comments3/pass2_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | [ 4 | [ 5 | [ 6 | [ 7 | [ 8 | [ 9 | [ 10 | [ 11 | [ 12 | [ 13 | [ 14 | [ 15 | [ 16 | [ 17 | [ 18 | [ 19 | [ 20 | Not too deep 21 | ] 22 | ] 23 | ] 24 | ] 25 | ] 26 | ] 27 | ] 28 | ] 29 | ] 30 | ] 31 | ] 32 | ] 33 | ] 34 | ] 35 | ] 36 | ] 37 | ] 38 | ] 39 | ] 40 | -------------------------------------------------------------------------------- /test/assets/comments3/pass3_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | "JSON Test Pattern pass3": { 3 | "The outermost value": must be an object or array. 4 | "In this test": It is an object. 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/comments3/pass4_result.hjson: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /test/assets/comments3/pass5_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigDouble: 9.22337203685478e+58 3 | bigInt: 9.22337203685478e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/comments3/pass6_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | a: 1 3 | b: 2 4 | c: 3 5 | d: /*cm1*/ 4 6 | /*cm2 */ e: /* cm3*/ 5 /* cm 4 */ 7 | f: 6 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/comments3/passSingle_result.hjson: -------------------------------------------------------------------------------- 1 | allow quoteless strings 2 | -------------------------------------------------------------------------------- /test/assets/comments3/root_result.hjson: -------------------------------------------------------------------------------- 1 | {// a object with the root braces omitted 2 | database: 3 | { 4 | host: 127.0.0.1 5 | port: 555 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/assets/comments3/stringify1_result.hjson: -------------------------------------------------------------------------------- 1 | // test if stringify produces correct output 2 | { 3 | quotes: 4 | { 5 | num1: "1,2" 6 | num2: "-1.1 ," 7 | num3: "1e10 ,2" 8 | num4: "-1e-10," 9 | kw1: "true," 10 | kw2: "false ," 11 | kw3: "null,123" 12 | close1: "1}" 13 | close1b: "1 }" 14 | close2: "1]" 15 | close2b: "1 ]" 16 | close3: "1," 17 | close3b: "1 ," 18 | comment1: "1#str" 19 | comment2: "1//str" 20 | comment3: "1/*str*/" 21 | punc1: "{" 22 | punc1b: "{foo" 23 | punc2: "}" 24 | punc2b: "}foo" 25 | punc3: "[" 26 | punc3b: "[foo" 27 | punc4: "]" 28 | punc4b: "]foo" 29 | punc5: "," 30 | punc5b: ",foo" 31 | punc6: ":" 32 | punc6b: ":foo" 33 | } 34 | noquotes: 35 | { 36 | num0: .1,2 37 | num1: 1.1.1,2 38 | num2: -.1, 39 | num3: 1e10e,2 40 | num4: -1e--10, 41 | kw1: true1, 42 | kw2: false0, 43 | kw3: null0, 44 | close1: a} 45 | close2: a] 46 | comment1: a#str 47 | comment2: a//str 48 | comment3: a/*str*/ 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /test/assets/comments3/strings2_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # Hjson 3 allows the use of single quotes 3 | 4 | key1: a key in single quotes 5 | "key 2": a key in single quotes 6 | "key \"": a key in single quotes 7 | 8 | text: [ 9 | single quoted string 10 | '''You need quotes for escapes''' 11 | " untrimmed " 12 | "untrimmed " 13 | containing " double quotes 14 | containing " double quotes 15 | containing " double quotes 16 | '''"containing more " double quotes"''' 17 | containing ' single quotes 18 | containing ' single quotes 19 | containing ' single quotes 20 | "'containing more ' single quotes'" 21 | "'containing more ' single quotes'" 22 | 23 | "\n" 24 | " \n" 25 | "\n \n \n \n" 26 | "\t\n" 27 | ] 28 | 29 | # escapes/no escape 30 | 31 | foo3a: asdf''' 32 | foo3b: "'''asdf" 33 | 34 | foo4a: "asdf'''\nasdf" 35 | foo4b: "asdf\n'''asdf" 36 | } 37 | -------------------------------------------------------------------------------- /test/assets/comments3/strings3_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | // Empty string 3 | a: "" 4 | // Unicode code points that require escape inside quotes. 5 | b: "\u00ad\u0600\u0604\u070f\u17b4\u17b5\u200c\u200f\u2028\u202f\u2060\u206f\ufeff\ufff0\uffff" 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/comments3/strings4_result.hjson: -------------------------------------------------------------------------------- 1 | "" 2 | -------------------------------------------------------------------------------- /test/assets/comments3/strings_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # simple 3 | 4 | text1: This is a valid string value. 5 | text2: a \ is just a \ 6 | 7 | text3: '''You need quotes for escapes''' 8 | 9 | text4a: " untrimmed " 10 | text4b: " untrimmed" 11 | text4c: "untrimmed " 12 | 13 | notml1: "\n" 14 | notml2: " \n" 15 | notml3: "\n \n \n \n" 16 | notml4: "\t\n" 17 | 18 | # multiline string 19 | 20 | multiline1: 21 | 22 | ''' 23 | first line 24 | indented line 25 | last line 26 | ''' 27 | 28 | multiline2: 29 | 30 | ''' 31 | first line 32 | indented line 33 | last line 34 | ''' 35 | 36 | multiline3: 37 | 38 | ''' 39 | first line 40 | indented line 41 | last line 42 | 43 | ''' # trailing lf 44 | 45 | multiline4: 46 | ←→±≠Я 47 | 48 | # escapes/no escape 49 | 50 | foo1a: asdf\"'a\s\w 51 | foo1b: asdf\"'a\s\w 52 | foo1c: asdf\"'a\s\w 53 | 54 | foo2a: '''"asdf"''' 55 | foo2b: '''"asdf"''' 56 | 57 | foo3a: asdf''' 58 | foo3b: "'''asdf" 59 | 60 | foo4a: "asdf'''\nasdf" 61 | foo4b: "asdf\n'''asdf" 62 | 63 | # in arrays 64 | arr: 65 | [ 66 | one 67 | two 68 | three 69 | four 70 | ] 71 | 72 | # not strings 73 | not: 74 | { 75 | number: 5 76 | negative: -4.2 77 | yes: true 78 | no: false 79 | null: null 80 | array: [ 81 | 1 82 | 2 83 | 3 84 | 4 85 | 5 86 | 6 87 | 7 88 | 8 89 | 9 90 | 0 91 | -1 92 | 0.5 93 | ] 94 | } 95 | 96 | # special quoted 97 | special: 98 | { 99 | true: "true" 100 | false: "false" 101 | null: "null" 102 | one: "1" 103 | two: "2" 104 | minus: "-3" 105 | zero: "0" 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /test/assets/comments3/trail_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | // the following line contains trailing whitespace: 3 | foo: 0 -- this string starts at 0 and ends at 1, preceding and trailing whitespace is ignored -- 1 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/comments3/windowseol_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 3 | js-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 4 | ml-ascii: 5 | ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 6 | newline: 7 | 8 | ''' 9 | 1 10 | 2 11 | ''' 12 | } 13 | -------------------------------------------------------------------------------- /test/assets/comments3_result.hjson: -------------------------------------------------------------------------------- 1 | a string value // still part of the string 2 | -------------------------------------------------------------------------------- /test/assets/comments3_result.json: -------------------------------------------------------------------------------- 1 | "a string value // still part of the string" 2 | -------------------------------------------------------------------------------- /test/assets/comments3_test.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ a string value // still part of the string 3 | // after2 4 | -------------------------------------------------------------------------------- /test/assets/comments4_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | a string value // still part of the string 3 | a string value 4 | {} 5 | {} 6 | {} 7 | [] 8 | {} 9 | { 10 | val5a: 1 11 | val5b: 2 12 | } 13 | [] 14 | [] 15 | [] 16 | [] 17 | [ 18 | 1 19 | 2 20 | ] 21 | 3 22 | 4 23 | ] 24 | -------------------------------------------------------------------------------- /test/assets/comments4_result.json: -------------------------------------------------------------------------------- 1 | [ 2 | "a string value // still part of the string", 3 | "a string value", 4 | {}, 5 | {}, 6 | {}, 7 | [], 8 | {}, 9 | { 10 | "val5a": 1, 11 | "val5b": 2 12 | }, 13 | [], 14 | [], 15 | [], 16 | [], 17 | [ 18 | 1, 19 | 2 20 | ], 21 | 3, 22 | 4 23 | ] 24 | -------------------------------------------------------------------------------- /test/assets/comments4_test.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ [ #before1 3 | /*key1keycm*/a string value // still part of the string 4 | /* key2keycm */ "a string value" // not part of the string 5 | // map1before 6 | /* map1key */ 7 | {}//map2after 8 | {} 9 | { 10 | // map3 inner comment 11 | } 12 | [] 13 | // map4before 14 | /*map4key*/{ 15 | /* map4inner */ 16 | } // map4after 17 | //map5before 18 | /*map5key*/ { 19 | //map5ab4 20 | val5a: /* map5akey */ 1, // map5aAfter 21 | val5b: 2 /* map5bb4comma */ , #map5bAfter 22 | #map5extra 23 | } /* map5after */ 24 | // vec1bbefore 25 | /* vec1bkey */ 26 | []//vec1bafter 27 | [] 28 | [ 29 | // vec3 inner comment 30 | ] 31 | // vec4before 32 | /*vec4key*/[ 33 | /* vec4inner */ 34 | ] // vec4after 35 | //vec5before 36 | /*vec5key*/ [ 37 | //vec5ab4 38 | 1, // vec5aAfter 39 | 2 /* vec5bb4comma */ , #vec5bAfter 40 | #vec5extra 41 | ] /* map5after */ 42 | // before3 43 | 44 | 3 # after3 45 | # before4 46 | /*before4b*/4/*after4*/ 47 | #after4b 48 | ] 49 | // after2 50 | 51 | /* after3 */ 52 | -------------------------------------------------------------------------------- /test/assets/comments5_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | key1: a string value // still part of the string 3 | key2: a string value 4 | map1: {} 5 | map2: {} 6 | map3: {} 7 | vec1: [] 8 | map4: {} 9 | map5: 10 | { 11 | val5a: 1 12 | val5b: 2 13 | } 14 | vec1b: [] 15 | vec2: [] 16 | vec3: [] 17 | vec4: [] 18 | vec5: 19 | [ 20 | 1 21 | 2 22 | ] 23 | key3: 3 24 | key4: 4 25 | } 26 | -------------------------------------------------------------------------------- /test/assets/comments5_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "key1": "a string value // still part of the string", 3 | "key2": "a string value", 4 | "map1": {}, 5 | "map2": {}, 6 | "map3": {}, 7 | "vec1": [], 8 | "map4": {}, 9 | "map5": { 10 | "val5a": 1, 11 | "val5b": 2 12 | }, 13 | "vec1b": [], 14 | "vec2": [], 15 | "vec3": [], 16 | "vec4": [], 17 | "vec5": [ 18 | 1, 19 | 2 20 | ], 21 | "key3": 3, 22 | "key4": 4 23 | } 24 | -------------------------------------------------------------------------------- /test/assets/comments5_test.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ { #before1 3 | key1:/*key1keycm*/a string value // still part of the string 4 | key2: /* key2keycm */ "a string value" // not part of the string 5 | // map1before 6 | map1: /* map1key */ 7 | {}//map2after 8 | map2: {} 9 | map3: { 10 | // map3 inner comment 11 | } 12 | vec1: [] 13 | // map4before 14 | map4:/*map4key*/{ 15 | /* map4inner */ 16 | } // map4after 17 | //map5before 18 | map5: /*map5key*/ { 19 | //map5ab4 20 | val5a: /* map5akey */ 1, // map5aAfter 21 | val5b: 2 /* map5bb4comma */ , #map5bAfter 22 | #map5extra 23 | } /* map5after */ 24 | // vec1bbefore 25 | vec1b: /* vec1bkey */ 26 | []//vec1bafter 27 | vec2: [] 28 | vec3: [ 29 | // vec3 inner comment 30 | ] 31 | // vec4before 32 | vec4:/*vec4key*/[ 33 | /* vec4inner */ 34 | ] // vec4after 35 | //vec5before 36 | vec5: /*vec5key*/ [ 37 | //vec5ab4 38 | 1, // vec5aAfter 39 | 2 /* vec5bb4comma */ , #vec5bAfter 40 | #vec5extra 41 | ] /* map5after */ 42 | // before3 43 | 44 | key3 : 3 # after3 45 | # before4 46 | /*before4b*/key4:4/*after4*/ 47 | #after4b 48 | } 49 | // after2 50 | 51 | /* after3 */ 52 | -------------------------------------------------------------------------------- /test/assets/comments6_result.hjson: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /test/assets/comments6_result.json: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /test/assets/comments6_test.hjson: -------------------------------------------------------------------------------- 1 | // before 2 | /* before2 */ 3 // after1 3 | // after2 4 | 5 | -------------------------------------------------------------------------------- /test/assets/comments7_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | b: 3 | { 4 | sub1: 3 5 | sub2: 4 6 | } 7 | a: 2 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/comments7_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "b": { 3 | "sub1": 3, 4 | "sub2": 4 5 | }, 6 | "a": 2 7 | } 8 | -------------------------------------------------------------------------------- /test/assets/comments7_test.hjson: -------------------------------------------------------------------------------- 1 | # comment before 2 | b: /* key comment */ { 3 | sub1: 3 # comment after 4 | sub2: 4 # comment more after 5 | } # cm after obj 6 | // Comment B4 7 | a: 2 8 | /* Last comment */ 9 | -------------------------------------------------------------------------------- /test/assets/comments_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | foo1: This is a string value. # part of the string 3 | foo2: This is a string value. 4 | bar1: This is a string value. // part of the string 5 | bar2: This is a string value. 6 | foobar1: This is a string value./* part of the string */ 7 | foobar2: This is a string value. 8 | rem1: "# test" 9 | rem2: "// test" 10 | rem3: "/* test */" 11 | num1: 0 12 | num2: 0.0 13 | num3: 2 14 | true1: true 15 | true2: true 16 | true3: true 17 | false1: false 18 | false2: false 19 | false3: false 20 | null1: null 21 | null2: null 22 | null3: null 23 | str1: 00 # part of the string 24 | str2: 00.0 // part of the string 25 | str3: 02 /* part of the string */ 26 | } 27 | -------------------------------------------------------------------------------- /test/assets/comments_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo1": "This is a string value. # part of the string", 3 | "foo2": "This is a string value.", 4 | "bar1": "This is a string value. // part of the string", 5 | "bar2": "This is a string value.", 6 | "foobar1": "This is a string value./* part of the string */", 7 | "foobar2": "This is a string value.", 8 | "rem1": "# test", 9 | "rem2": "// test", 10 | "rem3": "/* test */", 11 | "num1": 0, 12 | "num2": 0.0, 13 | "num3": 2, 14 | "true1": true, 15 | "true2": true, 16 | "true3": true, 17 | "false1": false, 18 | "false2": false, 19 | "false3": false, 20 | "null1": null, 21 | "null2": null, 22 | "null3": null, 23 | "str1": "00 # part of the string", 24 | "str2": "00.0 // part of the string", 25 | "str3": "02 /* part of the string */" 26 | } 27 | -------------------------------------------------------------------------------- /test/assets/comments_test.hjson: -------------------------------------------------------------------------------- 1 | // test 2 | # all 3 | // comment 4 | /* 5 | styles 6 | */ 7 | # with lf 8 | 9 | 10 | 11 | # ! 12 | 13 | { 14 | # hjson style comment 15 | foo1: This is a string value. # part of the string 16 | foo2: "This is a string value." # a comment 17 | 18 | // js style comment 19 | bar1: This is a string value. // part of the string 20 | bar2: "This is a string value." // a comment 21 | 22 | /* js block style comments */foobar1:/* more */This is a string value./* part of the string */ 23 | /* js block style comments */foobar2:/* more */"This is a string value."/* a comment */ 24 | 25 | rem1: "# test" 26 | rem2: "// test" 27 | rem3: "/* test */" 28 | 29 | num1: 0 # comment 30 | num2: 0.0 // comment 31 | num3: 2 /* comment */ 32 | 33 | true1: true # comment 34 | true2: true // comment 35 | true3: true /* comment */ 36 | 37 | false1: false # comment 38 | false2: false // comment 39 | false3: false /* comment */ 40 | 41 | null1: null # comment 42 | null2: null // comment 43 | null3: null /* comment */ 44 | 45 | str1: 00 # part of the string 46 | str2: 00.0 // part of the string 47 | str3: 02 /* part of the string */ 48 | } 49 | -------------------------------------------------------------------------------- /test/assets/empty_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | "": empty 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/empty_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "": "empty" 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/empty_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | "": empty 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/failCharset1_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid \u char 3 | char: "\uxxxx" 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failJSON02_test.json: -------------------------------------------------------------------------------- 1 | ["Unclosed array" 2 | -------------------------------------------------------------------------------- /test/assets/failJSON05_test.json: -------------------------------------------------------------------------------- 1 | ["double extra comma",,] 2 | -------------------------------------------------------------------------------- /test/assets/failJSON06_test.json: -------------------------------------------------------------------------------- 1 | [ , "<-- missing value"] 2 | -------------------------------------------------------------------------------- /test/assets/failJSON07_test.json: -------------------------------------------------------------------------------- 1 | ["Comma after the close"], 2 | -------------------------------------------------------------------------------- /test/assets/failJSON08_test.json: -------------------------------------------------------------------------------- 1 | ["Extra close"]] 2 | -------------------------------------------------------------------------------- /test/assets/failJSON10_test.json: -------------------------------------------------------------------------------- 1 | {"Extra value after close": true} "misplaced quoted value" 2 | -------------------------------------------------------------------------------- /test/assets/failJSON11_test.json: -------------------------------------------------------------------------------- 1 | {"Illegal expression": 1 + 2} 2 | -------------------------------------------------------------------------------- /test/assets/failJSON12_test.json: -------------------------------------------------------------------------------- 1 | {"Illegal invocation": alert()} 2 | -------------------------------------------------------------------------------- /test/assets/failJSON13_test.json: -------------------------------------------------------------------------------- 1 | {"Numbers cannot have leading zeroes": 013} 2 | -------------------------------------------------------------------------------- /test/assets/failJSON14_test.json: -------------------------------------------------------------------------------- 1 | {"Numbers cannot be hex": 0x14} 2 | -------------------------------------------------------------------------------- /test/assets/failJSON15_test.json: -------------------------------------------------------------------------------- 1 | ["Illegal backslash escape: \x15"] 2 | -------------------------------------------------------------------------------- /test/assets/failJSON16_test.json: -------------------------------------------------------------------------------- 1 | [\naked] 2 | -------------------------------------------------------------------------------- /test/assets/failJSON17_test.json: -------------------------------------------------------------------------------- 1 | ["Illegal backslash escape: \017"] 2 | -------------------------------------------------------------------------------- /test/assets/failJSON19_test.json: -------------------------------------------------------------------------------- 1 | {"Missing colon" null} 2 | -------------------------------------------------------------------------------- /test/assets/failJSON20_test.json: -------------------------------------------------------------------------------- 1 | {"Double colon":: null} 2 | -------------------------------------------------------------------------------- /test/assets/failJSON21_test.json: -------------------------------------------------------------------------------- 1 | {"Comma instead of colon", null} 2 | -------------------------------------------------------------------------------- /test/assets/failJSON22_test.json: -------------------------------------------------------------------------------- 1 | ["Colon instead of comma": false] 2 | -------------------------------------------------------------------------------- /test/assets/failJSON23_test.json: -------------------------------------------------------------------------------- 1 | ["Bad value", truth] 2 | -------------------------------------------------------------------------------- /test/assets/failJSON26_test.json: -------------------------------------------------------------------------------- 1 | ["tab\ character\ in\ string\ "] 2 | -------------------------------------------------------------------------------- /test/assets/failJSON28_test.json: -------------------------------------------------------------------------------- 1 | ["line\ 2 | break"] 3 | -------------------------------------------------------------------------------- /test/assets/failJSON29_test.json: -------------------------------------------------------------------------------- 1 | [0e] 2 | -------------------------------------------------------------------------------- /test/assets/failJSON30_test.json: -------------------------------------------------------------------------------- 1 | [0e+] 2 | -------------------------------------------------------------------------------- /test/assets/failJSON31_test.json: -------------------------------------------------------------------------------- 1 | [0e+-1] 2 | -------------------------------------------------------------------------------- /test/assets/failJSON32_test.json: -------------------------------------------------------------------------------- 1 | {"Comma instead if closing brace": true, 2 | -------------------------------------------------------------------------------- /test/assets/failJSON33_test.json: -------------------------------------------------------------------------------- 1 | ["mismatch"} 2 | -------------------------------------------------------------------------------- /test/assets/failJSON34_test.json: -------------------------------------------------------------------------------- 1 | A quoteless string is OK, 2 | but two must be contained in an array. 3 | -------------------------------------------------------------------------------- /test/assets/failKey1_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid name 3 | wrong name: 0 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failKey2_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid name 3 | {name: 0 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failKey3_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid name 3 | key,name: 0 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failKey4_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid name 3 | : 0 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failKey5_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid name 3 | '''foo''': 0 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failMLStr1_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid multiline string 3 | ml: ''' 4 | -------------------------------------------------------------------------------- /test/assets/failObj1_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid obj 3 | noDelimiter 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/failObj2_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid obj 3 | noEnd 4 | { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/failObj3_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # missing key 3 | 4 | [ 5 | test 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /test/assets/failObj4_test.hjson: -------------------------------------------------------------------------------- 1 | a: 1 2 | b: 2 3 | # trailing bracket in bracketless root 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr1a_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid quoteless string 3 | ql: ] 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr1b_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid quoteless string 3 | ql: ]x 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr1c_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | foo 3 | # invalid quoteless string 4 | ] 5 | ] 6 | -------------------------------------------------------------------------------- /test/assets/failStr1d_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | foo 3 | # invalid quoteless string 4 | ]x 5 | ] 6 | -------------------------------------------------------------------------------- /test/assets/failStr2a_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid quoteless string 3 | ql: } 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr2b_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid quoteless string 3 | ql: }x 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr2c_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | foo 3 | # invalid quoteless string 4 | } 5 | ] 6 | -------------------------------------------------------------------------------- /test/assets/failStr2d_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | foo 3 | # invalid quoteless string 4 | }x 5 | ] 6 | -------------------------------------------------------------------------------- /test/assets/failStr3a_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid quoteless string 3 | ql: { 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr3b_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid quoteless string 3 | ql: {x 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr3c_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | foo 3 | # invalid quoteless string 4 | { 5 | ] 6 | -------------------------------------------------------------------------------- /test/assets/failStr3d_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | foo 3 | # invalid quoteless string 4 | {x 5 | ] 6 | -------------------------------------------------------------------------------- /test/assets/failStr4a_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid quoteless string 3 | ql: [ 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr4b_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid quoteless string 3 | ql: [x 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr4c_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | foo 3 | # invalid quoteless string 4 | [ 5 | ] 6 | -------------------------------------------------------------------------------- /test/assets/failStr4d_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | foo 3 | # invalid quoteless string 4 | [x 5 | ] 6 | -------------------------------------------------------------------------------- /test/assets/failStr5a_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid quoteless string 3 | ql: : 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr5b_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid quoteless string 3 | ql: :x 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr5c_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | foo 3 | # invalid quoteless string 4 | : 5 | ] 6 | -------------------------------------------------------------------------------- /test/assets/failStr5d_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | foo 3 | # invalid quoteless string 4 | :x 5 | ] 6 | -------------------------------------------------------------------------------- /test/assets/failStr6a_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid quoteless string 3 | ql: , 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr6b_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid quoteless string 3 | ql: ,x 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr6c_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | # invalid quoteless string 3 | # note that if there were a preceding value the comma would 4 | # be allowed/ignored as a separator/trailing comma 5 | , 6 | ] 7 | -------------------------------------------------------------------------------- /test/assets/failStr6d_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | # invalid quoteless string 3 | # note that if there were a preceding value the comma would 4 | # be allowed/ignored as a separator/trailing comma 5 | ,x 6 | ] 7 | -------------------------------------------------------------------------------- /test/assets/failStr7a_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid string containing a newline 3 | foo : " 4 | " 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/failStr8a_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # invalid ml-string 3 | foo : ""'text''' 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/failStr9a_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | = 4 | [['''''' 5 | -------------------------------------------------------------------------------- /test/assets/int64_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigInt: 144115188075855873 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/int64_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "bigInt": 144115188075855873 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/int64_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigInt: 144115188075855873 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/kan_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | numbers: 3 | [ 4 | 0 5 | 0 6 | 0 7 | 42 8 | 42.1 9 | -5 10 | -5.1 11 | 1701.0 12 | -1701.0 13 | 12.345 14 | -12.345 15 | ] 16 | native: 17 | [ 18 | true 19 | true 20 | false 21 | false 22 | null 23 | null 24 | ] 25 | strings: 26 | [ 27 | x 0 28 | .0 29 | 00 30 | 01 31 | 0 0 0 32 | 42 x 33 | 42.1 asdf 34 | 1.2.3 35 | -5 0 - 36 | -5.1 -- 37 | 17.01e2 + 38 | -17.01e2 : 39 | 12345e-3 @ 40 | -12345e-3 $ 41 | true true 42 | x true 43 | false false 44 | x false 45 | null null 46 | x null 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /test/assets/kan_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "numbers": [ 3 | 0, 4 | 0, 5 | 0, 6 | 42, 7 | 42.1, 8 | -5, 9 | -5.1, 10 | 1701.0, 11 | -1701.0, 12 | 12.345, 13 | -12.345 14 | ], 15 | "native": [ 16 | true, 17 | true, 18 | false, 19 | false, 20 | null, 21 | null 22 | ], 23 | "strings": [ 24 | "x 0", 25 | ".0", 26 | "00", 27 | "01", 28 | "0 0 0", 29 | "42 x", 30 | "42.1 asdf", 31 | "1.2.3", 32 | "-5 0 -", 33 | "-5.1 --", 34 | "17.01e2 +", 35 | "-17.01e2 :", 36 | "12345e-3 @", 37 | "-12345e-3 $", 38 | "true true", 39 | "x true", 40 | "false false", 41 | "x false", 42 | "null null", 43 | "x null" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /test/assets/kan_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # the comma forces a whitespace check 3 | numbers: 4 | [ 5 | 0 6 | 0 , 7 | -0 8 | 42 , 9 | 42.1 , 10 | -5 11 | -5.1 12 | 17.01e2 13 | -17.01e2 14 | 12345e-3 , 15 | -12345e-3 , 16 | ] 17 | native: 18 | [ 19 | true , 20 | true 21 | false , 22 | false 23 | null , 24 | null 25 | ] 26 | strings: 27 | [ 28 | x 0 29 | .0 30 | 00 31 | 01 32 | 0 0 0 33 | 42 x 34 | 42.1 asdf 35 | 1.2.3 36 | -5 0 - 37 | -5.1 -- 38 | 17.01e2 + 39 | -17.01e2 : 40 | 12345e-3 @ 41 | -12345e-3 $ 42 | true true 43 | x true 44 | false false 45 | x false 46 | null null 47 | x null 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /test/assets/keys_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | unquoted_key: test 3 | _unquoted: test 4 | test-key: test 5 | -test: test 6 | .key: test 7 | trailing: test 8 | trailing2: test 9 | "#c1": test 10 | "foo#bar": test 11 | "//bar": test 12 | "foo//bar": test 13 | "/*foo*/": test 14 | "foo/*foo*/bar": test 15 | "/*": test 16 | "foo/*bar": test 17 | "\"": test 18 | "foo\"bar": test 19 | "'''": test 20 | "foo'''bar": test 21 | "'": test 22 | "'foo": test 23 | "foo'bar": test 24 | ":": test 25 | "foo:bar": test 26 | "{": test 27 | "foo{bar": test 28 | "}": test 29 | "foo}bar": test 30 | "[": test 31 | "foo[bar": test 32 | "]": test 33 | "foo]bar": test 34 | nl1: test 35 | nl2: test 36 | nl3: test 37 | } 38 | -------------------------------------------------------------------------------- /test/assets/keys_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "unquoted_key": "test", 3 | "_unquoted": "test", 4 | "test-key": "test", 5 | "-test": "test", 6 | ".key": "test", 7 | "trailing": "test", 8 | "trailing2": "test", 9 | "#c1": "test", 10 | "foo#bar": "test", 11 | "//bar": "test", 12 | "foo//bar": "test", 13 | "/*foo*/": "test", 14 | "foo/*foo*/bar": "test", 15 | "/*": "test", 16 | "foo/*bar": "test", 17 | "\"": "test", 18 | "foo\"bar": "test", 19 | "'''": "test", 20 | "foo'''bar": "test", 21 | "'": "test", 22 | "'foo": "test", 23 | "foo'bar": "test", 24 | ":": "test", 25 | "foo:bar": "test", 26 | "{": "test", 27 | "foo{bar": "test", 28 | "}": "test", 29 | "foo}bar": "test", 30 | "[": "test", 31 | "foo[bar": "test", 32 | "]": "test", 33 | "foo]bar": "test", 34 | "nl1": "test", 35 | "nl2": "test", 36 | "nl3": "test" 37 | } 38 | -------------------------------------------------------------------------------- /test/assets/keys_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | # unquoted keys 3 | unquoted_key: test 4 | _unquoted: test 5 | test-key: test 6 | -test: test 7 | .key: test 8 | # trailing spaces in key names are ignored 9 | trailing : test 10 | trailing2 : test 11 | # comment char in key name 12 | "#c1": test 13 | "foo#bar": test 14 | "//bar": test 15 | "foo//bar": test 16 | "/*foo*/": test 17 | "foo/*foo*/bar": test 18 | "/*": test 19 | "foo/*bar": test 20 | # quotes in key name 21 | "\"": test 22 | "foo\"bar": test 23 | "'''": test 24 | "foo'''bar": test 25 | "'": test 26 | "'foo": test 27 | "foo'bar": test 28 | # control char in key name 29 | ":": test 30 | "foo:bar": test 31 | "{": test 32 | "foo{bar": test 33 | "}": test 34 | "foo}bar": test 35 | "[": test 36 | "foo[bar": test 37 | "]": test 38 | "foo]bar": test 39 | # newline 40 | nl1: 41 | test 42 | nl2 43 | : 44 | test 45 | 46 | nl3 47 | 48 | : 49 | 50 | test 51 | } 52 | -------------------------------------------------------------------------------- /test/assets/mltabs_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | foo: 3 | ''' 4 | bar joe 5 | oki doki 6 | two tabs 7 | ''' 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/mltabs_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": "bar\tjoe\noki\tdoki\n\t\ttwo tabs" 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/mltabs_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": "bar\tjoe\noki\tdoki\n\t\ttwo tabs" 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/oa_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | a 3 | {} 4 | {} 5 | [] 6 | [] 7 | { 8 | b: 1 9 | c: [] 10 | d: {} 11 | } 12 | [] 13 | ] 14 | -------------------------------------------------------------------------------- /test/assets/oa_result.json: -------------------------------------------------------------------------------- 1 | [ 2 | "a", 3 | {}, 4 | {}, 5 | [], 6 | [], 7 | { 8 | "b": 1, 9 | "c": [], 10 | "d": {} 11 | }, 12 | [] 13 | ] 14 | -------------------------------------------------------------------------------- /test/assets/oa_test.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | a 3 | {} 4 | {} 5 | [] 6 | [] 7 | { 8 | b: 1 9 | c: [] 10 | d: {} 11 | } 12 | [] 13 | ] 14 | -------------------------------------------------------------------------------- /test/assets/pass1_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | JSON Test Pattern pass1 3 | { 4 | "object with 1 member": 5 | [ 6 | array with 1 element 7 | ] 8 | } 9 | {} 10 | [] 11 | -42 12 | true 13 | false 14 | null 15 | { 16 | integer: 1234567890 17 | real: -9876.54321 18 | e: 1.23456789e-13 19 | E: 1.23456789e+34 20 | -: 2.3456789012e+76 21 | zero: 0 22 | one: 1 23 | space: " " 24 | quote: '''"''' 25 | backslash: \ 26 | controls: "\b\f\n\r\t" 27 | slash: / & / 28 | alpha: abcdefghijklmnopqrstuvwyz 29 | ALPHA: ABCDEFGHIJKLMNOPQRSTUVWYZ 30 | digit: 0123456789 31 | 0123456789: digit 32 | special: `1~!@#$%^&*()_+-={':[,]}|;.? 33 | hex: ģ䕧覫췯ꯍ 34 | true: true 35 | false: false 36 | null: null 37 | array: [] 38 | object: {} 39 | address: 50 St. James Street 40 | url: http://www.JSON.org/ 41 | comment: "// /* */": " " 43 | " s p a c e d ": 44 | [ 45 | 1 46 | 2 47 | 3 48 | 4 49 | 5 50 | 6 51 | 7 52 | ] 53 | compact: 54 | [ 55 | 1 56 | 2 57 | 3 58 | 4 59 | 5 60 | 6 61 | 7 62 | ] 63 | jsontext: '''{"object with 1 member":["array with 1 element"]}''' 64 | quotes: " " %22 0x22 034 " 65 | "/\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?": A key can be any string 66 | } 67 | 0.5 68 | 98.6 69 | 99.44 70 | 1066 71 | 10.0 72 | 1.0 73 | 0.1 74 | 1.0 75 | 2.0 76 | 2.0 77 | rosebud 78 | ] 79 | -------------------------------------------------------------------------------- /test/assets/pass1_result.json: -------------------------------------------------------------------------------- 1 | [ 2 | "JSON Test Pattern pass1", 3 | { 4 | "object with 1 member": [ 5 | "array with 1 element" 6 | ] 7 | }, 8 | {}, 9 | [], 10 | -42, 11 | true, 12 | false, 13 | null, 14 | { 15 | "integer": 1234567890, 16 | "real": -9876.54321, 17 | "e": 1.23456789e-13, 18 | "E": 1.23456789e+34, 19 | "-": 2.3456789012e+76, 20 | "zero": 0, 21 | "one": 1, 22 | "space": " ", 23 | "quote": "\"", 24 | "backslash": "\\", 25 | "controls": "\b\f\n\r\t", 26 | "slash": "/ & /", 27 | "alpha": "abcdefghijklmnopqrstuvwyz", 28 | "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", 29 | "digit": "0123456789", 30 | "0123456789": "digit", 31 | "special": "`1~!@#$%^&*()_+-={':[,]}|;.?", 32 | "hex": "ģ䕧覫췯ꯍ", 33 | "true": true, 34 | "false": false, 35 | "null": null, 36 | "array": [], 37 | "object": {}, 38 | "address": "50 St. James Street", 39 | "url": "http://www.JSON.org/", 40 | "comment": "// /* */": " ", 42 | " s p a c e d ": [ 43 | 1, 44 | 2, 45 | 3, 46 | 4, 47 | 5, 48 | 6, 49 | 7 50 | ], 51 | "compact": [ 52 | 1, 53 | 2, 54 | 3, 55 | 4, 56 | 5, 57 | 6, 58 | 7 59 | ], 60 | "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", 61 | "quotes": "" \" %22 0x22 034 "", 62 | "/\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?": "A key can be any string" 63 | }, 64 | 0.5, 65 | 98.6, 66 | 99.44, 67 | 1066, 68 | 10.0, 69 | 1.0, 70 | 0.1, 71 | 1.0, 72 | 2.0, 73 | 2.0, 74 | "rosebud" 75 | ] 76 | -------------------------------------------------------------------------------- /test/assets/pass1_test.json: -------------------------------------------------------------------------------- 1 | [ 2 | "JSON Test Pattern pass1", 3 | {"object with 1 member":["array with 1 element"]}, 4 | {}, 5 | [], 6 | -42, 7 | true, 8 | false, 9 | null, 10 | { 11 | "integer": 1234567890, 12 | "real": -9876.543210, 13 | "e": 0.123456789e-12, 14 | "E": 1.234567890E+34, 15 | "-": 23456789012E66, 16 | "zero": 0, 17 | "one": 1, 18 | "space": " ", 19 | "quote": "\"", 20 | "backslash": "\\", 21 | "controls": "\b\f\n\r\t", 22 | "slash": "/ & \/", 23 | "alpha": "abcdefghijklmnopqrstuvwyz", 24 | "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", 25 | "digit": "0123456789", 26 | "0123456789": "digit", 27 | "special": "`1~!@#$%^&*()_+-={':[,]}|;.?", 28 | "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", 29 | "true": true, 30 | "false": false, 31 | "null": null, 32 | "array":[ ], 33 | "object":{ }, 34 | "address": "50 St. James Street", 35 | "url": "http://www.JSON.org/", 36 | "comment": "// /* */": " ", 38 | " s p a c e d " :[1,2 , 3 39 | 40 | , 41 | 42 | 4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], 43 | "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", 44 | "quotes": "" \u0022 %22 0x22 034 "", 45 | "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" 46 | : "A key can be any string" 47 | }, 48 | 0.5 ,98.6 49 | , 50 | 99.44 51 | , 52 | 53 | 1066, 54 | 1e1, 55 | 0.1e1, 56 | 1e-1, 57 | 1e00,2e+00,2e-00 58 | ,"rosebud"] 59 | -------------------------------------------------------------------------------- /test/assets/pass2_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | [ 4 | [ 5 | [ 6 | [ 7 | [ 8 | [ 9 | [ 10 | [ 11 | [ 12 | [ 13 | [ 14 | [ 15 | [ 16 | [ 17 | [ 18 | [ 19 | [ 20 | Not too deep 21 | ] 22 | ] 23 | ] 24 | ] 25 | ] 26 | ] 27 | ] 28 | ] 29 | ] 30 | ] 31 | ] 32 | ] 33 | ] 34 | ] 35 | ] 36 | ] 37 | ] 38 | ] 39 | ] 40 | -------------------------------------------------------------------------------- /test/assets/pass2_result.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | [ 4 | [ 5 | [ 6 | [ 7 | [ 8 | [ 9 | [ 10 | [ 11 | [ 12 | [ 13 | [ 14 | [ 15 | [ 16 | [ 17 | [ 18 | [ 19 | [ 20 | "Not too deep" 21 | ] 22 | ] 23 | ] 24 | ] 25 | ] 26 | ] 27 | ] 28 | ] 29 | ] 30 | ] 31 | ] 32 | ] 33 | ] 34 | ] 35 | ] 36 | ] 37 | ] 38 | ] 39 | ] 40 | -------------------------------------------------------------------------------- /test/assets/pass2_test.json: -------------------------------------------------------------------------------- 1 | [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] 2 | -------------------------------------------------------------------------------- /test/assets/pass3_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | "JSON Test Pattern pass3": 3 | { 4 | "The outermost value": must be an object or array. 5 | "In this test": It is an object. 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/assets/pass3_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "JSON Test Pattern pass3": { 3 | "The outermost value": "must be an object or array.", 4 | "In this test": "It is an object." 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/pass3_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "JSON Test Pattern pass3": { 3 | "The outermost value": "must be an object or array.", 4 | "In this test": "It is an object." 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/pass4_result.hjson: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /test/assets/pass4_result.json: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /test/assets/pass4_test.json: -------------------------------------------------------------------------------- 1 | 2 | 10 3 | -------------------------------------------------------------------------------- /test/assets/pass5_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigDouble: 9.22337203685478e+58 3 | bigInt: 9.22337203685478e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/pass5_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "bigDouble": 9.22337203685478e+58, 3 | "bigInt": 9.22337203685478e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/pass5_test.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigDouble: 92233720368547758073829419051489548484843823585675828488686.0 3 | bigInt: 92233720368547758073829419051489548484843823585675828488686 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/pass6_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | a: 1 3 | b: 2 4 | c: 3 5 | d: 4 6 | e: 5 7 | f: 6 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/pass6_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": 1, 3 | "b": 2, 4 | "c": 3, 5 | "d": 4, 6 | "e": 5, 7 | "f": 6 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/pass6_test.hjson: -------------------------------------------------------------------------------- 1 | a: 1, b: 2,c:3,'d' /*cm1*/ : 4, /*cm2 */ e: /* cm3*/ 5 /* cm 4 */ f : 6 2 | -------------------------------------------------------------------------------- /test/assets/passSingle_result.hjson: -------------------------------------------------------------------------------- 1 | allow quoteless strings 2 | -------------------------------------------------------------------------------- /test/assets/passSingle_result.json: -------------------------------------------------------------------------------- 1 | "allow quoteless strings" 2 | -------------------------------------------------------------------------------- /test/assets/passSingle_test.hjson: -------------------------------------------------------------------------------- 1 | allow quoteless strings 2 | -------------------------------------------------------------------------------- /test/assets/root_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | database: 3 | { 4 | host: 127.0.0.1 5 | port: 555 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/assets/root_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "host": "127.0.0.1", 4 | "port": 555 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/root_test.hjson: -------------------------------------------------------------------------------- 1 | // a object with the root braces omitted 2 | database: 3 | { 4 | host: 127.0.0.1 5 | port: 555 6 | } 7 | -------------------------------------------------------------------------------- /test/assets/sorted/charconv/pass5_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigDouble: 9.223372036854776e+58 3 | bigInt: 9.223372036854776e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/sorted/charconv/pass5_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "bigDouble": 9.223372036854776e+58, 3 | "bigInt": 9.223372036854776e+58 4 | } 5 | -------------------------------------------------------------------------------- /test/assets/sorted/charset2_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | hex: ģ䕧覫췯ꯍ 3 | uescape: "\u0000,\u0001,\uffff" 4 | "um\u000blaut": äöüßÄÖÜ 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/sorted/charset2_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "hex": "ģ䕧覫췯ꯍ", 3 | "uescape": "\u0000,\u0001,\uffff", 4 | "um\u000blaut": "äöüßÄÖÜ" 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/sorted/charset_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | js-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 3 | ml-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 4 | ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/sorted/charset_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "js-ascii": "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 3 | "ml-ascii": "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 4 | "ql-ascii": "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" 5 | } 6 | -------------------------------------------------------------------------------- /test/assets/sorted/comments2_result.hjson: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /test/assets/sorted/comments2_result.json: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /test/assets/sorted/comments3_result.hjson: -------------------------------------------------------------------------------- 1 | a string value // still part of the string 2 | -------------------------------------------------------------------------------- /test/assets/sorted/comments3_result.json: -------------------------------------------------------------------------------- 1 | "a string value // still part of the string" 2 | -------------------------------------------------------------------------------- /test/assets/sorted/comments4_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | a string value // still part of the string 3 | a string value 4 | {} 5 | {} 6 | {} 7 | [] 8 | {} 9 | { 10 | val5a: 1 11 | val5b: 2 12 | } 13 | [] 14 | [] 15 | [] 16 | [] 17 | [ 18 | 1 19 | 2 20 | ] 21 | 3 22 | 4 23 | ] 24 | -------------------------------------------------------------------------------- /test/assets/sorted/comments4_result.json: -------------------------------------------------------------------------------- 1 | [ 2 | "a string value // still part of the string", 3 | "a string value", 4 | {}, 5 | {}, 6 | {}, 7 | [], 8 | {}, 9 | { 10 | "val5a": 1, 11 | "val5b": 2 12 | }, 13 | [], 14 | [], 15 | [], 16 | [], 17 | [ 18 | 1, 19 | 2 20 | ], 21 | 3, 22 | 4 23 | ] 24 | -------------------------------------------------------------------------------- /test/assets/sorted/comments5_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | key1: a string value // still part of the string 3 | key2: a string value 4 | key3: 3 5 | key4: 4 6 | map1: {} 7 | map2: {} 8 | map3: {} 9 | map4: {} 10 | map5: 11 | { 12 | val5a: 1 13 | val5b: 2 14 | } 15 | vec1: [] 16 | vec1b: [] 17 | vec2: [] 18 | vec3: [] 19 | vec4: [] 20 | vec5: 21 | [ 22 | 1 23 | 2 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /test/assets/sorted/comments5_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "key1": "a string value // still part of the string", 3 | "key2": "a string value", 4 | "key3": 3, 5 | "key4": 4, 6 | "map1": {}, 7 | "map2": {}, 8 | "map3": {}, 9 | "map4": {}, 10 | "map5": { 11 | "val5a": 1, 12 | "val5b": 2 13 | }, 14 | "vec1": [], 15 | "vec1b": [], 16 | "vec2": [], 17 | "vec3": [], 18 | "vec4": [], 19 | "vec5": [ 20 | 1, 21 | 2 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /test/assets/sorted/comments6_result.hjson: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /test/assets/sorted/comments6_result.json: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /test/assets/sorted/comments7_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | a: 2 3 | b: 4 | { 5 | sub1: 3 6 | sub2: 4 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/sorted/comments7_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": 2, 3 | "b": { 4 | "sub1": 3, 5 | "sub2": 4 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/assets/sorted/comments_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bar1: This is a string value. // part of the string 3 | bar2: This is a string value. 4 | false1: false 5 | false2: false 6 | false3: false 7 | foo1: This is a string value. # part of the string 8 | foo2: This is a string value. 9 | foobar1: This is a string value./* part of the string */ 10 | foobar2: This is a string value. 11 | null1: null 12 | null2: null 13 | null3: null 14 | num1: 0 15 | num2: 0.0 16 | num3: 2 17 | rem1: "# test" 18 | rem2: "// test" 19 | rem3: "/* test */" 20 | str1: 00 # part of the string 21 | str2: 00.0 // part of the string 22 | str3: 02 /* part of the string */ 23 | true1: true 24 | true2: true 25 | true3: true 26 | } 27 | -------------------------------------------------------------------------------- /test/assets/sorted/comments_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "bar1": "This is a string value. // part of the string", 3 | "bar2": "This is a string value.", 4 | "false1": false, 5 | "false2": false, 6 | "false3": false, 7 | "foo1": "This is a string value. # part of the string", 8 | "foo2": "This is a string value.", 9 | "foobar1": "This is a string value./* part of the string */", 10 | "foobar2": "This is a string value.", 11 | "null1": null, 12 | "null2": null, 13 | "null3": null, 14 | "num1": 0, 15 | "num2": 0.0, 16 | "num3": 2, 17 | "rem1": "# test", 18 | "rem2": "// test", 19 | "rem3": "/* test */", 20 | "str1": "00 # part of the string", 21 | "str2": "00.0 // part of the string", 22 | "str3": "02 /* part of the string */", 23 | "true1": true, 24 | "true2": true, 25 | "true3": true 26 | } 27 | -------------------------------------------------------------------------------- /test/assets/sorted/empty_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | "": empty 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/sorted/empty_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "": "empty" 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/sorted/int64_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | bigInt: 144115188075855873 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/sorted/int64_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "bigInt": 144115188075855873 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/sorted/kan_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | native: 3 | [ 4 | true 5 | true 6 | false 7 | false 8 | null 9 | null 10 | ] 11 | numbers: 12 | [ 13 | 0 14 | 0 15 | 0 16 | 42 17 | 42.1 18 | -5 19 | -5.1 20 | 1701.0 21 | -1701.0 22 | 12.345 23 | -12.345 24 | ] 25 | strings: 26 | [ 27 | x 0 28 | .0 29 | 00 30 | 01 31 | 0 0 0 32 | 42 x 33 | 42.1 asdf 34 | 1.2.3 35 | -5 0 - 36 | -5.1 -- 37 | 17.01e2 + 38 | -17.01e2 : 39 | 12345e-3 @ 40 | -12345e-3 $ 41 | true true 42 | x true 43 | false false 44 | x false 45 | null null 46 | x null 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /test/assets/sorted/kan_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "native": [ 3 | true, 4 | true, 5 | false, 6 | false, 7 | null, 8 | null 9 | ], 10 | "numbers": [ 11 | 0, 12 | 0, 13 | 0, 14 | 42, 15 | 42.1, 16 | -5, 17 | -5.1, 18 | 1701.0, 19 | -1701.0, 20 | 12.345, 21 | -12.345 22 | ], 23 | "strings": [ 24 | "x 0", 25 | ".0", 26 | "00", 27 | "01", 28 | "0 0 0", 29 | "42 x", 30 | "42.1 asdf", 31 | "1.2.3", 32 | "-5 0 -", 33 | "-5.1 --", 34 | "17.01e2 +", 35 | "-17.01e2 :", 36 | "12345e-3 @", 37 | "-12345e-3 $", 38 | "true true", 39 | "x true", 40 | "false false", 41 | "x false", 42 | "null null", 43 | "x null" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /test/assets/sorted/keys_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | "\"": test 3 | "#c1": test 4 | "'": test 5 | "'''": test 6 | "'foo": test 7 | -test: test 8 | .key: test 9 | "/*": test 10 | "/*foo*/": test 11 | "//bar": test 12 | ":": test 13 | "[": test 14 | "]": test 15 | _unquoted: test 16 | "foo\"bar": test 17 | "foo#bar": test 18 | "foo'''bar": test 19 | "foo'bar": test 20 | "foo/*bar": test 21 | "foo/*foo*/bar": test 22 | "foo//bar": test 23 | "foo:bar": test 24 | "foo[bar": test 25 | "foo]bar": test 26 | "foo{bar": test 27 | "foo}bar": test 28 | nl1: test 29 | nl2: test 30 | nl3: test 31 | test-key: test 32 | trailing: test 33 | trailing2: test 34 | unquoted_key: test 35 | "{": test 36 | "}": test 37 | } 38 | -------------------------------------------------------------------------------- /test/assets/sorted/keys_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "\"": "test", 3 | "#c1": "test", 4 | "'": "test", 5 | "'''": "test", 6 | "'foo": "test", 7 | "-test": "test", 8 | ".key": "test", 9 | "/*": "test", 10 | "/*foo*/": "test", 11 | "//bar": "test", 12 | ":": "test", 13 | "[": "test", 14 | "]": "test", 15 | "_unquoted": "test", 16 | "foo\"bar": "test", 17 | "foo#bar": "test", 18 | "foo'''bar": "test", 19 | "foo'bar": "test", 20 | "foo/*bar": "test", 21 | "foo/*foo*/bar": "test", 22 | "foo//bar": "test", 23 | "foo:bar": "test", 24 | "foo[bar": "test", 25 | "foo]bar": "test", 26 | "foo{bar": "test", 27 | "foo}bar": "test", 28 | "nl1": "test", 29 | "nl2": "test", 30 | "nl3": "test", 31 | "test-key": "test", 32 | "trailing": "test", 33 | "trailing2": "test", 34 | "unquoted_key": "test", 35 | "{": "test", 36 | "}": "test" 37 | } 38 | -------------------------------------------------------------------------------- /test/assets/sorted/mltabs_result.hjson: -------------------------------------------------------------------------------- 1 | { 2 | foo: 3 | ''' 4 | bar joe 5 | oki doki 6 | two tabs 7 | ''' 8 | } 9 | -------------------------------------------------------------------------------- /test/assets/sorted/mltabs_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": "bar\tjoe\noki\tdoki\n\t\ttwo tabs" 3 | } 4 | -------------------------------------------------------------------------------- /test/assets/sorted/oa_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | a 3 | {} 4 | {} 5 | [] 6 | [] 7 | { 8 | b: 1 9 | c: [] 10 | d: {} 11 | } 12 | [] 13 | ] 14 | -------------------------------------------------------------------------------- /test/assets/sorted/oa_result.json: -------------------------------------------------------------------------------- 1 | [ 2 | "a", 3 | {}, 4 | {}, 5 | [], 6 | [], 7 | { 8 | "b": 1, 9 | "c": [], 10 | "d": {} 11 | }, 12 | [] 13 | ] 14 | -------------------------------------------------------------------------------- /test/assets/sorted/pass1_result.hjson: -------------------------------------------------------------------------------- 1 | [ 2 | JSON Test Pattern pass1 3 | { 4 | "object with 1 member": 5 | [ 6 | array with 1 element 7 | ] 8 | } 9 | {} 10 | [] 11 | -42 12 | true 13 | false 14 | null 15 | { 16 | " s p a c e d ": 17 | [ 18 | 1 19 | 2 20 | 3 21 | 4 22 | 5 23 | 6 24 | 7 25 | ] 26 | "# -- --> */": " " 27 | -: 2.3456789012e+76 28 | "/\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?": A key can be any string 29 | 0123456789: digit 30 | ALPHA: ABCDEFGHIJKLMNOPQRSTUVWYZ 31 | E: 1.23456789e+34 32 | address: 50 St. James Street 33 | alpha: abcdefghijklmnopqrstuvwyz 34 | array: [] 35 | backslash: \ 36 | comment: "// /* */": " ", 25 | "-": 2.3456789012e+76, 26 | "/\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?": "A key can be any string", 27 | "0123456789": "digit", 28 | "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", 29 | "E": 1.23456789e+34, 30 | "address": "50 St. James Street", 31 | "alpha": "abcdefghijklmnopqrstuvwyz", 32 | "array": [], 33 | "backslash": "\\", 34 | "comment": "// /*