You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by cm...@apache.org on 2026/06/09 18:41:11 UTC
(trafficserver) branch 10.1.x updated (85d19f484a -> e84ab1a968)
This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a change to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
from 85d19f484a Allow DNS search_default_domains mode 2 (#13178)
new a50f7e3c06 slice: Fix a crash caused by use-after-free (#13113)
new b43ff3e1a4 Correct records.yaml record drift (#13177)
new ed29950131 yaml-cpp-0.9.0 (#13192)
new 3da3a0faf2 GCC 16: Regex header integer includes (#13193)
new 89e24aa431 Fix autest compatibility with Fedora 43 / Python 3.14 (#12857)
new b99e662cc9 Check Curl support for TLS 1.0 and 1.1 (#12887)
new b9b38b4f7d Fedora 44 test fixes (#13198)
new 8202d03d32 Single source of truth for Proxy Verifier metadata (#13200)
new e84ab1a968 Proxy Verifier v3.1.3 (#13217)
The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
CMakeLists.txt | 7 +-
doc/admin-guide/files/records.yaml.en.rst | 47 +-
include/tsutil/Regex.h | 3 +-
lib/yamlcpp/.bazelignore | 1 +
lib/yamlcpp/.codedocs | 2 +-
lib/yamlcpp/.github/dependabot.yml | 11 +
lib/yamlcpp/.github/workflows/build.yml | 141 +
lib/yamlcpp/.github/workflows/bzlmod-archive.yml | 19 +
lib/yamlcpp/.travis.yml | 37 -
lib/yamlcpp/BUILD.bazel | 2 +
lib/yamlcpp/CMakeLists.txt | 41 +-
lib/yamlcpp/CONTRIBUTING.md | 4 +-
lib/yamlcpp/MODULE.bazel | 14 +
lib/yamlcpp/MODULE.bazel.lock | 282 +
lib/yamlcpp/README.md | 32 +-
lib/yamlcpp/WORKSPACE | 10 -
lib/yamlcpp/include/yaml-cpp/dll.h | 2 -
lib/yamlcpp/include/yaml-cpp/emitfromevents.h | 1 +
lib/yamlcpp/include/yaml-cpp/emitter.h | 20 +-
lib/yamlcpp/include/yaml-cpp/emitterstyle.h | 7 +-
lib/yamlcpp/include/yaml-cpp/exceptions.h | 2 +
lib/yamlcpp/include/yaml-cpp/fptostring.h | 15 +
lib/yamlcpp/include/yaml-cpp/node/convert.h | 9 +-
.../include/yaml-cpp/node/detail/iterator.h | 2 +-
lib/yamlcpp/include/yaml-cpp/node/detail/memory.h | 1 +
.../include/yaml-cpp/node/detail/node_iterator.h | 2 +-
lib/yamlcpp/include/yaml-cpp/node/impl.h | 8 +-
lib/yamlcpp/include/yaml-cpp/node/type.h | 7 +-
lib/yamlcpp/include/yaml-cpp/null.h | 4 +-
lib/yamlcpp/include/yaml-cpp/traits.h | 1 +
lib/yamlcpp/include/yaml-cpp/yaml.h | 4 +
lib/yamlcpp/src/contrib/dragonbox.h | 4196 +++++++++++
lib/yamlcpp/src/emitfromevents.cpp | 9 +-
lib/yamlcpp/src/emitter.cpp | 27 +-
lib/yamlcpp/src/emitterutils.cpp | 76 +-
lib/yamlcpp/src/emitterutils.h | 14 +-
lib/yamlcpp/src/fptostring.cpp | 255 +
lib/yamlcpp/src/indentation.h | 1 -
lib/yamlcpp/src/memory.cpp | 8 +
lib/yamlcpp/src/node_data.cpp | 1 +
lib/yamlcpp/src/null.cpp | 13 +-
lib/yamlcpp/src/ostream_wrapper.cpp | 2 +-
lib/yamlcpp/src/parse.cpp | 2 +-
lib/yamlcpp/src/parser.cpp | 1 +
lib/yamlcpp/src/regeximpl.h | 4 +
lib/yamlcpp/src/scanner.cpp | 24 +
lib/yamlcpp/src/scanner.h | 1 +
lib/yamlcpp/src/scantoken.cpp | 7 +
lib/yamlcpp/src/singledocparser.cpp | 7 +-
lib/yamlcpp/src/stream.cpp | 21 +-
lib/yamlcpp/src/stream.h | 3 +-
lib/yamlcpp/src/token.h | 7 +-
lib/yamlcpp/test/BUILD.bazel | 22 +-
lib/yamlcpp/test/CMakeLists.txt | 23 +-
lib/yamlcpp/test/cmake/CMakeLists.txt | 21 +
lib/yamlcpp/test/cmake/main.cpp | 3 +
lib/yamlcpp/test/fptostring_test.cpp | 249 +
lib/yamlcpp/test/googletest-1.13.0/.clang-format | 4 +
.../.github/ISSUE_TEMPLATE/00-bug_report.yml | 53 +
.../.github/ISSUE_TEMPLATE/10-feature_request.yml | 33 +
.../.github/ISSUE_TEMPLATE/config.yml | 5 +
.../.github/workflows/gtest-ci.yml | 43 +
lib/yamlcpp/test/googletest-1.13.0/.gitignore | 84 +
lib/yamlcpp/test/googletest-1.13.0/BUILD.bazel | 218 +
lib/yamlcpp/test/googletest-1.13.0/CMakeLists.txt | 39 +
lib/yamlcpp/test/googletest-1.13.0/CONTRIBUTING.md | 131 +
lib/yamlcpp/test/googletest-1.13.0/CONTRIBUTORS | 65 +
lib/yamlcpp/test/googletest-1.13.0/LICENSE | 28 +
lib/yamlcpp/test/googletest-1.13.0/README.md | 117 +
lib/yamlcpp/test/googletest-1.13.0/WORKSPACE | 40 +
.../test/googletest-1.13.0/ci/linux-presubmit.sh | 134 +
.../test/googletest-1.13.0/ci/macos-presubmit.sh | 75 +
.../googletest-1.13.0/ci/windows-presubmit.bat | 56 +
.../test/googletest-1.13.0/docs/_config.yml | 1 +
.../googletest-1.13.0/docs/_data/navigation.yml | 43 +
.../googletest-1.13.0/docs/_layouts/default.html | 58 +
.../test/googletest-1.13.0/docs/_sass/main.scss | 200 +
.../test/googletest-1.13.0/docs/advanced.md | 2407 ++++++
.../googletest-1.13.0/docs/assets/css/style.scss | 5 +
.../docs/community_created_documentation.md | 7 +
lib/yamlcpp/test/googletest-1.13.0/docs/faq.md | 692 ++
.../googletest-1.13.0/docs/gmock_cheat_sheet.md | 241 +
.../test/googletest-1.13.0/docs/gmock_cook_book.md | 4343 +++++++++++
.../test/googletest-1.13.0/docs/gmock_faq.md | 390 +
.../googletest-1.13.0/docs/gmock_for_dummies.md | 700 ++
lib/yamlcpp/test/googletest-1.13.0/docs/index.md | 22 +
.../test/googletest-1.13.0/docs/pkgconfig.md | 148 +
.../test/googletest-1.13.0/docs/platforms.md | 35 +
lib/yamlcpp/test/googletest-1.13.0/docs/primer.md | 483 ++
.../googletest-1.13.0/docs/quickstart-bazel.md | 146 +
.../googletest-1.13.0/docs/quickstart-cmake.md | 156 +
.../googletest-1.13.0/docs/reference/actions.md | 115 +
.../googletest-1.13.0/docs/reference/assertions.md | 633 ++
.../googletest-1.13.0/docs/reference/matchers.md | 290 +
.../googletest-1.13.0/docs/reference/mocking.md | 589 ++
.../googletest-1.13.0/docs/reference/testing.md | 1431 ++++
lib/yamlcpp/test/googletest-1.13.0/docs/samples.md | 22 +
.../googletest-1.13.0/googlemock/CMakeLists.txt | 218 +
.../test/googletest-1.13.0/googlemock/README.md | 40 +
.../googletest-1.13.0/googlemock/cmake/gmock.pc.in | 10 +
.../googlemock/cmake/gmock_main.pc.in | 10 +
.../googletest-1.13.0/googlemock/docs/README.md | 4 +
.../googlemock/include/gmock/gmock-actions.h | 2302 ++++++
.../googlemock/include/gmock/gmock-cardinalities.h | 159 +
.../include/gmock/gmock-function-mocker.h | 517 ++
.../googlemock/include/gmock/gmock-matchers.h | 5620 ++++++++++++++
.../googlemock/include/gmock/gmock-more-actions.h | 662 ++
.../googlemock/include/gmock/gmock-more-matchers.h | 122 +
.../googlemock/include/gmock/gmock-nice-strict.h | 277 +
.../googlemock/include/gmock/gmock-spec-builders.h | 2111 ++++++
.../googlemock/include/gmock/gmock.h | 96 +
.../include/gmock/internal/custom/README.md | 18 +
.../internal/custom/gmock-generated-actions.h | 7 +
.../include/gmock/internal/custom/gmock-matchers.h | 37 +
.../include/gmock/internal/custom/gmock-port.h | 40 +
.../include/gmock/internal/gmock-internal-utils.h | 490 ++
.../googlemock/include/gmock/internal/gmock-port.h | 139 +
.../googlemock/include/gmock/internal/gmock-pp.h | 279 +
.../googletest-1.13.0/googlemock/src/gmock-all.cc | 46 +
.../googlemock/src/gmock-cardinalities.cc | 155 +
.../googlemock/src/gmock-internal-utils.cc | 251 +
.../googlemock/src/gmock-matchers.cc | 479 ++
.../googlemock/src/gmock-spec-builders.cc | 795 ++
.../test/googletest-1.13.0/googlemock/src/gmock.cc | 223 +
.../googletest-1.13.0/googlemock/src/gmock_main.cc | 72 +
.../googletest-1.13.0/googlemock/test/BUILD.bazel | 119 +
.../googlemock/test/gmock-actions_test.cc | 2167 ++++++
.../googlemock/test/gmock-cardinalities_test.cc | 422 ++
.../googlemock/test/gmock-function-mocker_test.cc | 1004 +++
.../googlemock/test/gmock-internal-utils_test.cc | 765 ++
.../test/gmock-matchers-arithmetic_test.cc | 1517 ++++
.../test/gmock-matchers-comparisons_test.cc | 2359 ++++++
.../test/gmock-matchers-containers_test.cc | 3129 ++++++++
.../googlemock/test/gmock-matchers-misc_test.cc | 1819 +++++
.../googlemock/test/gmock-matchers_test.h | 192 +
.../googlemock/test/gmock-more-actions_test.cc | 1550 ++++
.../googlemock/test/gmock-nice-strict_test.cc | 541 ++
.../googlemock/test/gmock-port_test.cc | 42 +
.../googlemock/test/gmock-pp-string_test.cc | 205 +
.../googlemock/test/gmock-pp_test.cc | 83 +
.../googlemock/test/gmock-spec-builders_test.cc | 2620 +++++++
.../googlemock/test/gmock_all_test.cc | 49 +
.../googlemock/test/gmock_ex_test.cc | 78 +
.../googlemock/test/gmock_leak_test.py | 104 +
.../googlemock/test/gmock_leak_test_.cc | 99 +
.../googlemock/test/gmock_link2_test.cc | 38 +
.../googlemock/test/gmock_link_test.cc | 38 +
.../googlemock/test/gmock_link_test.h | 689 ++
.../googlemock/test/gmock_output_test.py | 186 +
.../googlemock/test/gmock_output_test_.cc | 291 +
.../googlemock/test/gmock_output_test_golden.txt | 317 +
.../googlemock/test/gmock_stress_test.cc | 227 +
.../googlemock/test/gmock_test.cc | 179 +
.../googlemock/test/gmock_test_utils.py | 96 +
.../googletest-1.13.0/googletest/CMakeLists.txt | 338 +
.../test/googletest-1.13.0/googletest/README.md | 217 +
.../googletest/cmake/Config.cmake.in | 9 +
.../googletest-1.13.0/googletest/cmake/gtest.pc.in | 9 +
.../googletest/cmake/gtest_main.pc.in | 10 +
.../googletest/cmake/internal_utils.cmake | 356 +
.../googletest/cmake/libgtest.la.in | 21 +
.../googletest-1.13.0/googletest/docs/README.md | 4 +
.../include/gtest/gtest-assertion-result.h | 237 +
.../googletest/include/gtest/gtest-death-test.h | 345 +
.../googletest/include/gtest/gtest-matchers.h | 956 +++
.../googletest/include/gtest/gtest-message.h | 220 +
.../googletest/include/gtest/gtest-param-test.h | 545 ++
.../googletest/include/gtest/gtest-printers.h | 1131 +++
.../googletest/include/gtest/gtest-spi.h | 250 +
.../googletest/include/gtest/gtest-test-part.h | 192 +
.../googletest/include/gtest/gtest-typed-test.h | 331 +
.../googletest/include/gtest/gtest.h | 2318 ++++++
.../googletest/include/gtest/gtest_pred_impl.h | 279 +
.../googletest/include/gtest/gtest_prod.h | 60 +
.../include/gtest/internal/custom/README.md | 44 +
.../include/gtest/internal/custom/gtest-port.h | 37 +
.../include/gtest/internal/custom/gtest-printers.h | 42 +
.../include/gtest/internal/custom/gtest.h | 37 +
.../gtest/internal/gtest-death-test-internal.h | 307 +
.../include/gtest/internal/gtest-filepath.h | 227 +
.../include/gtest/internal/gtest-internal.h | 1571 ++++
.../include/gtest/internal/gtest-param-util.h | 1031 +++
.../include/gtest/internal/gtest-port-arch.h | 118 +
.../googletest/include/gtest/internal/gtest-port.h | 2460 +++++++
.../include/gtest/internal/gtest-string.h | 178 +
.../include/gtest/internal/gtest-type-util.h | 190 +
.../googletest/samples/prime_tables.h | 124 +
.../googletest/samples/sample1.cc | 66 +
.../googletest-1.13.0/googletest/samples/sample1.h | 41 +
.../googletest/samples/sample10_unittest.cc | 139 +
.../googletest/samples/sample1_unittest.cc | 148 +
.../googletest/samples/sample2.cc | 54 +
.../googletest-1.13.0/googletest/samples/sample2.h | 79 +
.../googletest/samples/sample2_unittest.cc | 107 +
.../googletest/samples/sample3-inl.h | 171 +
.../googletest/samples/sample3_unittest.cc | 146 +
.../googletest/samples/sample4.cc | 50 +
.../googletest-1.13.0/googletest/samples/sample4.h | 53 +
.../googletest/samples/sample4_unittest.cc | 53 +
.../googletest/samples/sample5_unittest.cc | 189 +
.../googletest/samples/sample6_unittest.cc | 214 +
.../googletest/samples/sample7_unittest.cc | 113 +
.../googletest/samples/sample8_unittest.cc | 152 +
.../googletest/samples/sample9_unittest.cc | 149 +
.../googletest-1.13.0/googletest/src/gtest-all.cc | 49 +
.../googletest/src/gtest-assertion-result.cc | 77 +
.../googletest/src/gtest-death-test.cc | 1620 ++++
.../googletest/src/gtest-filepath.cc | 410 ++
.../googletest/src/gtest-internal-inl.h | 1217 +++
.../googletest/src/gtest-matchers.cc | 98 +
.../googletest-1.13.0/googletest/src/gtest-port.cc | 1394 ++++
.../googletest/src/gtest-printers.cc | 553 ++
.../googletest/src/gtest-test-part.cc | 105 +
.../googletest/src/gtest-typed-test.cc | 104 +
.../test/googletest-1.13.0/googletest/src/gtest.cc | 6844 +++++++++++++++++
.../googletest-1.13.0/googletest/src/gtest_main.cc | 65 +
.../googletest-1.13.0/googletest/test/BUILD.bazel | 595 ++
.../test/googletest-break-on-failure-unittest.py | 208 +
.../test/googletest-break-on-failure-unittest_.cc | 83 +
.../test/googletest-catch-exceptions-test.py | 236 +
.../test/googletest-catch-exceptions-test_.cc | 289 +
.../googletest/test/googletest-color-test.py | 128 +
.../googletest/test/googletest-color-test_.cc | 60 +
.../googletest/test/googletest-death-test-test.cc | 1526 ++++
.../test/googletest-death-test_ex_test.cc | 91 +
.../googletest/test/googletest-env-var-test.py | 120 +
.../googletest/test/googletest-env-var-test_.cc | 130 +
.../test/googletest-failfast-unittest.py | 410 ++
.../test/googletest-failfast-unittest_.cc | 166 +
.../googletest/test/googletest-filepath-test.cc | 671 ++
.../googletest/test/googletest-filter-unittest.py | 670 ++
.../googletest/test/googletest-filter-unittest_.cc | 106 +
.../test/googletest-global-environment-unittest.py | 130 +
.../googletest-global-environment-unittest_.cc | 58 +
.../test/googletest-json-outfiles-test.py | 195 +
.../test/googletest-json-output-unittest.py | 912 +++
.../test/googletest-list-tests-unittest.py | 205 +
.../test/googletest-list-tests-unittest_.cc | 140 +
.../googletest/test/googletest-listener-test.cc | 514 ++
.../googletest/test/googletest-message-test.cc | 161 +
.../googletest/test/googletest-options-test.cc | 222 +
.../test/googletest-output-test-golden-lin.txt | 1196 +++
.../googletest/test/googletest-output-test.py | 346 +
.../googletest/test/googletest-output-test_.cc | 1053 +++
.../googletest-param-test-invalid-name1-test.py | 63 +
.../googletest-param-test-invalid-name1-test_.cc | 46 +
.../googletest-param-test-invalid-name2-test.py | 62 +
.../googletest-param-test-invalid-name2-test_.cc | 50 +
.../googletest/test/googletest-param-test-test.cc | 1173 +++
.../googletest/test/googletest-param-test-test.h | 49 +
.../googletest/test/googletest-param-test2-test.cc | 58 +
.../googletest/test/googletest-port-test.cc | 1299 ++++
.../googletest/test/googletest-printers-test.cc | 1987 +++++
.../test/googletest-setuptestsuite-test.py | 54 +
.../test/googletest-setuptestsuite-test_.cc | 44 +
.../googletest/test/googletest-shuffle-test.py | 323 +
.../googletest/test/googletest-shuffle-test_.cc | 100 +
.../googletest/test/googletest-test-part-test.cc | 220 +
.../test/googletest-throw-on-failure-test.py | 168 +
.../test/googletest-throw-on-failure-test_.cc | 71 +
.../test/googletest-uninitialized-test.py | 67 +
.../test/googletest-uninitialized-test_.cc | 39 +
.../googletest/test/gtest-typed-test2_test.cc | 39 +
.../googletest/test/gtest-typed-test_test.cc | 423 ++
.../googletest/test/gtest-typed-test_test.h | 57 +
.../googletest/test/gtest-unittest-api_test.cc | 328 +
.../googletest/test/gtest_all_test.cc | 46 +
.../test/gtest_assert_by_exception_test.cc | 112 +
.../googletest/test/gtest_dirs_test.cc | 97 +
.../googletest/test/gtest_environment_test.cc | 179 +
.../googletest/test/gtest_help_test.py | 189 +
.../googletest/test/gtest_help_test_.cc | 44 +
.../googletest/test/gtest_json_test_utils.py | 62 +
.../googletest/test/gtest_list_output_unittest.py | 286 +
.../googletest/test/gtest_list_output_unittest_.cc | 77 +
.../googletest/test/gtest_main_unittest.cc | 42 +
.../googletest/test/gtest_no_test_unittest.cc | 54 +
.../googletest/test/gtest_pred_impl_unittest.cc | 2070 ++++++
.../googletest/test/gtest_premature_exit_test.cc | 128 +
.../googletest/test/gtest_prod_test.cc | 56 +
.../googletest/test/gtest_repeat_test.cc | 222 +
.../test/gtest_skip_check_output_test.py | 59 +
.../gtest_skip_environment_check_output_test.py | 54 +
.../test/gtest_skip_in_environment_setup_test.cc | 50 +
.../googletest/test/gtest_skip_test.cc | 51 +
.../googletest/test/gtest_sole_header_test.cc | 54 +
.../googletest/test/gtest_stress_test.cc | 242 +
.../test/gtest_test_macro_stack_footprint_test.cc | 89 +
.../googletest/test/gtest_test_utils.py | 255 +
.../googletest/test/gtest_testbridge_test.py | 63 +
.../googletest/test/gtest_testbridge_test_.cc | 42 +
.../test/gtest_throw_on_failure_ex_test.cc | 90 +
.../googletest/test/gtest_unittest.cc | 7756 ++++++++++++++++++++
.../googletest/test/gtest_xml_outfile1_test_.cc | 43 +
.../googletest/test/gtest_xml_outfile2_test_.cc | 45 +
.../googletest/test/gtest_xml_outfiles_test.py | 135 +
.../googletest/test/gtest_xml_output_unittest.py | 415 ++
.../googletest/test/gtest_xml_output_unittest_.cc | 195 +
.../googletest/test/gtest_xml_test_utils.py | 201 +
.../googletest/test/production.cc | 35 +
.../googletest-1.13.0/googletest/test/production.h | 55 +
lib/yamlcpp/test/{ => integration}/BUILD.bazel | 8 +-
lib/yamlcpp/test/integration/emitter_test.cpp | 46 +-
lib/yamlcpp/test/{ => integration}/handler_test.h | 0
lib/yamlcpp/test/integration/load_node_test.cpp | 87 +
lib/yamlcpp/test/node/node_test.cpp | 29 +-
lib/yamlcpp/util/read.cpp | 4 +-
lib/yamlcpp/util/sandbox.cpp | 4 +-
lib/yamlcpp/yaml-cpp-config.cmake.in | 17 +-
plugins/slice/Data.h | 5 +-
plugins/slice/server.cc | 35 +-
plugins/slice/slice.cc | 13 +-
src/mgmt/rpc/server/unit_tests/test_rpcserver.cc | 90 +-
tests/gold_tests/autest-site/conditions.test.ext | 212 +
tests/gold_tests/autest-site/microserver.test.ext | 25 +-
tests/gold_tests/autest-site/ports.py | 67 +-
.../jsonrpc/plugins/jsonrpc_plugin_handler_test.cc | 7 +-
.../polite_hook_wait/polite_hook_wait.cc | 3 +-
.../tls/tls_check_cert_select_plugin.test.py | 5 +-
tests/gold_tests/tls/tls_client_versions.test.py | 32 +-
.../tls/tls_client_versions_minmax.test.py | 48 +-
tests/prepare_proxy_verifier.sh | 23 +-
tests/proxy-verifier-checksum.txt | 1 +
tests/proxy-verifier-version.txt | 2 +-
324 files changed, 116139 insertions(+), 333 deletions(-)
create mode 100644 lib/yamlcpp/.bazelignore
create mode 100644 lib/yamlcpp/.github/dependabot.yml
create mode 100644 lib/yamlcpp/.github/workflows/build.yml
create mode 100644 lib/yamlcpp/.github/workflows/bzlmod-archive.yml
delete mode 100644 lib/yamlcpp/.travis.yml
create mode 100644 lib/yamlcpp/MODULE.bazel
create mode 100644 lib/yamlcpp/MODULE.bazel.lock
delete mode 100644 lib/yamlcpp/WORKSPACE
create mode 100644 lib/yamlcpp/include/yaml-cpp/fptostring.h
create mode 100644 lib/yamlcpp/src/contrib/dragonbox.h
create mode 100644 lib/yamlcpp/src/fptostring.cpp
create mode 100644 lib/yamlcpp/test/cmake/CMakeLists.txt
create mode 100644 lib/yamlcpp/test/cmake/main.cpp
create mode 100644 lib/yamlcpp/test/fptostring_test.cpp
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/.clang-format
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/.github/ISSUE_TEMPLATE/00-bug_report.yml
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/.github/ISSUE_TEMPLATE/10-feature_request.yml
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/.github/ISSUE_TEMPLATE/config.yml
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/.github/workflows/gtest-ci.yml
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/.gitignore
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/BUILD.bazel
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/CMakeLists.txt
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/CONTRIBUTING.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/CONTRIBUTORS
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/LICENSE
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/README.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/WORKSPACE
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/ci/linux-presubmit.sh
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/ci/macos-presubmit.sh
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/ci/windows-presubmit.bat
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/_config.yml
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/_data/navigation.yml
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/_layouts/default.html
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/_sass/main.scss
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/advanced.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/assets/css/style.scss
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/community_created_documentation.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/faq.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/gmock_cheat_sheet.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/gmock_cook_book.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/gmock_faq.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/gmock_for_dummies.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/index.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/pkgconfig.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/platforms.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/primer.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/quickstart-bazel.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/quickstart-cmake.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/reference/actions.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/reference/assertions.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/reference/matchers.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/reference/mocking.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/reference/testing.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/docs/samples.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/CMakeLists.txt
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/README.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/cmake/gmock.pc.in
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/cmake/gmock_main.pc.in
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/docs/README.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/gmock-actions.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/gmock-cardinalities.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/gmock-function-mocker.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/gmock-matchers.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/gmock-more-actions.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/gmock-more-matchers.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/gmock-nice-strict.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/gmock-spec-builders.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/gmock.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/internal/custom/README.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/internal/custom/gmock-generated-actions.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/internal/custom/gmock-matchers.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/internal/custom/gmock-port.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/internal/gmock-internal-utils.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/internal/gmock-port.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/include/gmock/internal/gmock-pp.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/src/gmock-all.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/src/gmock-cardinalities.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/src/gmock-internal-utils.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/src/gmock-matchers.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/src/gmock-spec-builders.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/src/gmock.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/src/gmock_main.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/BUILD.bazel
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-actions_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-cardinalities_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-function-mocker_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-internal-utils_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-matchers-arithmetic_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-matchers-comparisons_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-matchers-containers_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-matchers-misc_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-matchers_test.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-more-actions_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-nice-strict_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-port_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-pp-string_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-pp_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock-spec-builders_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_all_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_ex_test.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_leak_test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_leak_test_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_link2_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_link_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_link_test.h
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_output_test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_output_test_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_output_test_golden.txt
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_stress_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_test.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googlemock/test/gmock_test_utils.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/CMakeLists.txt
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/README.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/cmake/Config.cmake.in
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/cmake/gtest.pc.in
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/cmake/gtest_main.pc.in
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/cmake/internal_utils.cmake
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/cmake/libgtest.la.in
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/docs/README.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/gtest-assertion-result.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/gtest-death-test.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/gtest-matchers.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/gtest-message.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/gtest-param-test.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/gtest-printers.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/gtest-spi.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/gtest-test-part.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/gtest-typed-test.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/gtest.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/gtest_pred_impl.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/gtest_prod.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/internal/custom/README.md
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/internal/custom/gtest-port.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/internal/custom/gtest-printers.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/internal/custom/gtest.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/internal/gtest-death-test-internal.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/internal/gtest-filepath.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/internal/gtest-internal.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/internal/gtest-param-util.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/internal/gtest-port-arch.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/internal/gtest-port.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/internal/gtest-string.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/include/gtest/internal/gtest-type-util.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/prime_tables.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample1.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample1.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample10_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample1_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample2.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample2.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample2_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample3-inl.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample3_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample4.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample4.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample4_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample5_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample6_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample7_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample8_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/samples/sample9_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/src/gtest-all.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/src/gtest-assertion-result.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/src/gtest-death-test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/src/gtest-filepath.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/src/gtest-internal-inl.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/src/gtest-matchers.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/src/gtest-port.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/src/gtest-printers.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/src/gtest-test-part.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/src/gtest-typed-test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/src/gtest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/src/gtest_main.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/BUILD.bazel
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-break-on-failure-unittest.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-break-on-failure-unittest_.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-catch-exceptions-test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-catch-exceptions-test_.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-color-test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-color-test_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-death-test-test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-death-test_ex_test.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-env-var-test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-env-var-test_.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-failfast-unittest.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-failfast-unittest_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-filepath-test.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-filter-unittest.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-filter-unittest_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-global-environment-unittest.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-global-environment-unittest_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-json-outfiles-test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-json-output-unittest.py
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-list-tests-unittest.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-list-tests-unittest_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-listener-test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-message-test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-options-test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-output-test-golden-lin.txt
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-output-test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-output-test_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-param-test-invalid-name1-test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-param-test-invalid-name1-test_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-param-test-invalid-name2-test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-param-test-invalid-name2-test_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-param-test-test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-param-test-test.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-param-test2-test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-port-test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-printers-test.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-setuptestsuite-test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-setuptestsuite-test_.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-shuffle-test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-shuffle-test_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-test-part-test.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-throw-on-failure-test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-throw-on-failure-test_.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-uninitialized-test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/googletest-uninitialized-test_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest-typed-test2_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest-typed-test_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest-typed-test_test.h
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest-unittest-api_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_all_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_assert_by_exception_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_dirs_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_environment_test.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_help_test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_help_test_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_json_test_utils.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_list_output_unittest.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_list_output_unittest_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_main_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_no_test_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_pred_impl_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_premature_exit_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_prod_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_repeat_test.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_skip_check_output_test.py
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_skip_environment_check_output_test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_skip_in_environment_setup_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_skip_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_sole_header_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_stress_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_test_macro_stack_footprint_test.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_test_utils.py
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_testbridge_test.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_testbridge_test_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_throw_on_failure_ex_test.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_unittest.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_xml_outfile1_test_.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_xml_outfile2_test_.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_xml_outfiles_test.py
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_xml_output_unittest.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_xml_output_unittest_.cc
create mode 100755 lib/yamlcpp/test/googletest-1.13.0/googletest/test/gtest_xml_test_utils.py
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/production.cc
create mode 100644 lib/yamlcpp/test/googletest-1.13.0/googletest/test/production.h
copy lib/yamlcpp/test/{ => integration}/BUILD.bazel (52%)
rename lib/yamlcpp/test/{ => integration}/handler_test.h (100%)
create mode 100644 tests/proxy-verifier-checksum.txt
(trafficserver) 03/09: yaml-cpp-0.9.0 (#13192)
Posted by cm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit ed2995013101043f96e04a53837c39cb82043ba4
Author: Brian Neradt <br...@gmail.com>
AuthorDate: Fri May 22 13:00:36 2026 -0500
yaml-cpp-0.9.0 (#13192)
Update bundled yaml-cpp to 0.9.0 for GCC 16 compatibility
GCC 16 (Fedora 44) no longer exposes fixed-width integer types
through transitive includes, breaking the bundled yaml-cpp 0.8.0
build at emitterutils.cpp. Bumping the vendored library to 0.9.0
picks up the upstream fix and restores the build under GCC 16.
Also switch the JSONRPC test plugin to the generated
YAMLCPP_LIB_VERSION macro instead of a hardcoded "0.8.0" string
so the version compatibility check tracks the bundled library.
(cherry picked from commit e0513735cdee8809d6afe759c409ca2724be3a4d)
---
lib/yamlcpp/.bazelignore | 1 +
lib/yamlcpp/.codedocs | 2 +-
lib/yamlcpp/.github/dependabot.yml | 11 +
lib/yamlcpp/.github/workflows/build.yml | 141 +
lib/yamlcpp/.github/workflows/bzlmod-archive.yml | 19 +
lib/yamlcpp/.travis.yml | 37 -
lib/yamlcpp/BUILD.bazel | 2 +
lib/yamlcpp/CMakeLists.txt | 41 +-
lib/yamlcpp/CONTRIBUTING.md | 4 +-
lib/yamlcpp/MODULE.bazel | 14 +
lib/yamlcpp/MODULE.bazel.lock | 282 +
lib/yamlcpp/README.md | 32 +-
lib/yamlcpp/WORKSPACE | 10 -
lib/yamlcpp/include/yaml-cpp/dll.h | 2 -
lib/yamlcpp/include/yaml-cpp/emitfromevents.h | 1 +
lib/yamlcpp/include/yaml-cpp/emitter.h | 20 +-
lib/yamlcpp/include/yaml-cpp/emitterstyle.h | 7 +-
lib/yamlcpp/include/yaml-cpp/exceptions.h | 2 +
lib/yamlcpp/include/yaml-cpp/fptostring.h | 15 +
lib/yamlcpp/include/yaml-cpp/node/convert.h | 9 +-
.../include/yaml-cpp/node/detail/iterator.h | 2 +-
lib/yamlcpp/include/yaml-cpp/node/detail/memory.h | 1 +
.../include/yaml-cpp/node/detail/node_iterator.h | 2 +-
lib/yamlcpp/include/yaml-cpp/node/impl.h | 8 +-
lib/yamlcpp/include/yaml-cpp/node/type.h | 7 +-
lib/yamlcpp/include/yaml-cpp/null.h | 4 +-
lib/yamlcpp/include/yaml-cpp/traits.h | 1 +
lib/yamlcpp/include/yaml-cpp/yaml.h | 4 +
lib/yamlcpp/src/contrib/dragonbox.h | 4196 +++++++++++
lib/yamlcpp/src/emitfromevents.cpp | 9 +-
lib/yamlcpp/src/emitter.cpp | 27 +-
lib/yamlcpp/src/emitterutils.cpp | 76 +-
lib/yamlcpp/src/emitterutils.h | 14 +-
lib/yamlcpp/src/fptostring.cpp | 255 +
lib/yamlcpp/src/indentation.h | 1 -
lib/yamlcpp/src/memory.cpp | 8 +
lib/yamlcpp/src/node_data.cpp | 1 +
lib/yamlcpp/src/null.cpp | 13 +-
lib/yamlcpp/src/ostream_wrapper.cpp | 2 +-
lib/yamlcpp/src/parse.cpp | 2 +-
lib/yamlcpp/src/parser.cpp | 1 +
lib/yamlcpp/src/regeximpl.h | 4 +
lib/yamlcpp/src/scanner.cpp | 24 +
lib/yamlcpp/src/scanner.h | 1 +
lib/yamlcpp/src/scantoken.cpp | 7 +
lib/yamlcpp/src/singledocparser.cpp | 7 +-
lib/yamlcpp/src/stream.cpp | 21 +-
lib/yamlcpp/src/stream.h | 3 +-
lib/yamlcpp/src/token.h | 7 +-
lib/yamlcpp/test/BUILD.bazel | 22 +-
lib/yamlcpp/test/CMakeLists.txt | 23 +-
lib/yamlcpp/test/cmake/CMakeLists.txt | 21 +
lib/yamlcpp/test/cmake/main.cpp | 3 +
lib/yamlcpp/test/fptostring_test.cpp | 249 +
lib/yamlcpp/test/googletest-1.13.0/.clang-format | 4 +
.../.github/ISSUE_TEMPLATE/00-bug_report.yml | 53 +
.../.github/ISSUE_TEMPLATE/10-feature_request.yml | 33 +
.../.github/ISSUE_TEMPLATE/config.yml | 5 +
.../.github/workflows/gtest-ci.yml | 43 +
lib/yamlcpp/test/googletest-1.13.0/.gitignore | 84 +
lib/yamlcpp/test/googletest-1.13.0/BUILD.bazel | 218 +
lib/yamlcpp/test/googletest-1.13.0/CMakeLists.txt | 39 +
lib/yamlcpp/test/googletest-1.13.0/CONTRIBUTING.md | 131 +
lib/yamlcpp/test/googletest-1.13.0/CONTRIBUTORS | 65 +
lib/yamlcpp/test/googletest-1.13.0/LICENSE | 28 +
lib/yamlcpp/test/googletest-1.13.0/README.md | 117 +
lib/yamlcpp/test/googletest-1.13.0/WORKSPACE | 40 +
.../test/googletest-1.13.0/ci/linux-presubmit.sh | 134 +
.../test/googletest-1.13.0/ci/macos-presubmit.sh | 75 +
.../googletest-1.13.0/ci/windows-presubmit.bat | 56 +
.../test/googletest-1.13.0/docs/_config.yml | 1 +
.../googletest-1.13.0/docs/_data/navigation.yml | 43 +
.../googletest-1.13.0/docs/_layouts/default.html | 58 +
.../test/googletest-1.13.0/docs/_sass/main.scss | 200 +
.../test/googletest-1.13.0/docs/advanced.md | 2407 ++++++
.../googletest-1.13.0/docs/assets/css/style.scss | 5 +
.../docs/community_created_documentation.md | 7 +
lib/yamlcpp/test/googletest-1.13.0/docs/faq.md | 692 ++
.../googletest-1.13.0/docs/gmock_cheat_sheet.md | 241 +
.../test/googletest-1.13.0/docs/gmock_cook_book.md | 4343 +++++++++++
.../test/googletest-1.13.0/docs/gmock_faq.md | 390 +
.../googletest-1.13.0/docs/gmock_for_dummies.md | 700 ++
lib/yamlcpp/test/googletest-1.13.0/docs/index.md | 22 +
.../test/googletest-1.13.0/docs/pkgconfig.md | 148 +
.../test/googletest-1.13.0/docs/platforms.md | 35 +
lib/yamlcpp/test/googletest-1.13.0/docs/primer.md | 483 ++
.../googletest-1.13.0/docs/quickstart-bazel.md | 146 +
.../googletest-1.13.0/docs/quickstart-cmake.md | 156 +
.../googletest-1.13.0/docs/reference/actions.md | 115 +
.../googletest-1.13.0/docs/reference/assertions.md | 633 ++
.../googletest-1.13.0/docs/reference/matchers.md | 290 +
.../googletest-1.13.0/docs/reference/mocking.md | 589 ++
.../googletest-1.13.0/docs/reference/testing.md | 1431 ++++
lib/yamlcpp/test/googletest-1.13.0/docs/samples.md | 22 +
.../googletest-1.13.0/googlemock/CMakeLists.txt | 218 +
.../test/googletest-1.13.0/googlemock/README.md | 40 +
.../googletest-1.13.0/googlemock/cmake/gmock.pc.in | 10 +
.../googlemock/cmake/gmock_main.pc.in | 10 +
.../googletest-1.13.0/googlemock/docs/README.md | 4 +
.../googlemock/include/gmock/gmock-actions.h | 2302 ++++++
.../googlemock/include/gmock/gmock-cardinalities.h | 159 +
.../include/gmock/gmock-function-mocker.h | 517 ++
.../googlemock/include/gmock/gmock-matchers.h | 5620 ++++++++++++++
.../googlemock/include/gmock/gmock-more-actions.h | 662 ++
.../googlemock/include/gmock/gmock-more-matchers.h | 122 +
.../googlemock/include/gmock/gmock-nice-strict.h | 277 +
.../googlemock/include/gmock/gmock-spec-builders.h | 2111 ++++++
.../googlemock/include/gmock/gmock.h | 96 +
.../include/gmock/internal/custom/README.md | 18 +
.../internal/custom/gmock-generated-actions.h | 7 +
.../include/gmock/internal/custom/gmock-matchers.h | 37 +
.../include/gmock/internal/custom/gmock-port.h | 40 +
.../include/gmock/internal/gmock-internal-utils.h | 490 ++
.../googlemock/include/gmock/internal/gmock-port.h | 139 +
.../googlemock/include/gmock/internal/gmock-pp.h | 279 +
.../googletest-1.13.0/googlemock/src/gmock-all.cc | 46 +
.../googlemock/src/gmock-cardinalities.cc | 155 +
.../googlemock/src/gmock-internal-utils.cc | 251 +
.../googlemock/src/gmock-matchers.cc | 479 ++
.../googlemock/src/gmock-spec-builders.cc | 795 ++
.../test/googletest-1.13.0/googlemock/src/gmock.cc | 223 +
.../googletest-1.13.0/googlemock/src/gmock_main.cc | 72 +
.../googletest-1.13.0/googlemock/test/BUILD.bazel | 119 +
.../googlemock/test/gmock-actions_test.cc | 2167 ++++++
.../googlemock/test/gmock-cardinalities_test.cc | 422 ++
.../googlemock/test/gmock-function-mocker_test.cc | 1004 +++
.../googlemock/test/gmock-internal-utils_test.cc | 765 ++
.../test/gmock-matchers-arithmetic_test.cc | 1517 ++++
.../test/gmock-matchers-comparisons_test.cc | 2359 ++++++
.../test/gmock-matchers-containers_test.cc | 3129 ++++++++
.../googlemock/test/gmock-matchers-misc_test.cc | 1819 +++++
.../googlemock/test/gmock-matchers_test.h | 192 +
.../googlemock/test/gmock-more-actions_test.cc | 1550 ++++
.../googlemock/test/gmock-nice-strict_test.cc | 541 ++
.../googlemock/test/gmock-port_test.cc | 42 +
.../googlemock/test/gmock-pp-string_test.cc | 205 +
.../googlemock/test/gmock-pp_test.cc | 83 +
.../googlemock/test/gmock-spec-builders_test.cc | 2620 +++++++
.../googlemock/test/gmock_all_test.cc | 49 +
.../googlemock/test/gmock_ex_test.cc | 78 +
.../googlemock/test/gmock_leak_test.py | 104 +
.../googlemock/test/gmock_leak_test_.cc | 99 +
.../googlemock/test/gmock_link2_test.cc | 38 +
.../googlemock/test/gmock_link_test.cc | 38 +
.../googlemock/test/gmock_link_test.h | 689 ++
.../googlemock/test/gmock_output_test.py | 186 +
.../googlemock/test/gmock_output_test_.cc | 291 +
.../googlemock/test/gmock_output_test_golden.txt | 317 +
.../googlemock/test/gmock_stress_test.cc | 227 +
.../googlemock/test/gmock_test.cc | 179 +
.../googlemock/test/gmock_test_utils.py | 96 +
.../googletest-1.13.0/googletest/CMakeLists.txt | 338 +
.../test/googletest-1.13.0/googletest/README.md | 217 +
.../googletest/cmake/Config.cmake.in | 9 +
.../googletest-1.13.0/googletest/cmake/gtest.pc.in | 9 +
.../googletest/cmake/gtest_main.pc.in | 10 +
.../googletest/cmake/internal_utils.cmake | 356 +
.../googletest/cmake/libgtest.la.in | 21 +
.../googletest-1.13.0/googletest/docs/README.md | 4 +
.../include/gtest/gtest-assertion-result.h | 237 +
.../googletest/include/gtest/gtest-death-test.h | 345 +
.../googletest/include/gtest/gtest-matchers.h | 956 +++
.../googletest/include/gtest/gtest-message.h | 220 +
.../googletest/include/gtest/gtest-param-test.h | 545 ++
.../googletest/include/gtest/gtest-printers.h | 1131 +++
.../googletest/include/gtest/gtest-spi.h | 250 +
.../googletest/include/gtest/gtest-test-part.h | 192 +
.../googletest/include/gtest/gtest-typed-test.h | 331 +
.../googletest/include/gtest/gtest.h | 2318 ++++++
.../googletest/include/gtest/gtest_pred_impl.h | 279 +
.../googletest/include/gtest/gtest_prod.h | 60 +
.../include/gtest/internal/custom/README.md | 44 +
.../include/gtest/internal/custom/gtest-port.h | 37 +
.../include/gtest/internal/custom/gtest-printers.h | 42 +
.../include/gtest/internal/custom/gtest.h | 37 +
.../gtest/internal/gtest-death-test-internal.h | 307 +
.../include/gtest/internal/gtest-filepath.h | 227 +
.../include/gtest/internal/gtest-internal.h | 1571 ++++
.../include/gtest/internal/gtest-param-util.h | 1031 +++
.../include/gtest/internal/gtest-port-arch.h | 118 +
.../googletest/include/gtest/internal/gtest-port.h | 2460 +++++++
.../include/gtest/internal/gtest-string.h | 178 +
.../include/gtest/internal/gtest-type-util.h | 190 +
.../googletest/samples/prime_tables.h | 124 +
.../googletest/samples/sample1.cc | 66 +
.../googletest-1.13.0/googletest/samples/sample1.h | 41 +
.../googletest/samples/sample10_unittest.cc | 139 +
.../googletest/samples/sample1_unittest.cc | 148 +
.../googletest/samples/sample2.cc | 54 +
.../googletest-1.13.0/googletest/samples/sample2.h | 79 +
.../googletest/samples/sample2_unittest.cc | 107 +
.../googletest/samples/sample3-inl.h | 171 +
.../googletest/samples/sample3_unittest.cc | 146 +
.../googletest/samples/sample4.cc | 50 +
.../googletest-1.13.0/googletest/samples/sample4.h | 53 +
.../googletest/samples/sample4_unittest.cc | 53 +
.../googletest/samples/sample5_unittest.cc | 189 +
.../googletest/samples/sample6_unittest.cc | 214 +
.../googletest/samples/sample7_unittest.cc | 113 +
.../googletest/samples/sample8_unittest.cc | 152 +
.../googletest/samples/sample9_unittest.cc | 149 +
.../googletest-1.13.0/googletest/src/gtest-all.cc | 49 +
.../googletest/src/gtest-assertion-result.cc | 77 +
.../googletest/src/gtest-death-test.cc | 1620 ++++
.../googletest/src/gtest-filepath.cc | 410 ++
.../googletest/src/gtest-internal-inl.h | 1217 +++
.../googletest/src/gtest-matchers.cc | 98 +
.../googletest-1.13.0/googletest/src/gtest-port.cc | 1394 ++++
.../googletest/src/gtest-printers.cc | 553 ++
.../googletest/src/gtest-test-part.cc | 105 +
.../googletest/src/gtest-typed-test.cc | 104 +
.../test/googletest-1.13.0/googletest/src/gtest.cc | 6844 +++++++++++++++++
.../googletest-1.13.0/googletest/src/gtest_main.cc | 65 +
.../googletest-1.13.0/googletest/test/BUILD.bazel | 595 ++
.../test/googletest-break-on-failure-unittest.py | 208 +
.../test/googletest-break-on-failure-unittest_.cc | 83 +
.../test/googletest-catch-exceptions-test.py | 236 +
.../test/googletest-catch-exceptions-test_.cc | 289 +
.../googletest/test/googletest-color-test.py | 128 +
.../googletest/test/googletest-color-test_.cc | 60 +
.../googletest/test/googletest-death-test-test.cc | 1526 ++++
.../test/googletest-death-test_ex_test.cc | 91 +
.../googletest/test/googletest-env-var-test.py | 120 +
.../googletest/test/googletest-env-var-test_.cc | 130 +
.../test/googletest-failfast-unittest.py | 410 ++
.../test/googletest-failfast-unittest_.cc | 166 +
.../googletest/test/googletest-filepath-test.cc | 671 ++
.../googletest/test/googletest-filter-unittest.py | 670 ++
.../googletest/test/googletest-filter-unittest_.cc | 106 +
.../test/googletest-global-environment-unittest.py | 130 +
.../googletest-global-environment-unittest_.cc | 58 +
.../test/googletest-json-outfiles-test.py | 195 +
.../test/googletest-json-output-unittest.py | 912 +++
.../test/googletest-list-tests-unittest.py | 205 +
.../test/googletest-list-tests-unittest_.cc | 140 +
.../googletest/test/googletest-listener-test.cc | 514 ++
.../googletest/test/googletest-message-test.cc | 161 +
.../googletest/test/googletest-options-test.cc | 222 +
.../test/googletest-output-test-golden-lin.txt | 1196 +++
.../googletest/test/googletest-output-test.py | 346 +
.../googletest/test/googletest-output-test_.cc | 1053 +++
.../googletest-param-test-invalid-name1-test.py | 63 +
.../googletest-param-test-invalid-name1-test_.cc | 46 +
.../googletest-param-test-invalid-name2-test.py | 62 +
.../googletest-param-test-invalid-name2-test_.cc | 50 +
.../googletest/test/googletest-param-test-test.cc | 1173 +++
.../googletest/test/googletest-param-test-test.h | 49 +
.../googletest/test/googletest-param-test2-test.cc | 58 +
.../googletest/test/googletest-port-test.cc | 1299 ++++
.../googletest/test/googletest-printers-test.cc | 1987 +++++
.../test/googletest-setuptestsuite-test.py | 54 +
.../test/googletest-setuptestsuite-test_.cc | 44 +
.../googletest/test/googletest-shuffle-test.py | 323 +
.../googletest/test/googletest-shuffle-test_.cc | 100 +
.../googletest/test/googletest-test-part-test.cc | 220 +
.../test/googletest-throw-on-failure-test.py | 168 +
.../test/googletest-throw-on-failure-test_.cc | 71 +
.../test/googletest-uninitialized-test.py | 67 +
.../test/googletest-uninitialized-test_.cc | 39 +
.../googletest/test/gtest-typed-test2_test.cc | 39 +
.../googletest/test/gtest-typed-test_test.cc | 423 ++
.../googletest/test/gtest-typed-test_test.h | 57 +
.../googletest/test/gtest-unittest-api_test.cc | 328 +
.../googletest/test/gtest_all_test.cc | 46 +
.../test/gtest_assert_by_exception_test.cc | 112 +
.../googletest/test/gtest_dirs_test.cc | 97 +
.../googletest/test/gtest_environment_test.cc | 179 +
.../googletest/test/gtest_help_test.py | 189 +
.../googletest/test/gtest_help_test_.cc | 44 +
.../googletest/test/gtest_json_test_utils.py | 62 +
.../googletest/test/gtest_list_output_unittest.py | 286 +
.../googletest/test/gtest_list_output_unittest_.cc | 77 +
.../googletest/test/gtest_main_unittest.cc | 42 +
.../googletest/test/gtest_no_test_unittest.cc | 54 +
.../googletest/test/gtest_pred_impl_unittest.cc | 2070 ++++++
.../googletest/test/gtest_premature_exit_test.cc | 128 +
.../googletest/test/gtest_prod_test.cc | 56 +
.../googletest/test/gtest_repeat_test.cc | 222 +
.../test/gtest_skip_check_output_test.py | 59 +
.../gtest_skip_environment_check_output_test.py | 54 +
.../test/gtest_skip_in_environment_setup_test.cc | 50 +
.../googletest/test/gtest_skip_test.cc | 51 +
.../googletest/test/gtest_sole_header_test.cc | 54 +
.../googletest/test/gtest_stress_test.cc | 242 +
.../test/gtest_test_macro_stack_footprint_test.cc | 89 +
.../googletest/test/gtest_test_utils.py | 255 +
.../googletest/test/gtest_testbridge_test.py | 63 +
.../googletest/test/gtest_testbridge_test_.cc | 42 +
.../test/gtest_throw_on_failure_ex_test.cc | 90 +
.../googletest/test/gtest_unittest.cc | 7756 ++++++++++++++++++++
.../googletest/test/gtest_xml_outfile1_test_.cc | 43 +
.../googletest/test/gtest_xml_outfile2_test_.cc | 45 +
.../googletest/test/gtest_xml_outfiles_test.py | 135 +
.../googletest/test/gtest_xml_output_unittest.py | 415 ++
.../googletest/test/gtest_xml_output_unittest_.cc | 195 +
.../googletest/test/gtest_xml_test_utils.py | 201 +
.../googletest/test/production.cc | 35 +
.../googletest-1.13.0/googletest/test/production.h | 55 +
lib/yamlcpp/test/{ => integration}/BUILD.bazel | 8 +-
lib/yamlcpp/test/integration/emitter_test.cpp | 46 +-
lib/yamlcpp/test/{ => integration}/handler_test.h | 0
lib/yamlcpp/test/integration/load_node_test.cpp | 87 +
lib/yamlcpp/test/node/node_test.cpp | 29 +-
lib/yamlcpp/util/read.cpp | 4 +-
lib/yamlcpp/util/sandbox.cpp | 4 +-
lib/yamlcpp/yaml-cpp-config.cmake.in | 17 +-
.../jsonrpc/plugins/jsonrpc_plugin_handler_test.cc | 7 +-
307 files changed, 115662 insertions(+), 192 deletions(-)
diff --git a/lib/yamlcpp/.bazelignore b/lib/yamlcpp/.bazelignore
new file mode 100644
index 0000000000..446ebd009e
--- /dev/null
+++ b/lib/yamlcpp/.bazelignore
@@ -0,0 +1 @@
+test/googletest-1.13.0
diff --git a/lib/yamlcpp/.codedocs b/lib/yamlcpp/.codedocs
index 02e438213a..ae63822d21 100644
--- a/lib/yamlcpp/.codedocs
+++ b/lib/yamlcpp/.codedocs
@@ -8,7 +8,7 @@ EXAMPLE_PATH =
# One or more directories and files to exclude from documentation generation.
# Use relative paths with respect to the repository root directory.
-EXCLUDE = test/gtest-1.8.0/
+EXCLUDE = test/googletest-1.13.0/
# One or more wildcard patterns to exclude files and directories from document
# generation.
diff --git a/lib/yamlcpp/.github/dependabot.yml b/lib/yamlcpp/.github/dependabot.yml
new file mode 100644
index 0000000000..dc23806108
--- /dev/null
+++ b/lib/yamlcpp/.github/dependabot.yml
@@ -0,0 +1,11 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "monthly"
+ groups:
+ github-actions:
+ patterns:
+ - "*"
+
diff --git a/lib/yamlcpp/.github/workflows/build.yml b/lib/yamlcpp/.github/workflows/build.yml
new file mode 100644
index 0000000000..5c7614bd14
--- /dev/null
+++ b/lib/yamlcpp/.github/workflows/build.yml
@@ -0,0 +1,141 @@
+name: Github PR
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+ workflow_dispatch:
+permissions: read-all
+defaults:
+ run:
+ shell: bash
+jobs:
+ cmake-build:
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest, windows-latest, macos-latest]
+ cxx_standard: [11, 17, 20]
+ build: [static, shared]
+ googletest: [build, system]
+ generator: ["Default Generator", "MinGW Makefiles"]
+ exclude:
+ - os: ubuntu-latest
+ cxx_standard: 11
+ googletest: system
+ - os: macos-latest
+ build: shared
+ - os: macos-latest
+ generator: "MinGW Makefiles"
+ - os: ubuntu-latest
+ generator: "MinGW Makefiles"
+ - os: macos-latest
+ googletest: system
+ - os: windows-latest
+ googletest: system
+ env:
+ YAML_BUILD_SHARED_LIBS: ${{ matrix.build == 'shared' && 'ON' || 'OFF' }}
+ YAML_USE_SYSTEM_GTEST: ${{ matrix.googletest == 'system' && 'ON' || 'OFF' }}
+ CMAKE_GENERATOR: >-
+ ${{format(matrix.generator != 'Default Generator' && '-G "{0}"' || '', matrix.generator)}}
+ CMAKE_INSTALL_PREFIX: "${{ github.workspace }}/install-prefix"
+ CMAKE_BUILD_TYPE: Debug
+ CMAKE_CXX_FLAGS_DEBUG: ${{ matrix.googletest == 'build' && '-g -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC' || '-g' }}
+ runs-on: ${{ matrix.os }}
+ steps:
+
+ - uses: awalsh128/cache-apt-pkgs-action@latest
+ if: matrix.os == 'ubuntu-latest'
+ with:
+ packages: googletest libgmock-dev libgtest-dev
+ version: 1.0
+
+ - uses: actions/checkout@v6.0.2
+
+ - name: Configure
+ run: |
+ cmake \
+ ${{ env.CMAKE_GENERATOR }} \
+ -S "${{ github.workspace }}" \
+ -B build \
+ -D CMAKE_CXX_STANDARD=${{ matrix.cxx_standard }} \
+ -D CMAKE_INSTALL_PREFIX="${{ env.CMAKE_INSTALL_PREFIX }}" \
+ -D CMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
+ -D CMAKE_CXX_FLAGS_DEBUG="${{ env.CMAKE_CXX_FLAGS_DEBUG }}" \
+ -D YAML_BUILD_SHARED_LIBS=${{ env.YAML_BUILD_SHARED_LIBS }} \
+ -D YAML_USE_SYSTEM_GTEST=${{ env.YAML_USE_SYSTEM_GTEST }} \
+ -D YAML_CPP_BUILD_TESTS=ON
+
+ - name: Build
+ run: |
+ cmake \
+ --build build \
+ --config ${{ env.CMAKE_BUILD_TYPE }} \
+ --verbose \
+ --parallel
+
+ - name: Run Tests
+ shell: bash
+ run: |
+ ctest \
+ --test-dir build \
+ --build-config ${{ env.CMAKE_BUILD_TYPE }} \
+ --output-on-failure \
+ --verbose
+
+ - name: Install
+ run: cmake --install build --config ${{ env.CMAKE_BUILD_TYPE }}
+
+ - name: Configure CMake package test
+ run: |
+ cmake \
+ ${{ env.CMAKE_GENERATOR }} \
+ -S "${{ github.workspace }}/test/cmake" \
+ -B consumer-build \
+ -D CMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
+ -D CMAKE_PREFIX_PATH="${{ env.CMAKE_INSTALL_PREFIX }}"
+
+ - name: Build CMake package test
+ run: |
+ cmake \
+ --build consumer-build \
+ --config ${{ env.CMAKE_BUILD_TYPE }} \
+ --verbose
+
+ bazel-build:
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest, macos-latest]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v6.0.2
+
+ - name: Build
+ run: |
+ cd "${{ github.workspace }}"
+ bazel build :all
+
+ - name: Test
+ run: |
+ cd "${{ github.workspace }}"
+ bazel test test
+
+ bzlmod-build:
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest, macos-latest]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v6.0.2
+
+ - name: Build
+ shell: bash
+ run: |
+ cd "${{ github.workspace }}"
+ bazel build --enable_bzlmod :all
+
+ - name: Test
+ shell: bash
+ run: |
+ cd "${{ github.workspace }}"
+ bazel test --enable_bzlmod test
diff --git a/lib/yamlcpp/.github/workflows/bzlmod-archive.yml b/lib/yamlcpp/.github/workflows/bzlmod-archive.yml
new file mode 100644
index 0000000000..1b07d82ce6
--- /dev/null
+++ b/lib/yamlcpp/.github/workflows/bzlmod-archive.yml
@@ -0,0 +1,19 @@
+name: Bazel Release
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ # A release archive is required for bzlmod
+ # See: https://blog.bazel.build/2023/02/15/github-archive-checksum.html
+ bazel-release-archive:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v4.1.1
+ - run: git archive $GITHUB_REF -o "yaml-cpp-${GITHUB_REF:10}.tar.gz"
+ - run: gh release upload ${GITHUB_REF:10} "yaml-cpp-${GITHUB_REF:10}.tar.gz"
+ env:
+ GH_TOKEN: ${{ github.token }}
diff --git a/lib/yamlcpp/.travis.yml b/lib/yamlcpp/.travis.yml
deleted file mode 100644
index 46beb1d129..0000000000
--- a/lib/yamlcpp/.travis.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-language: c++
-
-matrix:
- include:
- - os: linux
- compiler: gcc
- - os: osx
- compiler: clang
- - os: osx
- compiler: gcc
-env:
- - CTEST_OUTPUT_ON_FAILURE=1
-
-before_script:
- - mkdir build
- - cd build
- - cmake ..
- - cd ..
-script:
- - cmake --build build
- - cmake --build build --target test
-
-addons:
- apt:
- sources:
- - ubuntu-toolchain-r-test
- - llvm-toolchain-precise-3.9
- packages:
- - g++-4.9
- - clang-3.9
- update: true
- homebrew:
- packages:
- - ccache
- - gcc@4.9
- - llvm@4
- update: true
diff --git a/lib/yamlcpp/BUILD.bazel b/lib/yamlcpp/BUILD.bazel
index 23e847e772..45ae375ee2 100644
--- a/lib/yamlcpp/BUILD.bazel
+++ b/lib/yamlcpp/BUILD.bazel
@@ -1,3 +1,5 @@
+load("@rules_cc//cc:defs.bzl", "cc_library")
+
yaml_cpp_defines = select({
# On Windows, ensure static linking is used.
"@platforms//os:windows": ["YAML_CPP_STATIC_DEFINE", "YAML_CPP_NO_CONTRIB"],
diff --git a/lib/yamlcpp/CMakeLists.txt b/lib/yamlcpp/CMakeLists.txt
index 6275d48893..631bfa34c8 100644
--- a/lib/yamlcpp/CMakeLists.txt
+++ b/lib/yamlcpp/CMakeLists.txt
@@ -1,6 +1,6 @@
-# 3.5 is actually available almost everywhere, but this a good minimum
-# manual edit the upper version limit from upstream to avoid deprecation warning
-cmake_minimum_required(VERSION 3.4...3.14)
+# 3.5 is actually available almost everywhere.
+# 3.30 as the upper policy limit avoids CMake deprecation warnings.
+cmake_minimum_required(VERSION 3.5...3.30)
# enable MSVC_RUNTIME_LIBRARY target property
# see https://cmake.org/cmake/help/latest/policy/CMP0091.html
@@ -8,7 +8,7 @@ if(POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif()
-project(YAML_CPP VERSION 0.8.0 LANGUAGES CXX)
+project(YAML_CPP VERSION 0.9.0 LANGUAGES CXX)
set(YAML_CPP_MAIN_PROJECT OFF)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
@@ -25,14 +25,20 @@ option(YAML_CPP_BUILD_CONTRIB "Enable yaml-cpp contrib in library" ON)
option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON)
option(YAML_BUILD_SHARED_LIBS "Build yaml-cpp shared library" ${BUILD_SHARED_LIBS})
option(YAML_CPP_INSTALL "Enable generation of yaml-cpp install targets" ${YAML_CPP_MAIN_PROJECT})
-option(YAML_CPP_FORMAT_SOURCE "Format source" ON)
+option(YAML_CPP_FORMAT_SOURCE "Format source" ${YAML_CPP_MAIN_PROJECT})
+option(YAML_CPP_DISABLE_UNINSTALL "Disable uninstallation of yaml-cpp" OFF)
+option(YAML_USE_SYSTEM_GTEST "Use system googletest if found" OFF)
+option(YAML_ENABLE_PIC "Use Position-Independent Code " ON)
+
cmake_dependent_option(YAML_CPP_BUILD_TESTS
"Enable yaml-cpp tests" OFF
"BUILD_TESTING;YAML_CPP_MAIN_PROJECT" OFF)
cmake_dependent_option(YAML_MSVC_SHARED_RT
"MSVC: Build yaml-cpp with shared runtime libs (/MD)" ON
"CMAKE_SYSTEM_NAME MATCHES Windows" OFF)
-
+set(YAML_CPP_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/yaml-cpp"
+ CACHE STRING "Path to install the CMake package to")
+
if (YAML_CPP_FORMAT_SOURCE)
find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format)
endif()
@@ -45,10 +51,6 @@ else()
set(yaml-cpp-label-postfix "static")
endif()
-if (NOT YAML_BUILD_SHARED_LIBS)
- set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-endif()
-
set(build-shared $<BOOL:${YAML_BUILD_SHARED_LIBS}>)
set(build-windows-dll $<AND:$<BOOL:${CMAKE_HOST_WIN32}>,${build-shared}>)
set(not-msvc $<NOT:$<CXX_COMPILER_ID:MSVC>>)
@@ -90,7 +92,7 @@ set_property(TARGET yaml-cpp
CXX_STANDARD_REQUIRED ON)
if (NOT YAML_BUILD_SHARED_LIBS)
- set_property(TARGET yaml-cpp PROPERTY POSITION_INDEPENDENT_CODE ON)
+ set_property(TARGET yaml-cpp PROPERTY POSITION_INDEPENDENT_CODE ${YAML_ENABLE_PIC})
endif()
target_include_directories(yaml-cpp
@@ -109,7 +111,7 @@ endif()
if(YAML_CPP_MAIN_PROJECT)
target_compile_options(yaml-cpp
PRIVATE
- $<${not-msvc}:-Wall -Wextra -Weffc++ -Wno-long-long>
+ $<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long>
$<${not-msvc}:-pedantic -pedantic-errors>)
endif()
@@ -148,13 +150,12 @@ set_target_properties(yaml-cpp PROPERTIES
PROJECT_LABEL "yaml-cpp ${yaml-cpp-label-postfix}"
DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
-set(CONFIG_EXPORT_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/yaml-cpp")
-set(EXPORT_TARGETS yaml-cpp)
+set(EXPORT_TARGETS yaml-cpp::yaml-cpp)
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/yaml-cpp-config.cmake.in"
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
- INSTALL_DESTINATION "${CONFIG_EXPORT_DIR}"
- PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR CONFIG_EXPORT_DIR YAML_BUILD_SHARED_LIBS)
+ INSTALL_DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}"
+ PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR)
unset(EXPORT_TARGETS)
write_basic_package_version_file(
@@ -174,15 +175,14 @@ if (YAML_CPP_INSTALL)
FILES_MATCHING PATTERN "*.h")
install(EXPORT yaml-cpp-targets
NAMESPACE yaml-cpp::
- DESTINATION "${CONFIG_EXPORT_DIR}")
+ DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}")
install(FILES
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
- DESTINATION "${CONFIG_EXPORT_DIR}")
+ DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}")
install(FILES "${PROJECT_BINARY_DIR}/yaml-cpp.pc"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()
-unset(CONFIG_EXPORT_DIR)
if(YAML_CPP_BUILD_TESTS)
add_subdirectory(test)
@@ -197,11 +197,12 @@ if (YAML_CPP_FORMAT_SOURCE AND YAML_CPP_CLANG_FORMAT_EXE)
COMMAND clang-format --style=file -i $<TARGET_PROPERTY:yaml-cpp,SOURCES>
COMMAND_EXPAND_LISTS
COMMENT "Running clang-format"
+ WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
VERBATIM)
endif()
# uninstall target
-if(NOT TARGET uninstall)
+if(YAML_CPP_INSTALL AND NOT YAML_CPP_DISABLE_UNINSTALL AND NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
diff --git a/lib/yamlcpp/CONTRIBUTING.md b/lib/yamlcpp/CONTRIBUTING.md
index 5705fe2bcf..e4ca076dc8 100644
--- a/lib/yamlcpp/CONTRIBUTING.md
+++ b/lib/yamlcpp/CONTRIBUTING.md
@@ -17,9 +17,9 @@ Commit messages should be in the imperative mood, as described in the [Git contr
# Tests
-Please verify the tests pass by running the target `test/yaml-cpp-tests`.
+Please verify the tests pass by configuring CMake with `-D YAML_CPP_BUILD_TESTS=ON` and running the target `test/yaml-cpp-tests`.
-If you are adding functionality, add tests accordingly.
+If you are adding functionality, add tests accordingly. Note that the "spec tests" are reserved for examples directly from the YAML spec, so if you have new examples, put them in other test files.
# Pull request process
diff --git a/lib/yamlcpp/MODULE.bazel b/lib/yamlcpp/MODULE.bazel
new file mode 100644
index 0000000000..132cde13b2
--- /dev/null
+++ b/lib/yamlcpp/MODULE.bazel
@@ -0,0 +1,14 @@
+"""
+yaml-cpp is a YAML parser and emitter in c++ matching the YAML specification.
+"""
+
+module(
+ name = "yaml-cpp",
+ compatibility_level = 1,
+ version = "0.8.0",
+)
+
+bazel_dep(name = "platforms", version = "1.0.0")
+bazel_dep(name = "rules_cc", version = "0.2.14")
+
+bazel_dep(name = "googletest", version = "1.17.0.bcr.2", dev_dependency = True)
diff --git a/lib/yamlcpp/MODULE.bazel.lock b/lib/yamlcpp/MODULE.bazel.lock
new file mode 100644
index 0000000000..d06bb14a0b
--- /dev/null
+++ b/lib/yamlcpp/MODULE.bazel.lock
@@ -0,0 +1,282 @@
+{
+ "lockFileVersion": 24,
+ "registryFileHashes": {
+ "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
+ "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
+ "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16",
+ "https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1",
+ "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215",
+ "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/source.json": "d725d73707d01bb46ab3ca59ba408b8e9bd336642ca77a2269d4bfb8bbfd413d",
+ "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85",
+ "https://bcr.bazel.build/modules/apple_support/1.22.1/MODULE.bazel": "90bd1a660590f3ceffbdf524e37483094b29352d85317060b2327fff8f3f4458",
+ "https://bcr.bazel.build/modules/apple_support/1.23.1/MODULE.bazel": "53763fed456a968cf919b3240427cf3a9d5481ec5466abc9d5dc51bc70087442",
+ "https://bcr.bazel.build/modules/apple_support/1.23.1/source.json": "d888b44312eb0ad2c21a91d026753f330caa48a25c9b2102fae75eb2b0dcfdd2",
+ "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
+ "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
+ "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
+ "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
+ "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
+ "https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65",
+ "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d",
+ "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
+ "https://bcr.bazel.build/modules/bazel_features/1.30.0/source.json": "b07e17f067fe4f69f90b03b36ef1e08fe0d1f3cac254c1241a1818773e3423bc",
+ "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
+ "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953",
+ "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
+ "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
+ "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
+ "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
+ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
+ "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
+ "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108",
+ "https://bcr.bazel.build/modules/googletest/1.17.0.bcr.2/MODULE.bazel": "827f54f492a3ce549c940106d73de332c2b30cebd0c20c0bc5d786aba7f116cb",
+ "https://bcr.bazel.build/modules/googletest/1.17.0.bcr.2/source.json": "3664514073a819992320ffbce5825e4238459df344d8b01748af2208f8d2e1eb",
+ "https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
+ "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
+ "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
+ "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
+ "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
+ "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
+ "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
+ "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
+ "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
+ "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc",
+ "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580",
+ "https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96",
+ "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
+ "https://bcr.bazel.build/modules/protobuf/23.1/MODULE.bazel": "88b393b3eb4101d18129e5db51847cd40a5517a53e81216144a8c32dfeeca52a",
+ "https://bcr.bazel.build/modules/protobuf/24.4/MODULE.bazel": "7bc7ce5f2abf36b3b7b7c8218d3acdebb9426aeb35c2257c96445756f970eb12",
+ "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
+ "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92",
+ "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e",
+ "https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981",
+ "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.13.6/MODULE.bazel": "2d746fda559464b253b2b2e6073cb51643a2ac79009ca02100ebbc44b4548656",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.13.6/source.json": "6aa0703de8efb20cc897bbdbeb928582ee7beaf278bcd001ac253e1605bddfae",
+ "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
+ "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a",
+ "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa",
+ "https://bcr.bazel.build/modules/re2/2025-08-12.bcr.1/MODULE.bazel": "e09b434b122bfb786a69179f9b325e35cb1856c3f56a7a81dd61609260ed46e1",
+ "https://bcr.bazel.build/modules/re2/2025-08-12.bcr.1/source.json": "a8ae7c09533bf67f9f6e5122d884d5741600b09d78dca6fc0f2f8d2ee0c2d957",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.4/MODULE.bazel": "bb03a452a7527ac25a7518fb86a946ef63df860b9657d8323a0c50f8504fb0b9",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.14/source.json": "55d0a4587c5592fad350f6e698530f4faf0e7dd15e69d43f8d87e220c78bea54",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642",
+ "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
+ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
+ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
+ "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
+ "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
+ "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39",
+ "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6",
+ "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
+ "https://bcr.bazel.build/modules/rules_java/7.1.0/MODULE.bazel": "30d9135a2b6561c761bd67bd4990da591e6bdc128790ce3e7afd6a3558b2fb64",
+ "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
+ "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
+ "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
+ "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
+ "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
+ "https://bcr.bazel.build/modules/rules_java/8.14.0/MODULE.bazel": "717717ed40cc69994596a45aec6ea78135ea434b8402fb91b009b9151dd65615",
+ "https://bcr.bazel.build/modules/rules_java/8.14.0/source.json": "8a88c4ca9e8759da53cddc88123880565c520503321e2566b4e33d0287a3d4bc",
+ "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
+ "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
+ "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
+ "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
+ "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
+ "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
+ "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
+ "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
+ "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483",
+ "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
+ "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2",
+ "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1",
+ "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
+ "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
+ "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
+ "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
+ "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
+ "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937",
+ "https://bcr.bazel.build/modules/rules_python/0.34.0/MODULE.bazel": "1d623d026e075b78c9fde483a889cda7996f5da4f36dffb24c246ab30f06513a",
+ "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
+ "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7",
+ "https://bcr.bazel.build/modules/rules_python/1.5.1/MODULE.bazel": "acfe65880942d44a69129d4c5c3122d57baaf3edf58ae5a6bd4edea114906bf5",
+ "https://bcr.bazel.build/modules/rules_python/1.5.1/source.json": "aa903e1bcbdfa1580f2b8e2d55100b7c18bc92d779ebb507fec896c75635f7bd",
+ "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
+ "https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95",
+ "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
+ "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
+ "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef",
+ "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
+ "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7",
+ "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
+ "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
+ "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
+ "https://bcr.bazel.build/modules/upb/0.0.0-20230516-61a97ef/MODULE.bazel": "c0df5e35ad55e264160417fd0875932ee3c9dda63d9fccace35ac62f45e1b6f9",
+ "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806",
+ "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
+ },
+ "selectedYankedVersions": {},
+ "moduleExtensions": {
+ "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
+ "general": {
+ "bzlTransitiveDigest": "rL/34P1aFDq2GqVC2zCFgQ8nTuOC6ziogocpvG50Qz8=",
+ "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "com_github_jetbrains_kotlin_git": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository",
+ "attributes": {
+ "urls": [
+ "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip"
+ ],
+ "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88"
+ }
+ },
+ "com_github_jetbrains_kotlin": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository",
+ "attributes": {
+ "git_repository_name": "com_github_jetbrains_kotlin_git",
+ "compiler_version": "1.9.23"
+ }
+ },
+ "com_github_google_ksp": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository",
+ "attributes": {
+ "urls": [
+ "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip"
+ ],
+ "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d",
+ "strip_version": "1.9.23-1.0.20"
+ }
+ },
+ "com_github_pinterest_ktlint": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
+ "attributes": {
+ "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985",
+ "urls": [
+ "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint"
+ ],
+ "executable": true
+ }
+ },
+ "rules_android": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806",
+ "strip_prefix": "rules_android-0.1.1",
+ "urls": [
+ "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"
+ ]
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_kotlin+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ },
+ "@@rules_python+//python/uv:uv.bzl%uv": {
+ "general": {
+ "bzlTransitiveDigest": "8vT1ddXtljNxYD0tJkksqzeKE6xqx4Ix+tXthAppjTI=",
+ "usagesDigest": "WYhzIw9khRBy34H1GxV5+fI1yi07O90NmCXosPUdHWQ=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "uv": {
+ "repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo",
+ "attributes": {
+ "toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'",
+ "toolchain_names": [
+ "none"
+ ],
+ "toolchain_implementations": {
+ "none": "'@@rules_python+//python:none'"
+ },
+ "toolchain_compatible_with": {
+ "none": [
+ "@platforms//:incompatible"
+ ]
+ },
+ "toolchain_target_settings": {}
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_python+",
+ "bazel_tools",
+ "bazel_tools"
+ ],
+ [
+ "rules_python+",
+ "platforms",
+ "platforms"
+ ]
+ ]
+ }
+ }
+ },
+ "facts": {}
+}
diff --git a/lib/yamlcpp/README.md b/lib/yamlcpp/README.md
index 70c231445d..ec72636d17 100644
--- a/lib/yamlcpp/README.md
+++ b/lib/yamlcpp/README.md
@@ -31,6 +31,17 @@ cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=on|OFF] ..
* `yaml-cpp` builds a static library by default, you may want to build a shared library by specifying `-DYAML_BUILD_SHARED_LIBS=ON`.
+ * [Debug mode of the GNU standard C++
+ library](https://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html)
+ can be used when both `yaml-cpp` and client code is compiled with the
+ `_GLIBCXX_DEBUG` flag (e.g. by calling CMake with `-D
+ CMAKE_CXX_FLAGS_DEBUG='-g -D_GLIBCXX_DEBUG'` option).
+
+ Note that for `yaml-cpp` unit tests to run successfully, the _GoogleTest_
+ library also must be built with this flag, i.e. the system one cannot be
+ used (the _YAML_USE_SYSTEM_GTEST_ CMake option must be _OFF_, which is the
+ default).
+
* For more options on customizing the build, see the [CMakeLists.txt](https://github.com/jbeder/yaml-cpp/blob/master/CMakeLists.txt) file.
#### 2. Build it!
@@ -38,13 +49,30 @@ cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=on|OFF] ..
**Note:** To clean up, just remove the `build` directory.
+## How to Integrate it within your project using CMake
+
+You can use for example FetchContent :
+
+```cmake
+include(FetchContent)
+
+FetchContent_Declare(
+ yaml-cpp
+ GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
+ GIT_TAG <tag_name> # Can be a tag (yaml-cpp-x.x.x), a commit hash, or a branch name (master)
+)
+FetchContent_MakeAvailable(yaml-cpp)
+
+target_link_libraries(YOUR_LIBRARY PUBLIC yaml-cpp::yaml-cpp) # The library or executable that require yaml-cpp library
+```
+
## Recent Releases
-[yaml-cpp 0.6.0](https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-0.6.0) released! This release requires C++11, and no longer depends on Boost.
+[yaml-cpp 0.8.0](https://github.com/jbeder/yaml-cpp/releases/tag/0.8.0) released!
[yaml-cpp 0.3.0](https://github.com/jbeder/yaml-cpp/releases/tag/release-0.3.0) is still available if you want the old API.
-**The old API will continue to be supported, and will still receive bugfixes!** The 0.3.x and 0.4.x versions will be old API releases, and 0.5.x and above will all be new API releases.
+**The old API will stop receiving bugfixes in 2026.** The 0.3.x versions provide the old API, and 0.5.x and above all provide the new API.
# API Documentation
diff --git a/lib/yamlcpp/WORKSPACE b/lib/yamlcpp/WORKSPACE
deleted file mode 100644
index d5ecc0b548..0000000000
--- a/lib/yamlcpp/WORKSPACE
+++ /dev/null
@@ -1,10 +0,0 @@
-workspace(name = "com_github_jbeder_yaml_cpp")
-
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-
-http_archive(
- name = "com_google_googletest",
- strip_prefix = "googletest-release-1.8.1",
- url = "https://github.com/google/googletest/archive/release-1.8.1.tar.gz",
- sha256 = "9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c",
-)
diff --git a/lib/yamlcpp/include/yaml-cpp/dll.h b/lib/yamlcpp/include/yaml-cpp/dll.h
index eabdda1d95..4e55ab8c22 100644
--- a/lib/yamlcpp/include/yaml-cpp/dll.h
+++ b/lib/yamlcpp/include/yaml-cpp/dll.h
@@ -15,11 +15,9 @@
# ifndef YAML_CPP_API
# ifdef yaml_cpp_EXPORTS
/* We are building this library */
-# pragma message( "Defining YAML_CPP_API for DLL export" )
# define YAML_CPP_API __declspec(dllexport)
# else
/* We are using this library */
-# pragma message( "Defining YAML_CPP_API for DLL import" )
# define YAML_CPP_API __declspec(dllimport)
# endif
# endif
diff --git a/lib/yamlcpp/include/yaml-cpp/emitfromevents.h b/lib/yamlcpp/include/yaml-cpp/emitfromevents.h
index 1f389c5a13..c00d26e74d 100644
--- a/lib/yamlcpp/include/yaml-cpp/emitfromevents.h
+++ b/lib/yamlcpp/include/yaml-cpp/emitfromevents.h
@@ -23,6 +23,7 @@ class Emitter;
class EmitFromEvents : public EventHandler {
public:
EmitFromEvents(Emitter& emitter);
+ ~EmitFromEvents() override = default;
void OnDocumentStart(const Mark& mark) override;
void OnDocumentEnd() override;
diff --git a/lib/yamlcpp/include/yaml-cpp/emitter.h b/lib/yamlcpp/include/yaml-cpp/emitter.h
index 210b1ec974..67810ef341 100644
--- a/lib/yamlcpp/include/yaml-cpp/emitter.h
+++ b/lib/yamlcpp/include/yaml-cpp/emitter.h
@@ -9,18 +9,24 @@
#include <cmath>
#include <cstddef>
+#include <cstring>
#include <limits>
#include <memory>
#include <sstream>
#include <string>
#include <type_traits>
+#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
+#include <string_view>
+#endif
+
#include "yaml-cpp/binary.h"
#include "yaml-cpp/dll.h"
#include "yaml-cpp/emitterdef.h"
#include "yaml-cpp/emittermanip.h"
#include "yaml-cpp/null.h"
#include "yaml-cpp/ostream_wrapper.h"
+#include "yaml-cpp/fptostring.h"
namespace YAML {
class Binary;
@@ -67,6 +73,7 @@ class YAML_CPP_API Emitter {
Emitter& SetLocalPrecision(const _Precision& precision);
// overloads of write
+ Emitter& Write(const char* str, std::size_t size);
Emitter& Write(const std::string& str);
Emitter& Write(bool b);
Emitter& Write(char ch);
@@ -141,6 +148,7 @@ inline Emitter& Emitter::WriteIntegralType(T value) {
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream;
+ stream.imbue(std::locale::classic());
PrepareIntegralStream(stream);
stream << value;
m_stream << stream.str();
@@ -158,6 +166,7 @@ inline Emitter& Emitter::WriteStreamable(T value) {
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream;
+ stream.imbue(std::locale::classic());
SetStreamablePrecision<T>(stream);
bool special = false;
@@ -178,7 +187,7 @@ inline Emitter& Emitter::WriteStreamable(T value) {
}
if (!special) {
- stream << value;
+ stream << FpToString(value, stream.precision());
}
m_stream << stream.str();
@@ -198,8 +207,13 @@ inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
}
// overloads of insertion
+#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
+inline Emitter& operator<<(Emitter& emitter, const std::string_view& v) {
+ return emitter.Write(v.data(), v.size());
+}
+#endif
inline Emitter& operator<<(Emitter& emitter, const std::string& v) {
- return emitter.Write(v);
+ return emitter.Write(v.data(), v.size());
}
inline Emitter& operator<<(Emitter& emitter, bool v) {
return emitter.Write(v);
@@ -230,7 +244,7 @@ inline Emitter& operator<<(Emitter& emitter, const Binary& b) {
}
inline Emitter& operator<<(Emitter& emitter, const char* v) {
- return emitter.Write(std::string(v));
+ return emitter.Write(v, std::strlen(v));
}
inline Emitter& operator<<(Emitter& emitter, int v) {
diff --git a/lib/yamlcpp/include/yaml-cpp/emitterstyle.h b/lib/yamlcpp/include/yaml-cpp/emitterstyle.h
index 67bb3981b1..5a6355fa2b 100644
--- a/lib/yamlcpp/include/yaml-cpp/emitterstyle.h
+++ b/lib/yamlcpp/include/yaml-cpp/emitterstyle.h
@@ -8,9 +8,10 @@
#endif
namespace YAML {
-struct EmitterStyle {
- enum value { Default, Block, Flow };
-};
+namespace EmitterStyle {
+enum value { Default, Block, Flow };
+}
+
}
#endif // EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
diff --git a/lib/yamlcpp/include/yaml-cpp/exceptions.h b/lib/yamlcpp/include/yaml-cpp/exceptions.h
index f6b2602ae1..99e06b24eb 100644
--- a/lib/yamlcpp/include/yaml-cpp/exceptions.h
+++ b/lib/yamlcpp/include/yaml-cpp/exceptions.h
@@ -48,6 +48,8 @@ const char* const UNKNOWN_TOKEN = "unknown token";
const char* const DOC_IN_SCALAR = "illegal document indicator in scalar";
const char* const EOF_IN_SCALAR = "illegal EOF in scalar";
const char* const CHAR_IN_SCALAR = "illegal character in scalar";
+const char* const UNEXPECTED_SCALAR = "unexpected scalar";
+const char* const UNEXPECTED_FLOW = "plain value cannot start with flow indicator character";
const char* const TAB_IN_INDENTATION =
"illegal tab when looking for indentation";
const char* const FLOW_END = "illegal flow end";
diff --git a/lib/yamlcpp/include/yaml-cpp/fptostring.h b/lib/yamlcpp/include/yaml-cpp/fptostring.h
new file mode 100644
index 0000000000..051053be9a
--- /dev/null
+++ b/lib/yamlcpp/include/yaml-cpp/fptostring.h
@@ -0,0 +1,15 @@
+#ifndef YAML_H_FPTOSTRING
+#define YAML_H_FPTOSTRING
+
+#include "yaml-cpp/dll.h"
+
+#include <string>
+
+namespace YAML {
+// "precision = 0" refers to shortest known unique representation of the value
+YAML_CPP_API std::string FpToString(float v, size_t precision = 0);
+YAML_CPP_API std::string FpToString(double v, size_t precision = 0);
+YAML_CPP_API std::string FpToString(long double v, size_t precision = 0);
+}
+
+#endif
diff --git a/lib/yamlcpp/include/yaml-cpp/node/convert.h b/lib/yamlcpp/include/yaml-cpp/node/convert.h
index d0eb450f73..0f04ea6fd7 100644
--- a/lib/yamlcpp/include/yaml-cpp/node/convert.h
+++ b/lib/yamlcpp/include/yaml-cpp/node/convert.h
@@ -18,7 +18,7 @@
#include <valarray>
#include <vector>
-#if __cplusplus >= 201703L
+#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
#include <string_view>
#endif
@@ -28,6 +28,7 @@
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/type.h"
#include "yaml-cpp/null.h"
+#include "yaml-cpp/fptostring.h"
namespace YAML {
@@ -93,7 +94,7 @@ struct convert<char[N]> {
static Node encode(const char* rhs) { return Node(rhs); }
};
-#if __cplusplus >= 201703L
+#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
template <>
struct convert<std::string_view> {
static Node encode(std::string_view rhs) { return Node(std::string(rhs)); }
@@ -129,7 +130,7 @@ inner_encode(const T& rhs, std::stringstream& stream){
stream << ".inf";
}
} else {
- stream << rhs;
+ stream << FpToString(rhs, stream.precision());
}
}
@@ -171,6 +172,7 @@ ConvertStreamTo(std::stringstream& stream, T& rhs) {
\
static Node encode(const type& rhs) { \
std::stringstream stream; \
+ stream.imbue(std::locale::classic()); \
stream.precision(std::numeric_limits<type>::max_digits10); \
conversion::inner_encode(rhs, stream); \
return Node(stream.str()); \
@@ -182,6 +184,7 @@ ConvertStreamTo(std::stringstream& stream, T& rhs) {
} \
const std::string& input = node.Scalar(); \
std::stringstream stream(input); \
+ stream.imbue(std::locale::classic()); \
stream.unsetf(std::ios::dec); \
if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \
return false; \
diff --git a/lib/yamlcpp/include/yaml-cpp/node/detail/iterator.h b/lib/yamlcpp/include/yaml-cpp/node/detail/iterator.h
index 997c69a14c..04d2da4fca 100644
--- a/lib/yamlcpp/include/yaml-cpp/node/detail/iterator.h
+++ b/lib/yamlcpp/include/yaml-cpp/node/detail/iterator.h
@@ -41,7 +41,7 @@ class iterator_base {
using value_type = V;
using difference_type = std::ptrdiff_t;
using pointer = V*;
- using reference = V;
+ using reference = V&;
public:
iterator_base() : m_iterator(), m_pMemory() {}
diff --git a/lib/yamlcpp/include/yaml-cpp/node/detail/memory.h b/lib/yamlcpp/include/yaml-cpp/node/detail/memory.h
index e881545bf2..942ab668d4 100644
--- a/lib/yamlcpp/include/yaml-cpp/node/detail/memory.h
+++ b/lib/yamlcpp/include/yaml-cpp/node/detail/memory.h
@@ -25,6 +25,7 @@ class YAML_CPP_API memory {
memory() : m_nodes{} {}
node& create_node();
void merge(const memory& rhs);
+ size_t size() const;
private:
using Nodes = std::set<shared_node>;
diff --git a/lib/yamlcpp/include/yaml-cpp/node/detail/node_iterator.h b/lib/yamlcpp/include/yaml-cpp/node/detail/node_iterator.h
index 49dcf958db..6eb4ddc134 100644
--- a/lib/yamlcpp/include/yaml-cpp/node/detail/node_iterator.h
+++ b/lib/yamlcpp/include/yaml-cpp/node/detail/node_iterator.h
@@ -69,7 +69,7 @@ class node_iterator_base {
using value_type = node_iterator_value<V>;
using difference_type = std::ptrdiff_t;
using pointer = node_iterator_value<V>*;
- using reference = node_iterator_value<V>;
+ using reference = node_iterator_value<V>&;
using SeqIter = typename node_iterator_type<V>::seq;
using MapIter = typename node_iterator_type<V>::map;
diff --git a/lib/yamlcpp/include/yaml-cpp/node/impl.h b/lib/yamlcpp/include/yaml-cpp/node/impl.h
index 312281f18c..f5d622b254 100644
--- a/lib/yamlcpp/include/yaml-cpp/node/impl.h
+++ b/lib/yamlcpp/include/yaml-cpp/node/impl.h
@@ -97,7 +97,7 @@ struct as_if {
if (!node.m_pNode)
return fallback;
- T t;
+ T t = fallback;
if (convert<T>::decode(node, t))
return t;
return fallback;
@@ -124,8 +124,8 @@ struct as_if<T, void> {
const Node& node;
T operator()() const {
- if (!node.m_pNode)
- throw TypedBadConversion<T>(node.Mark());
+ if (!node.m_pNode) // no fallback
+ throw InvalidNode(node.m_invalidKey);
T t;
if (convert<T>::decode(node, t))
@@ -140,6 +140,8 @@ struct as_if<std::string, void> {
const Node& node;
std::string operator()() const {
+ if (node.Type() == NodeType::Undefined) // no fallback
+ throw InvalidNode(node.m_invalidKey);
if (node.Type() == NodeType::Null)
return "null";
if (node.Type() != NodeType::Scalar)
diff --git a/lib/yamlcpp/include/yaml-cpp/node/type.h b/lib/yamlcpp/include/yaml-cpp/node/type.h
index 9d55ca9662..b1237670cf 100644
--- a/lib/yamlcpp/include/yaml-cpp/node/type.h
+++ b/lib/yamlcpp/include/yaml-cpp/node/type.h
@@ -8,9 +8,10 @@
#endif
namespace YAML {
-struct NodeType {
- enum value { Undefined, Null, Scalar, Sequence, Map };
-};
+namespace NodeType {
+enum value { Undefined, Null, Scalar, Sequence, Map };
+}
+
}
#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
diff --git a/lib/yamlcpp/include/yaml-cpp/null.h b/lib/yamlcpp/include/yaml-cpp/null.h
index b9521d488a..472e961eae 100644
--- a/lib/yamlcpp/include/yaml-cpp/null.h
+++ b/lib/yamlcpp/include/yaml-cpp/null.h
@@ -8,7 +8,7 @@
#endif
#include "yaml-cpp/dll.h"
-#include <string>
+#include <cstddef>
namespace YAML {
class Node;
@@ -18,7 +18,7 @@ inline bool operator==(const _Null&, const _Null&) { return true; }
inline bool operator!=(const _Null&, const _Null&) { return false; }
YAML_CPP_API bool IsNull(const Node& node); // old API only
-YAML_CPP_API bool IsNullString(const std::string& str);
+YAML_CPP_API bool IsNullString(const char* str, std::size_t size);
extern YAML_CPP_API _Null Null;
}
diff --git a/lib/yamlcpp/include/yaml-cpp/traits.h b/lib/yamlcpp/include/yaml-cpp/traits.h
index ffe9999f19..8df9393054 100644
--- a/lib/yamlcpp/include/yaml-cpp/traits.h
+++ b/lib/yamlcpp/include/yaml-cpp/traits.h
@@ -121,6 +121,7 @@ template<typename Key, bool Streamable>
struct streamable_to_string {
static std::string impl(const Key& key) {
std::stringstream ss;
+ ss.imbue(std::locale::classic());
ss << key;
return ss.str();
}
diff --git a/lib/yamlcpp/include/yaml-cpp/yaml.h b/lib/yamlcpp/include/yaml-cpp/yaml.h
index 7f515efb96..7da7cf333b 100644
--- a/lib/yamlcpp/include/yaml-cpp/yaml.h
+++ b/lib/yamlcpp/include/yaml-cpp/yaml.h
@@ -7,6 +7,8 @@
#pragma once
#endif
+// IWYU pragma: begin_exports
+
#include "yaml-cpp/parser.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/emitterstyle.h"
@@ -21,4 +23,6 @@
#include "yaml-cpp/node/parse.h"
#include "yaml-cpp/node/emit.h"
+// IWYU pragma: end_exports
+
#endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
diff --git a/lib/yamlcpp/src/contrib/dragonbox.h b/lib/yamlcpp/src/contrib/dragonbox.h
new file mode 100644
index 0000000000..de5a79f119
--- /dev/null
+++ b/lib/yamlcpp/src/contrib/dragonbox.h
@@ -0,0 +1,4196 @@
+// SPDX-FileCopyrightText: 2020-2024 Junekey Jeon
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+// SPDX-License-Identifier: BSL-1.0
+// SPDX-License-Identifier: MIT
+
+// This file is an adjusted copy of https://github.com/jk-jeon/dragonbox
+// Junekey Jeon agreed to license this file under MIT license explicitly for
+// usage in yaml-cpp.
+//
+// Changes to the original dragonbox library:
+// - Added additional license information and information at top
+// - Wrapped the 'jkj' namespace in an additional 'YAML' namespace
+
+#ifndef JKJ_HEADER_DRAGONBOX
+#define JKJ_HEADER_DRAGONBOX
+
+// Attribute for storing static data into a dedicated place, e.g. flash memory. Every ODR-used
+// static data declaration will be decorated with this macro. The users may define this macro,
+// before including the library headers, into whatever they want.
+#ifndef JKJ_STATIC_DATA_SECTION
+ #define JKJ_STATIC_DATA_SECTION
+#else
+ #define JKJ_STATIC_DATA_SECTION_DEFINED 1
+#endif
+
+// To use the library with toolchains without standard C++ headers, the users may define this macro
+// into their custom namespace which contains the defintions of all the standard C++ library
+// features used in this header. (The list can be found below.)
+#ifndef JKJ_STD_REPLACEMENT_NAMESPACE
+ #define JKJ_STD_REPLACEMENT_NAMESPACE std
+ #include <cassert>
+ #include <cstdint>
+ #include <cstring>
+ #include <limits>
+ #include <type_traits>
+
+ #ifdef __has_include
+ #if __has_include(<version>)
+ #include <version>
+ #endif
+ #endif
+#else
+ #define JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED 1
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////
+// Language feature detections.
+////////////////////////////////////////////////////////////////////////////////////////
+
+// C++14 constexpr
+#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304L
+ #define JKJ_HAS_CONSTEXPR14 1
+#elif __cplusplus >= 201402L
+ #define JKJ_HAS_CONSTEXPR14 1
+#elif defined(_MSC_VER) && _MSC_VER >= 1910 && _MSVC_LANG >= 201402L
+ #define JKJ_HAS_CONSTEXPR14 1
+#else
+ #define JKJ_HAS_CONSTEXPR14 0
+#endif
+
+#if JKJ_HAS_CONSTEXPR14
+ #define JKJ_CONSTEXPR14 constexpr
+#else
+ #define JKJ_CONSTEXPR14
+#endif
+
+// C++17 constexpr lambdas
+#if defined(__cpp_constexpr) && __cpp_constexpr >= 201603L
+ #define JKJ_HAS_CONSTEXPR17 1
+#elif __cplusplus >= 201703L
+ #define JKJ_HAS_CONSTEXPR17 1
+#elif defined(_MSC_VER) && _MSC_VER >= 1911 && _MSVC_LANG >= 201703L
+ #define JKJ_HAS_CONSTEXPR17 1
+#else
+ #define JKJ_HAS_CONSTEXPR17 0
+#endif
+
+// C++17 inline variables
+#if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L
+ #define JKJ_HAS_INLINE_VARIABLE 1
+#elif __cplusplus >= 201703L
+ #define JKJ_HAS_INLINE_VARIABLE 1
+#elif defined(_MSC_VER) && _MSC_VER >= 1912 && _MSVC_LANG >= 201703L
+ #define JKJ_HAS_INLINE_VARIABLE 1
+#else
+ #define JKJ_HAS_INLINE_VARIABLE 0
+#endif
+
+#if JKJ_HAS_INLINE_VARIABLE
+ #define JKJ_INLINE_VARIABLE inline constexpr
+#else
+ #define JKJ_INLINE_VARIABLE static constexpr
+#endif
+
+// C++17 if constexpr
+#if defined(__cpp_if_constexpr) && __cpp_if_constexpr >= 201606L
+ #define JKJ_HAS_IF_CONSTEXPR 1
+#elif __cplusplus >= 201703L
+ #define JKJ_HAS_IF_CONSTEXPR 1
+#elif defined(_MSC_VER) && _MSC_VER >= 1911 && _MSVC_LANG >= 201703L
+ #define JKJ_HAS_IF_CONSTEXPR 1
+#else
+ #define JKJ_HAS_IF_CONSTEXPR 0
+#endif
+
+#if JKJ_HAS_IF_CONSTEXPR
+ #define JKJ_IF_CONSTEXPR if constexpr
+#else
+ #define JKJ_IF_CONSTEXPR if
+#endif
+
+// C++20 std::bit_cast
+#if JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED
+ #if JKJ_STD_REPLACEMENT_HAS_BIT_CAST
+ #define JKJ_HAS_BIT_CAST 1
+ #else
+ #define JKJ_HAS_BIT_CAST 0
+ #endif
+#elif defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
+ #include <bit>
+ #define JKJ_HAS_BIT_CAST 1
+#else
+ #define JKJ_HAS_BIT_CAST 0
+#endif
+
+// C++23 if consteval or C++20 std::is_constant_evaluated
+#if defined(__cpp_if_consteval) && __cpp_is_consteval >= 202106L
+ #define JKJ_IF_CONSTEVAL if consteval
+ #define JKJ_IF_NOT_CONSTEVAL if !consteval
+ #define JKJ_CAN_BRANCH_ON_CONSTEVAL 1
+ #define JKJ_USE_IS_CONSTANT_EVALUATED 0
+#elif JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED
+ #if JKJ_STD_REPLACEMENT_HAS_IS_CONSTANT_EVALUATED
+ #define JKJ_IF_CONSTEVAL if (stdr::is_constant_evaluated())
+ #define JKJ_IF_NOT_CONSTEVAL if (!stdr::is_constant_evaluated())
+ #define JKJ_CAN_BRANCH_ON_CONSTEVAL 1
+ #define JKJ_USE_IS_CONSTANT_EVALUATED 1
+ #elif JKJ_HAS_IF_CONSTEXPR
+ #define JKJ_IF_CONSTEVAL if constexpr (false)
+ #define JKJ_IF_NOT_CONSTEVAL if constexpr (true)
+ #define JKJ_CAN_BRANCH_ON_CONSTEVAL 0
+ #define JKJ_USE_IS_CONSTANT_EVALUATED 0
+ #else
+ #define JKJ_IF_CONSTEVAL if (false)
+ #define JKJ_IF_NOT_CONSTEVAL if (true)
+ #define JKJ_CAN_BRANCH_ON_CONSTEVAL 0
+ #define JKJ_USE_IS_CONSTANT_EVALUATED 0
+ #endif
+#else
+ #if defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L
+ #define JKJ_IF_CONSTEVAL if (stdr::is_constant_evaluated())
+ #define JKJ_IF_NOT_CONSTEVAL if (!stdr::is_constant_evaluated())
+ #define JKJ_CAN_BRANCH_ON_CONSTEVAL 1
+ #define JKJ_USE_IS_CONSTANT_EVALUATED 1
+ #elif JKJ_HAS_IF_CONSTEXPR
+ #define JKJ_IF_CONSTEVAL if constexpr (false)
+ #define JKJ_IF_NOT_CONSTEVAL if constexpr (true)
+ #define JKJ_CAN_BRANCH_ON_CONSTEVAL 0
+ #define JKJ_USE_IS_CONSTANT_EVALUATED 0
+ #else
+ #define JKJ_IF_CONSTEVAL if (false)
+ #define JKJ_IF_NOT_CONSTEVAL if (true)
+ #define JKJ_CAN_BRANCH_ON_CONSTEVAL 0
+ #define JKJ_USE_IS_CONSTANT_EVALUATED 0
+ #endif
+#endif
+
+#if JKJ_CAN_BRANCH_ON_CONSTEVAL && JKJ_HAS_BIT_CAST
+ #define JKJ_CONSTEXPR20 constexpr
+#else
+ #define JKJ_CONSTEXPR20
+#endif
+
+// Suppress additional buffer overrun check.
+// I have no idea why MSVC thinks some functions here are vulnerable to the buffer overrun
+// attacks. No, they aren't.
+#if defined(__GNUC__) || defined(__clang__)
+ #define JKJ_SAFEBUFFERS
+ #define JKJ_FORCEINLINE inline __attribute__((always_inline))
+#elif defined(_MSC_VER)
+ #define JKJ_SAFEBUFFERS __declspec(safebuffers)
+ #define JKJ_FORCEINLINE __forceinline
+#else
+ #define JKJ_SAFEBUFFERS
+ #define JKJ_FORCEINLINE inline
+#endif
+
+#if defined(__has_builtin)
+ #define JKJ_HAS_BUILTIN(x) __has_builtin(x)
+#else
+ #define JKJ_HAS_BUILTIN(x) false
+#endif
+
+#if defined(_MSC_VER)
+ #include <intrin.h>
+#elif defined(__INTEL_COMPILER)
+ #include <immintrin.h>
+#endif
+
+namespace YAML {
+namespace jkj {
+ namespace dragonbox {
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // The Compatibility layer for toolchains without standard C++ headers.
+ ////////////////////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ namespace stdr {
+ // <bit>
+#if JKJ_HAS_BIT_CAST
+ using JKJ_STD_REPLACEMENT_NAMESPACE::bit_cast;
+#endif
+
+ // <cassert>
+ // We need assert() macro, but it is not namespaced anyway, so nothing to do here.
+
+ // <cstdint>
+ using JKJ_STD_REPLACEMENT_NAMESPACE::int_least8_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::int_least16_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::int_least32_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::int_fast8_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::int_fast16_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::int_fast32_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::uint_least8_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::uint_least16_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::uint_least32_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::uint_least64_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::uint_fast8_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::uint_fast16_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::uint_fast32_t;
+ // We need INT32_C, UINT32_C and UINT64_C macros too, but again there is nothing to do
+ // here.
+
+ // <cstring>
+ using JKJ_STD_REPLACEMENT_NAMESPACE::size_t;
+ using JKJ_STD_REPLACEMENT_NAMESPACE::memcpy;
+
+ // <limits>
+ template <class T>
+ using numeric_limits = JKJ_STD_REPLACEMENT_NAMESPACE::numeric_limits<T>;
+
+ // <type_traits>
+ template <bool cond, class T = void>
+ using enable_if = JKJ_STD_REPLACEMENT_NAMESPACE::enable_if<cond, T>;
+ template <class T>
+ using add_rvalue_reference = JKJ_STD_REPLACEMENT_NAMESPACE::add_rvalue_reference<T>;
+ template <bool cond, class T_true, class T_false>
+ using conditional = JKJ_STD_REPLACEMENT_NAMESPACE::conditional<cond, T_true, T_false>;
+#if JKJ_USE_IS_CONSTANT_EVALUATED
+ using JKJ_STD_REPLACEMENT_NAMESPACE::is_constant_evaluated;
+#endif
+ template <class T1, class T2>
+ using is_same = JKJ_STD_REPLACEMENT_NAMESPACE::is_same<T1, T2>;
+#if !JKJ_HAS_BIT_CAST
+ template <class T>
+ using is_trivially_copyable = JKJ_STD_REPLACEMENT_NAMESPACE::is_trivially_copyable<T>;
+#endif
+ template <class T>
+ using is_integral = JKJ_STD_REPLACEMENT_NAMESPACE::is_integral<T>;
+ template <class T>
+ using is_signed = JKJ_STD_REPLACEMENT_NAMESPACE::is_signed<T>;
+ template <class T>
+ using is_unsigned = JKJ_STD_REPLACEMENT_NAMESPACE::is_unsigned<T>;
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Some general utilities for C++11-compatibility.
+ ////////////////////////////////////////////////////////////////////////////////////////
+ namespace detail {
+#if !JKJ_HAS_CONSTEXPR17
+ template <stdr::size_t... indices>
+ struct index_sequence {};
+
+ template <stdr::size_t current, stdr::size_t total, class Dummy, stdr::size_t... indices>
+ struct make_index_sequence_impl {
+ using type = typename make_index_sequence_impl<current + 1, total, Dummy, indices...,
+ current>::type;
+ };
+
+ template <stdr::size_t total, class Dummy, stdr::size_t... indices>
+ struct make_index_sequence_impl<total, total, Dummy, indices...> {
+ using type = index_sequence<indices...>;
+ };
+
+ template <stdr::size_t N>
+ using make_index_sequence = typename make_index_sequence_impl<0, N, void>::type;
+#endif
+
+ // Available since C++11, but including <utility> just for this is an overkill.
+ template <class T>
+ typename stdr::add_rvalue_reference<T>::type declval() noexcept;
+
+ // Similarly, including <array> is an overkill.
+ template <class T, stdr::size_t N>
+ struct array {
+ T data_[N];
+ constexpr T operator[](stdr::size_t idx) const noexcept { return data_[idx]; }
+ JKJ_CONSTEXPR14 T& operator[](stdr::size_t idx) noexcept { return data_[idx]; }
+ };
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Some basic features for encoding/decoding IEEE-754 formats.
+ ////////////////////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <class T>
+ struct physical_bits {
+ static constexpr stdr::size_t value =
+ sizeof(T) * stdr::numeric_limits<unsigned char>::digits;
+ };
+ template <class T>
+ struct value_bits {
+ static constexpr stdr::size_t value = stdr::numeric_limits<
+ typename stdr::enable_if<stdr::is_integral<T>::value, T>::type>::digits;
+ };
+
+ template <typename To, typename From>
+ JKJ_CONSTEXPR20 To bit_cast(const From& from) {
+#if JKJ_HAS_BIT_CAST
+ return stdr::bit_cast<To>(from);
+#else
+ static_assert(sizeof(From) == sizeof(To), "");
+ static_assert(stdr::is_trivially_copyable<To>::value, "");
+ static_assert(stdr::is_trivially_copyable<From>::value, "");
+ To to;
+ stdr::memcpy(&to, &from, sizeof(To));
+ return to;
+#endif
+ }
+ }
+
+ // These classes expose encoding specs of IEEE-754-like floating-point formats.
+ // Currently available formats are IEEE-754 binary32 & IEEE-754 binary64.
+
+ struct ieee754_binary32 {
+ static constexpr int total_bits = 32;
+ static constexpr int significand_bits = 23;
+ static constexpr int exponent_bits = 8;
+ static constexpr int min_exponent = -126;
+ static constexpr int max_exponent = 127;
+ static constexpr int exponent_bias = -127;
+ static constexpr int decimal_significand_digits = 9;
+ static constexpr int decimal_exponent_digits = 2;
+ };
+ struct ieee754_binary64 {
+ static constexpr int total_bits = 64;
+ static constexpr int significand_bits = 52;
+ static constexpr int exponent_bits = 11;
+ static constexpr int min_exponent = -1022;
+ static constexpr int max_exponent = 1023;
+ static constexpr int exponent_bias = -1023;
+ static constexpr int decimal_significand_digits = 17;
+ static constexpr int decimal_exponent_digits = 3;
+ };
+
+ // A floating-point format traits class defines ways to interpret a bit pattern of given size as
+ // an encoding of floating-point number. This is an implementation of such a traits class,
+ // supporting ways to interpret IEEE-754 binary floating-point numbers.
+ template <class Format, class CarrierUInt, class ExponentInt = int>
+ struct ieee754_binary_traits {
+ // CarrierUInt needs to have enough size to hold the entire contents of floating-point
+ // numbers. The actual bits are assumed to be aligned to the LSB, and every other bits are
+ // assumed to be zeroed.
+ static_assert(detail::value_bits<CarrierUInt>::value >= Format::total_bits,
+ "jkj::dragonbox: insufficient number of bits");
+ static_assert(detail::stdr::is_unsigned<CarrierUInt>::value, "");
+
+ // ExponentUInt needs to be large enough to hold (unsigned) exponent bits as well as the
+ // (signed) actual exponent.
+ // TODO: static overflow guard against intermediate computations.
+ static_assert(detail::value_bits<ExponentInt>::value >= Format::exponent_bits + 1,
+ "jkj::dragonbox: insufficient number of bits");
+ static_assert(detail::stdr::is_signed<ExponentInt>::value, "");
+
+ using format = Format;
+ using carrier_uint = CarrierUInt;
+ static constexpr int carrier_bits = int(detail::value_bits<carrier_uint>::value);
+ using exponent_int = ExponentInt;
+
+ // Extract exponent bits from a bit pattern.
+ // The result must be aligned to the LSB so that there is no additional zero paddings
+ // on the right. This function does not do bias adjustment.
+ static constexpr exponent_int extract_exponent_bits(carrier_uint u) noexcept {
+ return exponent_int((u >> format::significand_bits) &
+ ((exponent_int(1) << format::exponent_bits) - 1));
+ }
+
+ // Extract significand bits from a bit pattern.
+ // The result must be aligned to the LSB so that there is no additional zero paddings
+ // on the right. The result does not contain the implicit bit.
+ static constexpr carrier_uint extract_significand_bits(carrier_uint u) noexcept {
+ return carrier_uint(u & ((carrier_uint(1) << format::significand_bits) - 1u));
+ }
+
+ // Remove the exponent bits and extract significand bits together with the sign bit.
+ static constexpr carrier_uint remove_exponent_bits(carrier_uint u) noexcept {
+ return carrier_uint(u & ~(((carrier_uint(1) << format::exponent_bits) - 1u)
+ << format::significand_bits));
+ }
+
+ // Shift the obtained signed significand bits to the left by 1 to remove the sign bit.
+ static constexpr carrier_uint remove_sign_bit_and_shift(carrier_uint u) noexcept {
+ return carrier_uint((carrier_uint(u) << 1) &
+ ((((carrier_uint(1) << (Format::total_bits - 1)) - 1u) << 1) | 1u));
+ }
+
+ // Obtain the actual value of the binary exponent from the extracted exponent bits.
+ static constexpr exponent_int binary_exponent(exponent_int exponent_bits) noexcept {
+ return exponent_int(exponent_bits == 0 ? format::min_exponent
+ : exponent_bits + format::exponent_bias);
+ }
+
+ // Obtain the actual value of the binary significand from the extracted significand bits
+ // and exponent bits.
+ static constexpr carrier_uint binary_significand(carrier_uint significand_bits,
+ exponent_int exponent_bits) noexcept {
+ return carrier_uint(
+ exponent_bits == 0
+ ? significand_bits
+ : (significand_bits | (carrier_uint(1) << format::significand_bits)));
+ }
+
+ /* Various boolean observer functions */
+
+ static constexpr bool is_nonzero(carrier_uint u) noexcept {
+ return (u & ((carrier_uint(1) << (format::significand_bits + format::exponent_bits)) -
+ 1u)) != 0;
+ }
+ static constexpr bool is_positive(carrier_uint u) noexcept {
+ return u < (carrier_uint(1) << (format::significand_bits + format::exponent_bits));
+ }
+ static constexpr bool is_negative(carrier_uint u) noexcept { return !is_positive(u); }
+ static constexpr bool is_finite(exponent_int exponent_bits) noexcept {
+ return exponent_bits != ((exponent_int(1) << format::exponent_bits) - 1);
+ }
+ static constexpr bool has_all_zero_significand_bits(carrier_uint u) noexcept {
+ return ((u << 1) &
+ ((((carrier_uint(1) << (Format::total_bits - 1)) - 1u) << 1) | 1u)) == 0;
+ }
+ static constexpr bool has_even_significand_bits(carrier_uint u) noexcept {
+ return u % 2 == 0;
+ }
+ };
+
+ // Convert between bit patterns stored in carrier_uint and instances of an actual
+ // floating-point type. Depending on format and carrier_uint, this operation might not
+ // be possible for some specific bit patterns. However, the contract is that u always
+ // denotes a valid bit pattern, so the functions here are assumed to be noexcept.
+ // Users might specialize this class to change the behavior for certain types.
+ // The default provided by the library is to treat the given floating-point type Float as either
+ // IEEE-754 binary32 or IEEE-754 binary64, depending on the bitwise size of Float.
+ template <class Float>
+ struct default_float_bit_carrier_conversion_traits {
+ // Guards against types that have different internal representations than IEEE-754
+ // binary32/64. I don't know if there is a truly reliable way of detecting IEEE-754 binary
+ // formats. I just did my best here. Note that in some cases
+ // numeric_limits<Float>::is_iec559 may report false even if the internal representation is
+ // IEEE-754 compatible. In such a case, the user can specialize this traits template and
+ // remove this static sanity check in order to make Dragonbox work for Float.
+ static_assert(detail::stdr::numeric_limits<Float>::is_iec559 &&
+ detail::stdr::numeric_limits<Float>::radix == 2 &&
+ (detail::physical_bits<Float>::value == 32 ||
+ detail::physical_bits<Float>::value == 64),
+ "jkj::dragonbox: Float may not be of IEEE-754 binary32/binary64");
+
+ // Specifies the unsigned integer type to hold bitwise value of Float.
+ using carrier_uint =
+ typename detail::stdr::conditional<detail::physical_bits<Float>::value == 32,
+ detail::stdr::uint_least32_t,
+ detail::stdr::uint_least64_t>::type;
+
+ // Specifies the floating-point format.
+ using format = typename detail::stdr::conditional<detail::physical_bits<Float>::value == 32,
+ ieee754_binary32, ieee754_binary64>::type;
+
+ // Converts the floating-point type into the bit-carrier unsigned integer type.
+ static JKJ_CONSTEXPR20 carrier_uint float_to_carrier(Float x) noexcept {
+ return detail::bit_cast<carrier_uint>(x);
+ }
+
+ // Converts the bit-carrier unsigned integer type into the floating-point type.
+ static JKJ_CONSTEXPR20 Float carrier_to_float(carrier_uint x) noexcept {
+ return detail::bit_cast<Float>(x);
+ }
+ };
+
+ // Convenient wrappers for floating-point traits classes.
+ // In order to reduce the argument passing overhead, these classes should be as simple as
+ // possible (e.g., no inheritance, no private non-static data member, etc.; this is an
+ // unfortunate fact about common ABI convention).
+
+ template <class FormatTraits>
+ struct signed_significand_bits {
+ using format_traits = FormatTraits;
+ using carrier_uint = typename format_traits::carrier_uint;
+
+ carrier_uint u;
+
+ signed_significand_bits() = default;
+ constexpr explicit signed_significand_bits(carrier_uint bit_pattern) noexcept
+ : u{bit_pattern} {}
+
+ // Shift the obtained signed significand bits to the left by 1 to remove the sign bit.
+ constexpr carrier_uint remove_sign_bit_and_shift() const noexcept {
+ return format_traits::remove_sign_bit_and_shift(u);
+ }
+
+ constexpr bool is_positive() const noexcept { return format_traits::is_positive(u); }
+ constexpr bool is_negative() const noexcept { return format_traits::is_negative(u); }
+ constexpr bool has_all_zero_significand_bits() const noexcept {
+ return format_traits::has_all_zero_significand_bits(u);
+ }
+ constexpr bool has_even_significand_bits() const noexcept {
+ return format_traits::has_even_significand_bits(u);
+ }
+ };
+
+ template <class FormatTraits>
+ struct float_bits {
+ using format_traits = FormatTraits;
+ using carrier_uint = typename format_traits::carrier_uint;
+ using exponent_int = typename format_traits::exponent_int;
+
+ carrier_uint u;
+
+ float_bits() = default;
+ constexpr explicit float_bits(carrier_uint bit_pattern) noexcept : u{bit_pattern} {}
+
+ // Extract exponent bits from a bit pattern.
+ // The result must be aligned to the LSB so that there is no additional zero paddings
+ // on the right. This function does not do bias adjustment.
+ constexpr exponent_int extract_exponent_bits() const noexcept {
+ return format_traits::extract_exponent_bits(u);
+ }
+
+ // Extract significand bits from a bit pattern.
+ // The result must be aligned to the LSB so that there is no additional zero paddings
+ // on the right. The result does not contain the implicit bit.
+ constexpr carrier_uint extract_significand_bits() const noexcept {
+ return format_traits::extract_significand_bits(u);
+ }
+
+ // Remove the exponent bits and extract significand bits together with the sign bit.
+ constexpr signed_significand_bits<format_traits> remove_exponent_bits() const noexcept {
+ return signed_significand_bits<format_traits>(format_traits::remove_exponent_bits(u));
+ }
+
+ // Obtain the actual value of the binary exponent from the extracted exponent bits.
+ static constexpr exponent_int binary_exponent(exponent_int exponent_bits) noexcept {
+ return format_traits::binary_exponent(exponent_bits);
+ }
+ constexpr exponent_int binary_exponent() const noexcept {
+ return binary_exponent(extract_exponent_bits());
+ }
+
+ // Obtain the actual value of the binary exponent from the extracted significand bits
+ // and exponent bits.
+ static constexpr carrier_uint binary_significand(carrier_uint significand_bits,
+ exponent_int exponent_bits) noexcept {
+ return format_traits::binary_significand(significand_bits, exponent_bits);
+ }
+ constexpr carrier_uint binary_significand() const noexcept {
+ return binary_significand(extract_significand_bits(), extract_exponent_bits());
+ }
+
+ constexpr bool is_nonzero() const noexcept { return format_traits::is_nonzero(u); }
+ constexpr bool is_positive() const noexcept { return format_traits::is_positive(u); }
+ constexpr bool is_negative() const noexcept { return format_traits::is_negative(u); }
+ constexpr bool is_finite(exponent_int exponent_bits) const noexcept {
+ return format_traits::is_finite(exponent_bits);
+ }
+ constexpr bool is_finite() const noexcept {
+ return format_traits::is_finite(extract_exponent_bits());
+ }
+ constexpr bool has_even_significand_bits() const noexcept {
+ return format_traits::has_even_significand_bits(u);
+ }
+ };
+
+ template <class Float,
+ class ConversionTraits = default_float_bit_carrier_conversion_traits<Float>,
+ class FormatTraits = ieee754_binary_traits<typename ConversionTraits::format,
+ typename ConversionTraits::carrier_uint>>
+ JKJ_CONSTEXPR20 float_bits<FormatTraits> make_float_bits(Float x) noexcept {
+ return float_bits<FormatTraits>(ConversionTraits::float_to_carrier(x));
+ }
+
+ namespace detail {
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Bit operation intrinsics.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ namespace bits {
+ // Most compilers should be able to optimize this into the ROR instruction.
+ // n is assumed to be at most of bit_width bits.
+ template <stdr::size_t bit_width, class UInt>
+ JKJ_CONSTEXPR14 UInt rotr(UInt n, unsigned int r) noexcept {
+ static_assert(bit_width > 0, "jkj::dragonbox: rotation bit-width must be positive");
+ static_assert(bit_width <= value_bits<UInt>::value,
+ "jkj::dragonbox: rotation bit-width is too large");
+ r &= (bit_width - 1);
+ return (n >> r) | (n << ((bit_width - r) & (bit_width - 1)));
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Utilities for wide unsigned integer arithmetic.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ namespace wuint {
+ // Compilers might support built-in 128-bit integer types. However, it seems that
+ // emulating them with a pair of 64-bit integers actually produces a better code,
+ // so we avoid using those built-ins. That said, they are still useful for
+ // implementing 64-bit x 64-bit -> 128-bit multiplication.
+
+ // clang-format off
+#if defined(__SIZEOF_INT128__)
+ // To silence "error: ISO C++ does not support '__int128' for 'type name'
+ // [-Wpedantic]"
+#if defined(__GNUC__)
+ __extension__
+#endif
+ using builtin_uint128_t = unsigned __int128;
+#endif
+ // clang-format on
+
+ struct uint128 {
+ uint128() = default;
+
+ stdr::uint_least64_t high_;
+ stdr::uint_least64_t low_;
+
+ constexpr uint128(stdr::uint_least64_t high, stdr::uint_least64_t low) noexcept
+ : high_{high}, low_{low} {}
+
+ constexpr stdr::uint_least64_t high() const noexcept { return high_; }
+ constexpr stdr::uint_least64_t low() const noexcept { return low_; }
+
+ JKJ_CONSTEXPR20 uint128& operator+=(stdr::uint_least64_t n) & noexcept {
+ auto const generic_impl = [&] {
+ auto const sum = (low_ + n) & UINT64_C(0xffffffffffffffff);
+ high_ += (sum < low_ ? 1 : 0);
+ low_ = sum;
+ };
+ // To suppress warning.
+ static_cast<void>(generic_impl);
+
+ JKJ_IF_CONSTEXPR(value_bits<stdr::uint_least64_t>::value > 64) {
+ generic_impl();
+ return *this;
+ }
+
+ JKJ_IF_CONSTEVAL {
+ generic_impl();
+ return *this;
+ }
+
+ // See https://github.com/fmtlib/fmt/pull/2985.
+#if JKJ_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
+ JKJ_IF_CONSTEXPR(
+ stdr::is_same<stdr::uint_least64_t, unsigned long long>::value) {
+ unsigned long long carry{};
+ low_ = stdr::uint_least64_t(__builtin_addcll(low_, n, 0, &carry));
+ high_ = stdr::uint_least64_t(__builtin_addcll(high_, 0, carry, &carry));
+ return *this;
+ }
+#endif
+#if JKJ_HAS_BUILTIN(__builtin_addcl) && !defined(__ibmxl__)
+ JKJ_IF_CONSTEXPR(stdr::is_same<stdr::uint_least64_t, unsigned long>::value) {
+ unsigned long carry{};
+ low_ = stdr::uint_least64_t(
+ __builtin_addcl(static_cast<unsigned long>(low_),
+ static_cast<unsigned long>(n), 0, &carry));
+ high_ = stdr::uint_least64_t(
+ __builtin_addcl(static_cast<unsigned long>(high_), 0, carry, &carry));
+ return *this;
+ }
+#endif
+#if JKJ_HAS_BUILTIN(__builtin_addc) && !defined(__ibmxl__)
+ JKJ_IF_CONSTEXPR(stdr::is_same<stdr::uint_least64_t, unsigned int>::value) {
+ unsigned int carry{};
+ low_ = stdr::uint_least64_t(__builtin_addc(static_cast<unsigned int>(low_),
+ static_cast<unsigned int>(n), 0,
+ &carry));
+ high_ = stdr::uint_least64_t(
+ __builtin_addc(static_cast<unsigned int>(high_), 0, carry, &carry));
+ return *this;
+ }
+#endif
+
+#if JKJ_HAS_BUILTIN(__builtin_ia32_addcarry_u64)
+ // __builtin_ia32_addcarry_u64 is not documented, but it seems it takes unsigned
+ // long long arguments.
+ unsigned long long result{};
+ auto const carry = __builtin_ia32_addcarry_u64(0, low_, n, &result);
+ low_ = stdr::uint_least64_t(result);
+ __builtin_ia32_addcarry_u64(carry, high_, 0, &result);
+ high_ = stdr::uint_least64_t(result);
+#elif defined(_MSC_VER) && defined(_M_X64)
+ // On MSVC, uint_least64_t and __int64 must be unsigned long long; see
+ // https://learn.microsoft.com/en-us/cpp/c-runtime-library/standard-types
+ // and https://learn.microsoft.com/en-us/cpp/cpp/int8-int16-int32-int64.
+ static_assert(stdr::is_same<unsigned long long, stdr::uint_least64_t>::value,
+ "");
+ auto const carry = _addcarry_u64(0, low_, n, &low_);
+ _addcarry_u64(carry, high_, 0, &high_);
+#elif defined(__INTEL_COMPILER) && (defined(_M_X64) || defined(__x86_64))
+ // Cannot find any documentation on how things are defined, but hopefully this
+ // is always true...
+ static_assert(stdr::is_same<unsigned __int64, stdr::uint_least64_t>::value, "");
+ auto const carry = _addcarry_u64(0, low_, n, &low_);
+ _addcarry_u64(carry, high_, 0, &high_);
+#else
+ generic_impl();
+#endif
+ return *this;
+ }
+ };
+
+ inline JKJ_CONSTEXPR20 stdr::uint_least64_t umul64(stdr::uint_least32_t x,
+ stdr::uint_least32_t y) noexcept {
+#if defined(_MSC_VER) && defined(_M_IX86)
+ JKJ_IF_NOT_CONSTEVAL { return __emulu(x, y); }
+#endif
+ return x * stdr::uint_least64_t(y);
+ }
+
+ // Get 128-bit result of multiplication of two 64-bit unsigned integers.
+ JKJ_SAFEBUFFERS inline JKJ_CONSTEXPR20 uint128
+ umul128(stdr::uint_least64_t x, stdr::uint_least64_t y) noexcept {
+ auto const generic_impl = [=]() -> uint128 {
+ auto const a = stdr::uint_least32_t(x >> 32);
+ auto const b = stdr::uint_least32_t(x);
+ auto const c = stdr::uint_least32_t(y >> 32);
+ auto const d = stdr::uint_least32_t(y);
+
+ auto const ac = umul64(a, c);
+ auto const bc = umul64(b, c);
+ auto const ad = umul64(a, d);
+ auto const bd = umul64(b, d);
+
+ auto const intermediate =
+ (bd >> 32) + stdr::uint_least32_t(ad) + stdr::uint_least32_t(bc);
+
+ return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
+ (intermediate << 32) + stdr::uint_least32_t(bd)};
+ };
+ // To silence warning.
+ static_cast<void>(generic_impl);
+
+#if defined(__SIZEOF_INT128__)
+ auto const result = builtin_uint128_t(x) * builtin_uint128_t(y);
+ return {stdr::uint_least64_t(result >> 64), stdr::uint_least64_t(result)};
+#elif defined(_MSC_VER) && defined(_M_X64)
+ JKJ_IF_CONSTEVAL {
+ // This redundant variable is to workaround MSVC's codegen bug caused by the
+ // interaction of NRVO and intrinsics.
+ auto const result = generic_impl();
+ return result;
+ }
+ uint128 result;
+ #if defined(__AVX2__)
+ result.low_ = _mulx_u64(x, y, &result.high_);
+ #else
+ result.low_ = _umul128(x, y, &result.high_);
+ #endif
+ return result;
+#else
+ return generic_impl();
+#endif
+ }
+
+ // Get high half of the 128-bit result of multiplication of two 64-bit unsigned
+ // integers.
+ JKJ_SAFEBUFFERS inline JKJ_CONSTEXPR20 stdr::uint_least64_t
+ umul128_upper64(stdr::uint_least64_t x, stdr::uint_least64_t y) noexcept {
+ auto const generic_impl = [=]() -> stdr::uint_least64_t {
+ auto const a = stdr::uint_least32_t(x >> 32);
+ auto const b = stdr::uint_least32_t(x);
+ auto const c = stdr::uint_least32_t(y >> 32);
+ auto const d = stdr::uint_least32_t(y);
+
+ auto const ac = umul64(a, c);
+ auto const bc = umul64(b, c);
+ auto const ad = umul64(a, d);
+ auto const bd = umul64(b, d);
+
+ auto const intermediate =
+ (bd >> 32) + stdr::uint_least32_t(ad) + stdr::uint_least32_t(bc);
+
+ return ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32);
+ };
+ // To silence warning.
+ static_cast<void>(generic_impl);
+
+#if defined(__SIZEOF_INT128__)
+ auto const result = builtin_uint128_t(x) * builtin_uint128_t(y);
+ return stdr::uint_least64_t(result >> 64);
+#elif defined(_MSC_VER) && defined(_M_X64)
+ JKJ_IF_CONSTEVAL {
+ // This redundant variable is to workaround MSVC's codegen bug caused by the
+ // interaction of NRVO and intrinsics.
+ auto const result = generic_impl();
+ return result;
+ }
+ stdr::uint_least64_t result;
+ #if defined(__AVX2__)
+ _mulx_u64(x, y, &result);
+ #else
+ result = __umulh(x, y);
+ #endif
+ return result;
+#else
+ return generic_impl();
+#endif
+ }
+
+ // Get upper 128-bits of multiplication of a 64-bit unsigned integer and a 128-bit
+ // unsigned integer.
+ JKJ_SAFEBUFFERS inline JKJ_CONSTEXPR20 uint128 umul192_upper128(stdr::uint_least64_t x,
+ uint128 y) noexcept {
+ auto r = umul128(x, y.high());
+ r += umul128_upper64(x, y.low());
+ return r;
+ }
+
+ // Get upper 64-bits of multiplication of a 32-bit unsigned integer and a 64-bit
+ // unsigned integer.
+ inline JKJ_CONSTEXPR20 stdr::uint_least64_t
+ umul96_upper64(stdr::uint_least32_t x, stdr::uint_least64_t y) noexcept {
+#if defined(__SIZEOF_INT128__) || (defined(_MSC_VER) && defined(_M_X64))
+ return umul128_upper64(stdr::uint_least64_t(x) << 32, y);
+#else
+ auto const yh = stdr::uint_least32_t(y >> 32);
+ auto const yl = stdr::uint_least32_t(y);
+
+ auto const xyh = umul64(x, yh);
+ auto const xyl = umul64(x, yl);
+
+ return xyh + (xyl >> 32);
+#endif
+ }
+
+ // Get lower 128-bits of multiplication of a 64-bit unsigned integer and a 128-bit
+ // unsigned integer.
+ JKJ_SAFEBUFFERS inline JKJ_CONSTEXPR20 uint128 umul192_lower128(stdr::uint_least64_t x,
+ uint128 y) noexcept {
+ auto const high = x * y.high();
+ auto const high_low = umul128(x, y.low());
+ return {(high + high_low.high()) & UINT64_C(0xffffffffffffffff), high_low.low()};
+ }
+
+ // Get lower 64-bits of multiplication of a 32-bit unsigned integer and a 64-bit
+ // unsigned integer.
+ constexpr stdr::uint_least64_t umul96_lower64(stdr::uint_least32_t x,
+ stdr::uint_least64_t y) noexcept {
+ return (x * y) & UINT64_C(0xffffffffffffffff);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Some simple utilities for constexpr computation.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ template <int k, class Int>
+ constexpr Int compute_power(Int a) noexcept {
+ static_assert(k >= 0, "");
+#if JKJ_HAS_CONSTEXPR14
+ Int p = 1;
+ for (int i = 0; i < k; ++i) {
+ p *= a;
+ }
+ return p;
+#else
+ return k == 0 ? 1
+ : k % 2 == 0 ? compute_power<k / 2, Int>(a * a)
+ : a * compute_power<k / 2, Int>(a * a);
+#endif
+ }
+
+ template <int a, class UInt>
+ constexpr int count_factors(UInt n) noexcept {
+ static_assert(a > 1, "");
+#if JKJ_HAS_CONSTEXPR14
+ int c = 0;
+ while (n % a == 0) {
+ n /= a;
+ ++c;
+ }
+ return c;
+#else
+ return n % a == 0 ? count_factors<a, UInt>(n / a) + 1 : 0;
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Utilities for fast/constexpr log computation.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ namespace log {
+ static_assert((stdr::int_fast32_t(-1) >> 1) == stdr::int_fast32_t(-1) &&
+ (stdr::int_fast16_t(-1) >> 1) == stdr::int_fast16_t(-1),
+ "jkj::dragonbox: right-shift for signed integers must be arithmetic");
+
+ // For constexpr computation.
+ // Returns -1 when n = 0.
+ template <class UInt>
+ constexpr int floor_log2(UInt n) noexcept {
+#if JKJ_HAS_CONSTEXPR14
+ int count = -1;
+ while (n != 0) {
+ ++count;
+ n >>= 1;
+ }
+ return count;
+#else
+ return n == 0 ? -1 : floor_log2<UInt>(n / 2) + 1;
+#endif
+ }
+
+ template <template <stdr::size_t> class Info, stdr::int_least32_t min_exponent,
+ stdr::int_least32_t max_exponent, stdr::size_t current_tier,
+ stdr::int_least32_t supported_min_exponent = Info<current_tier>::min_exponent,
+ stdr::int_least32_t supported_max_exponent = Info<current_tier>::max_exponent>
+ constexpr bool is_in_range(int) noexcept {
+ return min_exponent >= supported_min_exponent &&
+ max_exponent <= supported_max_exponent;
+ }
+ template <template <stdr::size_t> class Info, stdr::int_least32_t min_exponent,
+ stdr::int_least32_t max_exponent, stdr::size_t current_tier>
+ constexpr bool is_in_range(...) noexcept {
+ // Supposed to be always false, but formally dependent on the template parameters.
+ static_assert(min_exponent > max_exponent,
+ "jkj::dragonbox: exponent range is too wide");
+ return false;
+ }
+
+ template <template <stdr::size_t> class Info, stdr::int_least32_t min_exponent,
+ stdr::int_least32_t max_exponent, stdr::size_t current_tier = 0,
+ bool = is_in_range<Info, min_exponent, max_exponent, current_tier>(0)>
+ struct compute_impl;
+
+ template <template <stdr::size_t> class Info, stdr::int_least32_t min_exponent,
+ stdr::int_least32_t max_exponent, stdr::size_t current_tier>
+ struct compute_impl<Info, min_exponent, max_exponent, current_tier, true> {
+ using info = Info<current_tier>;
+ using default_return_type = typename info::default_return_type;
+ template <class ReturnType, class Int>
+ static constexpr ReturnType compute(Int e) noexcept {
+#if JKJ_HAS_CONSTEXPR14
+ assert(min_exponent <= e && e <= max_exponent);
+#endif
+ // The sign is irrelevant for the mathematical validity of the formula, but
+ // assuming positivity makes the overflow analysis simpler.
+ static_assert(info::multiply >= 0 && info::subtract >= 0, "");
+ return static_cast<ReturnType>((e * info::multiply - info::subtract) >>
+ info::shift);
+ }
+ };
+
+ template <template <stdr::size_t> class Info, stdr::int_least32_t min_exponent,
+ stdr::int_least32_t max_exponent, stdr::size_t current_tier>
+ struct compute_impl<Info, min_exponent, max_exponent, current_tier, false> {
+ using next_tier = compute_impl<Info, min_exponent, max_exponent, current_tier + 1>;
+ using default_return_type = typename next_tier::default_return_type;
+ template <class ReturnType, class Int>
+ static constexpr ReturnType compute(Int e) noexcept {
+ return next_tier::template compute<ReturnType>(e);
+ }
+ };
+
+ template <stdr::size_t tier>
+ struct floor_log10_pow2_info;
+ template <>
+ struct floor_log10_pow2_info<0> {
+ using default_return_type = stdr::int_fast8_t;
+ static constexpr stdr::int_fast16_t multiply = 77;
+ static constexpr stdr::int_fast16_t subtract = 0;
+ static constexpr stdr::size_t shift = 8;
+ static constexpr stdr::int_least32_t min_exponent = -102;
+ static constexpr stdr::int_least32_t max_exponent = 102;
+ };
+ template <>
+ struct floor_log10_pow2_info<1> {
+ using default_return_type = stdr::int_fast8_t;
+ // 24-bits are enough in fact.
+ static constexpr stdr::int_fast32_t multiply = 1233;
+ static constexpr stdr::int_fast32_t subtract = 0;
+ static constexpr stdr::size_t shift = 12;
+ // Formula itself holds on [-680,680]; [-425,425] is to ensure that the output is
+ // within [-127,127].
+ static constexpr stdr::int_least32_t min_exponent = -425;
+ static constexpr stdr::int_least32_t max_exponent = 425;
+ };
+ template <>
+ struct floor_log10_pow2_info<2> {
+ using default_return_type = stdr::int_fast16_t;
+ static constexpr stdr::int_fast32_t multiply = INT32_C(315653);
+ static constexpr stdr::int_fast32_t subtract = 0;
+ static constexpr stdr::size_t shift = 20;
+ static constexpr stdr::int_least32_t min_exponent = -2620;
+ static constexpr stdr::int_least32_t max_exponent = 2620;
+ };
+ template <stdr::int_least32_t min_exponent = -2620,
+ stdr::int_least32_t max_exponent = 2620,
+ class ReturnType = typename compute_impl<floor_log10_pow2_info, min_exponent,
+ max_exponent>::default_return_type,
+ class Int>
+ constexpr ReturnType floor_log10_pow2(Int e) noexcept {
+ return compute_impl<floor_log10_pow2_info, min_exponent,
+ max_exponent>::template compute<ReturnType>(e);
+ }
+
+ template <stdr::size_t tier>
+ struct floor_log2_pow10_info;
+ template <>
+ struct floor_log2_pow10_info<0> {
+ using default_return_type = stdr::int_fast8_t;
+ static constexpr stdr::int_fast16_t multiply = 53;
+ static constexpr stdr::int_fast16_t subtract = 0;
+ static constexpr stdr::size_t shift = 4;
+ static constexpr stdr::int_least32_t min_exponent = -15;
+ static constexpr stdr::int_least32_t max_exponent = 18;
+ };
+ template <>
+ struct floor_log2_pow10_info<1> {
+ using default_return_type = stdr::int_fast16_t;
+ // 24-bits are enough in fact.
+ static constexpr stdr::int_fast32_t multiply = 1701;
+ static constexpr stdr::int_fast32_t subtract = 0;
+ static constexpr stdr::size_t shift = 9;
+ static constexpr stdr::int_least32_t min_exponent = -58;
+ static constexpr stdr::int_least32_t max_exponent = 58;
+ };
+ template <>
+ struct floor_log2_pow10_info<2> {
+ using default_return_type = stdr::int_fast16_t;
+ static constexpr stdr::int_fast32_t multiply = INT32_C(1741647);
+ static constexpr stdr::int_fast32_t subtract = 0;
+ static constexpr stdr::size_t shift = 19;
+ // Formula itself holds on [-4003,4003]; [-1233,1233] is to ensure no overflow.
+ static constexpr stdr::int_least32_t min_exponent = -1233;
+ static constexpr stdr::int_least32_t max_exponent = 1233;
+ };
+ template <stdr::int_least32_t min_exponent = -1233,
+ stdr::int_least32_t max_exponent = 1233,
+ class ReturnType = typename compute_impl<floor_log2_pow10_info, min_exponent,
+ max_exponent>::default_return_type,
+ class Int>
+ constexpr ReturnType floor_log2_pow10(Int e) noexcept {
+ return compute_impl<floor_log2_pow10_info, min_exponent,
+ max_exponent>::template compute<ReturnType>(e);
+ }
+
+ template <stdr::size_t tier>
+ struct floor_log10_pow2_minus_log10_4_over_3_info;
+ template <>
+ struct floor_log10_pow2_minus_log10_4_over_3_info<0> {
+ using default_return_type = stdr::int_fast8_t;
+ static constexpr stdr::int_fast16_t multiply = 77;
+ static constexpr stdr::int_fast16_t subtract = 31;
+ static constexpr stdr::size_t shift = 8;
+ static constexpr stdr::int_least32_t min_exponent = -75;
+ static constexpr stdr::int_least32_t max_exponent = 129;
+ };
+ template <>
+ struct floor_log10_pow2_minus_log10_4_over_3_info<1> {
+ using default_return_type = stdr::int_fast8_t;
+ // 24-bits are enough in fact.
+ static constexpr stdr::int_fast32_t multiply = 19728;
+ static constexpr stdr::int_fast32_t subtract = 8241;
+ static constexpr stdr::size_t shift = 16;
+ // Formula itself holds on [-849,315]; [-424,315] is to ensure that the output is
+ // within [-127,127].
+ static constexpr stdr::int_least32_t min_exponent = -424;
+ static constexpr stdr::int_least32_t max_exponent = 315;
+ };
+ template <>
+ struct floor_log10_pow2_minus_log10_4_over_3_info<2> {
+ using default_return_type = stdr::int_fast16_t;
+ static constexpr stdr::int_fast32_t multiply = INT32_C(631305);
+ static constexpr stdr::int_fast32_t subtract = INT32_C(261663);
+ static constexpr stdr::size_t shift = 21;
+ static constexpr stdr::int_least32_t min_exponent = -2985;
+ static constexpr stdr::int_least32_t max_exponent = 2936;
+ };
+ template <stdr::int_least32_t min_exponent = -2985,
+ stdr::int_least32_t max_exponent = 2936,
+ class ReturnType =
+ typename compute_impl<floor_log10_pow2_minus_log10_4_over_3_info,
+ min_exponent, max_exponent>::default_return_type,
+ class Int>
+ constexpr ReturnType floor_log10_pow2_minus_log10_4_over_3(Int e) noexcept {
+ return compute_impl<floor_log10_pow2_minus_log10_4_over_3_info, min_exponent,
+ max_exponent>::template compute<ReturnType>(e);
+ }
+
+ template <stdr::size_t tier>
+ struct floor_log5_pow2_info;
+ template <>
+ struct floor_log5_pow2_info<0> {
+ using default_return_type = stdr::int_fast32_t;
+ static constexpr stdr::int_fast32_t multiply = INT32_C(225799);
+ static constexpr stdr::int_fast32_t subtract = 0;
+ static constexpr stdr::size_t shift = 19;
+ static constexpr stdr::int_least32_t min_exponent = -1831;
+ static constexpr stdr::int_least32_t max_exponent = 1831;
+ };
+ template <stdr::int_least32_t min_exponent = -1831,
+ stdr::int_least32_t max_exponent = 1831,
+ class ReturnType = typename compute_impl<floor_log5_pow2_info, min_exponent,
+ max_exponent>::default_return_type,
+ class Int>
+ constexpr ReturnType floor_log5_pow2(Int e) noexcept {
+ return compute_impl<floor_log5_pow2_info, min_exponent,
+ max_exponent>::template compute<ReturnType>(e);
+ }
+
+ template <stdr::size_t tier>
+ struct floor_log5_pow2_minus_log5_3_info;
+ template <>
+ struct floor_log5_pow2_minus_log5_3_info<0> {
+ using default_return_type = stdr::int_fast32_t;
+ static constexpr stdr::int_fast32_t multiply = INT32_C(451597);
+ static constexpr stdr::int_fast32_t subtract = INT32_C(715764);
+ static constexpr stdr::size_t shift = 20;
+ static constexpr stdr::int_least32_t min_exponent = -3543;
+ static constexpr stdr::int_least32_t max_exponent = 2427;
+ };
+ template <stdr::int_least32_t min_exponent = -3543,
+ stdr::int_least32_t max_exponent = 2427,
+ class ReturnType =
+ typename compute_impl<floor_log5_pow2_minus_log5_3_info, min_exponent,
+ max_exponent>::default_return_type,
+ class Int>
+ constexpr ReturnType floor_log5_pow2_minus_log5_3(Int e) noexcept {
+ return compute_impl<floor_log5_pow2_minus_log5_3_info, min_exponent,
+ max_exponent>::template compute<ReturnType>(e);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Utilities for fast divisibility tests.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ namespace div {
+ // Replace n by floor(n / 10^N).
+ // Returns true if and only if n is divisible by 10^N.
+ // Precondition: n <= 10^(N+1)
+ // !!It takes an in-out parameter!!
+ template <int N, class UInt>
+ struct divide_by_pow10_info;
+
+ template <class UInt>
+ struct divide_by_pow10_info<1, UInt> {
+ static constexpr stdr::uint_fast32_t magic_number = 6554;
+ static constexpr int shift_amount = 16;
+ };
+
+ template <>
+ struct divide_by_pow10_info<1, stdr::uint_least8_t> {
+ static constexpr stdr::uint_fast16_t magic_number = 103;
+ static constexpr int shift_amount = 10;
+ };
+
+ template <>
+ struct divide_by_pow10_info<1, stdr::uint_least16_t> {
+ static constexpr stdr::uint_fast16_t magic_number = 103;
+ static constexpr int shift_amount = 10;
+ };
+
+ template <class UInt>
+ struct divide_by_pow10_info<2, UInt> {
+ static constexpr stdr::uint_fast32_t magic_number = 656;
+ static constexpr int shift_amount = 16;
+ };
+
+ template <>
+ struct divide_by_pow10_info<2, stdr::uint_least16_t> {
+ static constexpr stdr::uint_fast32_t magic_number = 41;
+ static constexpr int shift_amount = 12;
+ };
+
+ template <int N, class UInt>
+ JKJ_CONSTEXPR14 bool check_divisibility_and_divide_by_pow10(UInt& n) noexcept {
+ // Make sure the computation for max_n does not overflow.
+ static_assert(N + 1 <= log::floor_log10_pow2(int(value_bits<UInt>::value)), "");
+ assert(n <= compute_power<N + 1>(UInt(10)));
+
+ using info = divide_by_pow10_info<N, UInt>;
+ using intermediate_type = decltype(info::magic_number);
+ auto const prod = intermediate_type(n * info::magic_number);
+
+ constexpr auto mask =
+ intermediate_type((intermediate_type(1) << info::shift_amount) - 1);
+ bool const result = ((prod & mask) < info::magic_number);
+
+ n = UInt(prod >> info::shift_amount);
+ return result;
+ }
+
+ // Compute floor(n / 10^N) for small n and N.
+ // Precondition: n <= 10^(N+1)
+ template <int N, class UInt>
+ JKJ_CONSTEXPR14 UInt small_division_by_pow10(UInt n) noexcept {
+ // Make sure the computation for max_n does not overflow.
+ static_assert(N + 1 <= log::floor_log10_pow2(int(value_bits<UInt>::value)), "");
+ assert(n <= compute_power<N + 1>(UInt(10)));
+
+ return UInt((n * divide_by_pow10_info<N, UInt>::magic_number) >>
+ divide_by_pow10_info<N, UInt>::shift_amount);
+ }
+
+ // Compute floor(n / 10^N) for small N.
+ // Precondition: n <= n_max
+ template <int N, class UInt, UInt n_max>
+ JKJ_CONSTEXPR20 UInt divide_by_pow10(UInt n) noexcept {
+ static_assert(N >= 0, "");
+
+ // Specialize for 32-bit division by 10.
+ // Without the bound on n_max (which compilers these days never leverage), the
+ // minimum needed amount of shift is larger than 32. Hence, this may generate better
+ // code for 32-bit or smaller architectures. Even for 64-bit architectures, it seems
+ // compilers tend to generate mov + mul instead of a single imul for an unknown
+ // reason if we just write n / 10.
+ JKJ_IF_CONSTEXPR(stdr::is_same<UInt, stdr::uint_least32_t>::value && N == 1 &&
+ n_max <= UINT32_C(1073741828)) {
+ return UInt(wuint::umul64(n, UINT32_C(429496730)) >> 32);
+ }
+ // Specialize for 64-bit division by 10.
+ // Without the bound on n_max (which compilers these days never leverage), the
+ // minimum needed amount of shift is larger than 64.
+ else JKJ_IF_CONSTEXPR(stdr::is_same<UInt, stdr::uint_least64_t>::value && N == 1 &&
+ n_max <= UINT64_C(4611686018427387908)) {
+ return UInt(wuint::umul128_upper64(n, UINT64_C(1844674407370955162)));
+ }
+ // Specialize for 32-bit division by 100.
+ // It seems compilers tend to generate mov + mul instead of a single imul for an
+ // unknown reason if we just write n / 100.
+ else JKJ_IF_CONSTEXPR(stdr::is_same<UInt, stdr::uint_least32_t>::value && N == 2) {
+ return UInt(wuint::umul64(n, UINT32_C(1374389535)) >> 37);
+ }
+ // Specialize for 64-bit division by 1000.
+ // Without the bound on n_max (which compilers these days never leverage), the
+ // smallest magic number for this computation does not fit into 64-bits.
+ else JKJ_IF_CONSTEXPR(stdr::is_same<UInt, stdr::uint_least64_t>::value && N == 3 &&
+ n_max <= UINT64_C(15534100272597517998)) {
+ return UInt(wuint::umul128_upper64(n, UINT64_C(4722366482869645214)) >> 8);
+ }
+ else {
+ constexpr auto divisor = compute_power<N>(UInt(10));
+ return n / divisor;
+ }
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Return types for the main interface function.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ template <class SignificandType, class ExponentType, bool is_signed, bool trailing_zero_flag>
+ struct decimal_fp;
+
+ template <class SignificandType, class ExponentType>
+ struct decimal_fp<SignificandType, ExponentType, false, false> {
+ SignificandType significand;
+ ExponentType exponent;
+ };
+
+ template <class SignificandType, class ExponentType>
+ struct decimal_fp<SignificandType, ExponentType, true, false> {
+ SignificandType significand;
+ ExponentType exponent;
+ bool is_negative;
+ };
+
+ template <class SignificandType, class ExponentType>
+ struct decimal_fp<SignificandType, ExponentType, false, true> {
+ SignificandType significand;
+ ExponentType exponent;
+ bool may_have_trailing_zeros;
+ };
+
+ template <class SignificandType, class ExponentType>
+ struct decimal_fp<SignificandType, ExponentType, true, true> {
+ SignificandType significand;
+ ExponentType exponent;
+ bool may_have_trailing_zeros;
+ bool is_negative;
+ };
+
+ template <class SignificandType, class ExponentType, bool trailing_zero_flag = false>
+ using unsigned_decimal_fp =
+ decimal_fp<SignificandType, ExponentType, false, trailing_zero_flag>;
+
+ template <class SignificandType, class ExponentType, bool trailing_zero_flag = false>
+ using signed_decimal_fp = decimal_fp<SignificandType, ExponentType, true, trailing_zero_flag>;
+
+ template <class SignificandType, class ExponentType>
+ constexpr signed_decimal_fp<SignificandType, ExponentType, false>
+ add_sign_to_unsigned_decimal_fp(
+ bool is_negative, unsigned_decimal_fp<SignificandType, ExponentType, false> r) noexcept {
+ return {r.significand, r.exponent, is_negative};
+ }
+
+ template <class SignificandType, class ExponentType>
+ constexpr signed_decimal_fp<SignificandType, ExponentType, true>
+ add_sign_to_unsigned_decimal_fp(
+ bool is_negative, unsigned_decimal_fp<SignificandType, ExponentType, true> r) noexcept {
+ return {r.significand, r.exponent, r.may_have_trailing_zeros, is_negative};
+ }
+
+ namespace detail {
+ template <class UnsignedDecimalFp>
+ struct unsigned_decimal_fp_to_signed;
+
+ template <class SignificandType, class ExponentType, bool trailing_zero_flag>
+ struct unsigned_decimal_fp_to_signed<
+ unsigned_decimal_fp<SignificandType, ExponentType, trailing_zero_flag>> {
+ using type = signed_decimal_fp<SignificandType, ExponentType, trailing_zero_flag>;
+ };
+
+ template <class UnsignedDecimalFp>
+ using unsigned_decimal_fp_to_signed_t =
+ typename unsigned_decimal_fp_to_signed<UnsignedDecimalFp>::type;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Computed cache entries.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ template <class FloatFormat, class Dummy = void>
+ struct cache_holder;
+
+ template <class Dummy>
+ struct cache_holder<ieee754_binary32, Dummy> {
+ using cache_entry_type = detail::stdr::uint_least64_t;
+ static constexpr int cache_bits = 64;
+ static constexpr int min_k = -31;
+ static constexpr int max_k = 46;
+ static constexpr detail::array<cache_entry_type, detail::stdr::size_t(max_k - min_k + 1)>
+ cache JKJ_STATIC_DATA_SECTION = {
+ {UINT64_C(0x81ceb32c4b43fcf5), UINT64_C(0xa2425ff75e14fc32),
+ UINT64_C(0xcad2f7f5359a3b3f), UINT64_C(0xfd87b5f28300ca0e),
+ UINT64_C(0x9e74d1b791e07e49), UINT64_C(0xc612062576589ddb),
+ UINT64_C(0xf79687aed3eec552), UINT64_C(0x9abe14cd44753b53),
+ UINT64_C(0xc16d9a0095928a28), UINT64_C(0xf1c90080baf72cb2),
+ UINT64_C(0x971da05074da7bef), UINT64_C(0xbce5086492111aeb),
+ UINT64_C(0xec1e4a7db69561a6), UINT64_C(0x9392ee8e921d5d08),
+ UINT64_C(0xb877aa3236a4b44a), UINT64_C(0xe69594bec44de15c),
+ UINT64_C(0x901d7cf73ab0acda), UINT64_C(0xb424dc35095cd810),
+ UINT64_C(0xe12e13424bb40e14), UINT64_C(0x8cbccc096f5088cc),
+ UINT64_C(0xafebff0bcb24aaff), UINT64_C(0xdbe6fecebdedd5bf),
+ UINT64_C(0x89705f4136b4a598), UINT64_C(0xabcc77118461cefd),
+ UINT64_C(0xd6bf94d5e57a42bd), UINT64_C(0x8637bd05af6c69b6),
+ UINT64_C(0xa7c5ac471b478424), UINT64_C(0xd1b71758e219652c),
+ UINT64_C(0x83126e978d4fdf3c), UINT64_C(0xa3d70a3d70a3d70b),
+ UINT64_C(0xcccccccccccccccd), UINT64_C(0x8000000000000000),
+ UINT64_C(0xa000000000000000), UINT64_C(0xc800000000000000),
+ UINT64_C(0xfa00000000000000), UINT64_C(0x9c40000000000000),
+ UINT64_C(0xc350000000000000), UINT64_C(0xf424000000000000),
+ UINT64_C(0x9896800000000000), UINT64_C(0xbebc200000000000),
+ UINT64_C(0xee6b280000000000), UINT64_C(0x9502f90000000000),
+ UINT64_C(0xba43b74000000000), UINT64_C(0xe8d4a51000000000),
+ UINT64_C(0x9184e72a00000000), UINT64_C(0xb5e620f480000000),
+ UINT64_C(0xe35fa931a0000000), UINT64_C(0x8e1bc9bf04000000),
+ UINT64_C(0xb1a2bc2ec5000000), UINT64_C(0xde0b6b3a76400000),
+ UINT64_C(0x8ac7230489e80000), UINT64_C(0xad78ebc5ac620000),
+ UINT64_C(0xd8d726b7177a8000), UINT64_C(0x878678326eac9000),
+ UINT64_C(0xa968163f0a57b400), UINT64_C(0xd3c21bcecceda100),
+ UINT64_C(0x84595161401484a0), UINT64_C(0xa56fa5b99019a5c8),
+ UINT64_C(0xcecb8f27f4200f3a), UINT64_C(0x813f3978f8940985),
+ UINT64_C(0xa18f07d736b90be6), UINT64_C(0xc9f2c9cd04674edf),
+ UINT64_C(0xfc6f7c4045812297), UINT64_C(0x9dc5ada82b70b59e),
+ UINT64_C(0xc5371912364ce306), UINT64_C(0xf684df56c3e01bc7),
+ UINT64_C(0x9a130b963a6c115d), UINT64_C(0xc097ce7bc90715b4),
+ UINT64_C(0xf0bdc21abb48db21), UINT64_C(0x96769950b50d88f5),
+ UINT64_C(0xbc143fa4e250eb32), UINT64_C(0xeb194f8e1ae525fe),
+ UINT64_C(0x92efd1b8d0cf37bf), UINT64_C(0xb7abc627050305ae),
+ UINT64_C(0xe596b7b0c643c71a), UINT64_C(0x8f7e32ce7bea5c70),
+ UINT64_C(0xb35dbf821ae4f38c), UINT64_C(0xe0352f62a19e306f)}};
+ };
+#if !JKJ_HAS_INLINE_VARIABLE
+ // decltype(...) should not depend on Dummy; see
+ // https://stackoverflow.com/questions/76438400/decltype-on-static-variable-in-template-class.
+ template <class Dummy>
+ constexpr decltype(cache_holder<ieee754_binary32>::cache)
+ cache_holder<ieee754_binary32, Dummy>::cache;
+#endif
+
+ template <class Dummy>
+ struct cache_holder<ieee754_binary64, Dummy> {
+ using cache_entry_type = detail::wuint::uint128;
+ static constexpr int cache_bits = 128;
+ static constexpr int min_k = -292;
+ static constexpr int max_k = 326;
+ static constexpr detail::array<cache_entry_type, detail::stdr::size_t(max_k - min_k + 1)>
+ cache JKJ_STATIC_DATA_SECTION = {
+ {{UINT64_C(0xff77b1fcbebcdc4f), UINT64_C(0x25e8e89c13bb0f7b)},
+ {UINT64_C(0x9faacf3df73609b1), UINT64_C(0x77b191618c54e9ad)},
+ {UINT64_C(0xc795830d75038c1d), UINT64_C(0xd59df5b9ef6a2418)},
+ {UINT64_C(0xf97ae3d0d2446f25), UINT64_C(0x4b0573286b44ad1e)},
+ {UINT64_C(0x9becce62836ac577), UINT64_C(0x4ee367f9430aec33)},
+ {UINT64_C(0xc2e801fb244576d5), UINT64_C(0x229c41f793cda740)},
+ {UINT64_C(0xf3a20279ed56d48a), UINT64_C(0x6b43527578c11110)},
+ {UINT64_C(0x9845418c345644d6), UINT64_C(0x830a13896b78aaaa)},
+ {UINT64_C(0xbe5691ef416bd60c), UINT64_C(0x23cc986bc656d554)},
+ {UINT64_C(0xedec366b11c6cb8f), UINT64_C(0x2cbfbe86b7ec8aa9)},
+ {UINT64_C(0x94b3a202eb1c3f39), UINT64_C(0x7bf7d71432f3d6aa)},
+ {UINT64_C(0xb9e08a83a5e34f07), UINT64_C(0xdaf5ccd93fb0cc54)},
+ {UINT64_C(0xe858ad248f5c22c9), UINT64_C(0xd1b3400f8f9cff69)},
+ {UINT64_C(0x91376c36d99995be), UINT64_C(0x23100809b9c21fa2)},
+ {UINT64_C(0xb58547448ffffb2d), UINT64_C(0xabd40a0c2832a78b)},
+ {UINT64_C(0xe2e69915b3fff9f9), UINT64_C(0x16c90c8f323f516d)},
+ {UINT64_C(0x8dd01fad907ffc3b), UINT64_C(0xae3da7d97f6792e4)},
+ {UINT64_C(0xb1442798f49ffb4a), UINT64_C(0x99cd11cfdf41779d)},
+ {UINT64_C(0xdd95317f31c7fa1d), UINT64_C(0x40405643d711d584)},
+ {UINT64_C(0x8a7d3eef7f1cfc52), UINT64_C(0x482835ea666b2573)},
+ {UINT64_C(0xad1c8eab5ee43b66), UINT64_C(0xda3243650005eed0)},
+ {UINT64_C(0xd863b256369d4a40), UINT64_C(0x90bed43e40076a83)},
+ {UINT64_C(0x873e4f75e2224e68), UINT64_C(0x5a7744a6e804a292)},
+ {UINT64_C(0xa90de3535aaae202), UINT64_C(0x711515d0a205cb37)},
+ {UINT64_C(0xd3515c2831559a83), UINT64_C(0x0d5a5b44ca873e04)},
+ {UINT64_C(0x8412d9991ed58091), UINT64_C(0xe858790afe9486c3)},
+ {UINT64_C(0xa5178fff668ae0b6), UINT64_C(0x626e974dbe39a873)},
+ {UINT64_C(0xce5d73ff402d98e3), UINT64_C(0xfb0a3d212dc81290)},
+ {UINT64_C(0x80fa687f881c7f8e), UINT64_C(0x7ce66634bc9d0b9a)},
+ {UINT64_C(0xa139029f6a239f72), UINT64_C(0x1c1fffc1ebc44e81)},
+ {UINT64_C(0xc987434744ac874e), UINT64_C(0xa327ffb266b56221)},
+ {UINT64_C(0xfbe9141915d7a922), UINT64_C(0x4bf1ff9f0062baa9)},
+ {UINT64_C(0x9d71ac8fada6c9b5), UINT64_C(0x6f773fc3603db4aa)},
+ {UINT64_C(0xc4ce17b399107c22), UINT64_C(0xcb550fb4384d21d4)},
+ {UINT64_C(0xf6019da07f549b2b), UINT64_C(0x7e2a53a146606a49)},
+ {UINT64_C(0x99c102844f94e0fb), UINT64_C(0x2eda7444cbfc426e)},
+ {UINT64_C(0xc0314325637a1939), UINT64_C(0xfa911155fefb5309)},
+ {UINT64_C(0xf03d93eebc589f88), UINT64_C(0x793555ab7eba27cb)},
+ {UINT64_C(0x96267c7535b763b5), UINT64_C(0x4bc1558b2f3458df)},
+ {UINT64_C(0xbbb01b9283253ca2), UINT64_C(0x9eb1aaedfb016f17)},
+ {UINT64_C(0xea9c227723ee8bcb), UINT64_C(0x465e15a979c1cadd)},
+ {UINT64_C(0x92a1958a7675175f), UINT64_C(0x0bfacd89ec191eca)},
+ {UINT64_C(0xb749faed14125d36), UINT64_C(0xcef980ec671f667c)},
+ {UINT64_C(0xe51c79a85916f484), UINT64_C(0x82b7e12780e7401b)},
+ {UINT64_C(0x8f31cc0937ae58d2), UINT64_C(0xd1b2ecb8b0908811)},
+ {UINT64_C(0xb2fe3f0b8599ef07), UINT64_C(0x861fa7e6dcb4aa16)},
+ {UINT64_C(0xdfbdcece67006ac9), UINT64_C(0x67a791e093e1d49b)},
+ {UINT64_C(0x8bd6a141006042bd), UINT64_C(0xe0c8bb2c5c6d24e1)},
+ {UINT64_C(0xaecc49914078536d), UINT64_C(0x58fae9f773886e19)},
+ {UINT64_C(0xda7f5bf590966848), UINT64_C(0xaf39a475506a899f)},
+ {UINT64_C(0x888f99797a5e012d), UINT64_C(0x6d8406c952429604)},
+ {UINT64_C(0xaab37fd7d8f58178), UINT64_C(0xc8e5087ba6d33b84)},
+ {UINT64_C(0xd5605fcdcf32e1d6), UINT64_C(0xfb1e4a9a90880a65)},
+ {UINT64_C(0x855c3be0a17fcd26), UINT64_C(0x5cf2eea09a550680)},
+ {UINT64_C(0xa6b34ad8c9dfc06f), UINT64_C(0xf42faa48c0ea481f)},
+ {UINT64_C(0xd0601d8efc57b08b), UINT64_C(0xf13b94daf124da27)},
+ {UINT64_C(0x823c12795db6ce57), UINT64_C(0x76c53d08d6b70859)},
+ {UINT64_C(0xa2cb1717b52481ed), UINT64_C(0x54768c4b0c64ca6f)},
+ {UINT64_C(0xcb7ddcdda26da268), UINT64_C(0xa9942f5dcf7dfd0a)},
+ {UINT64_C(0xfe5d54150b090b02), UINT64_C(0xd3f93b35435d7c4d)},
+ {UINT64_C(0x9efa548d26e5a6e1), UINT64_C(0xc47bc5014a1a6db0)},
+ {UINT64_C(0xc6b8e9b0709f109a), UINT64_C(0x359ab6419ca1091c)},
+ {UINT64_C(0xf867241c8cc6d4c0), UINT64_C(0xc30163d203c94b63)},
+ {UINT64_C(0x9b407691d7fc44f8), UINT64_C(0x79e0de63425dcf1e)},
+ {UINT64_C(0xc21094364dfb5636), UINT64_C(0x985915fc12f542e5)},
+ {UINT64_C(0xf294b943e17a2bc4), UINT64_C(0x3e6f5b7b17b2939e)},
+ {UINT64_C(0x979cf3ca6cec5b5a), UINT64_C(0xa705992ceecf9c43)},
+ {UINT64_C(0xbd8430bd08277231), UINT64_C(0x50c6ff782a838354)},
+ {UINT64_C(0xece53cec4a314ebd), UINT64_C(0xa4f8bf5635246429)},
+ {UINT64_C(0x940f4613ae5ed136), UINT64_C(0x871b7795e136be9a)},
+ {UINT64_C(0xb913179899f68584), UINT64_C(0x28e2557b59846e40)},
+ {UINT64_C(0xe757dd7ec07426e5), UINT64_C(0x331aeada2fe589d0)},
+ {UINT64_C(0x9096ea6f3848984f), UINT64_C(0x3ff0d2c85def7622)},
+ {UINT64_C(0xb4bca50b065abe63), UINT64_C(0x0fed077a756b53aa)},
+ {UINT64_C(0xe1ebce4dc7f16dfb), UINT64_C(0xd3e8495912c62895)},
+ {UINT64_C(0x8d3360f09cf6e4bd), UINT64_C(0x64712dd7abbbd95d)},
+ {UINT64_C(0xb080392cc4349dec), UINT64_C(0xbd8d794d96aacfb4)},
+ {UINT64_C(0xdca04777f541c567), UINT64_C(0xecf0d7a0fc5583a1)},
+ {UINT64_C(0x89e42caaf9491b60), UINT64_C(0xf41686c49db57245)},
+ {UINT64_C(0xac5d37d5b79b6239), UINT64_C(0x311c2875c522ced6)},
+ {UINT64_C(0xd77485cb25823ac7), UINT64_C(0x7d633293366b828c)},
+ {UINT64_C(0x86a8d39ef77164bc), UINT64_C(0xae5dff9c02033198)},
+ {UINT64_C(0xa8530886b54dbdeb), UINT64_C(0xd9f57f830283fdfd)},
+ {UINT64_C(0xd267caa862a12d66), UINT64_C(0xd072df63c324fd7c)},
+ {UINT64_C(0x8380dea93da4bc60), UINT64_C(0x4247cb9e59f71e6e)},
+ {UINT64_C(0xa46116538d0deb78), UINT64_C(0x52d9be85f074e609)},
+ {UINT64_C(0xcd795be870516656), UINT64_C(0x67902e276c921f8c)},
+ {UINT64_C(0x806bd9714632dff6), UINT64_C(0x00ba1cd8a3db53b7)},
+ {UINT64_C(0xa086cfcd97bf97f3), UINT64_C(0x80e8a40eccd228a5)},
+ {UINT64_C(0xc8a883c0fdaf7df0), UINT64_C(0x6122cd128006b2ce)},
+ {UINT64_C(0xfad2a4b13d1b5d6c), UINT64_C(0x796b805720085f82)},
+ {UINT64_C(0x9cc3a6eec6311a63), UINT64_C(0xcbe3303674053bb1)},
+ {UINT64_C(0xc3f490aa77bd60fc), UINT64_C(0xbedbfc4411068a9d)},
+ {UINT64_C(0xf4f1b4d515acb93b), UINT64_C(0xee92fb5515482d45)},
+ {UINT64_C(0x991711052d8bf3c5), UINT64_C(0x751bdd152d4d1c4b)},
+ {UINT64_C(0xbf5cd54678eef0b6), UINT64_C(0xd262d45a78a0635e)},
+ {UINT64_C(0xef340a98172aace4), UINT64_C(0x86fb897116c87c35)},
+ {UINT64_C(0x9580869f0e7aac0e), UINT64_C(0xd45d35e6ae3d4da1)},
+ {UINT64_C(0xbae0a846d2195712), UINT64_C(0x8974836059cca10a)},
+ {UINT64_C(0xe998d258869facd7), UINT64_C(0x2bd1a438703fc94c)},
+ {UINT64_C(0x91ff83775423cc06), UINT64_C(0x7b6306a34627ddd0)},
+ {UINT64_C(0xb67f6455292cbf08), UINT64_C(0x1a3bc84c17b1d543)},
+ {UINT64_C(0xe41f3d6a7377eeca), UINT64_C(0x20caba5f1d9e4a94)},
+ {UINT64_C(0x8e938662882af53e), UINT64_C(0x547eb47b7282ee9d)},
+ {UINT64_C(0xb23867fb2a35b28d), UINT64_C(0xe99e619a4f23aa44)},
+ {UINT64_C(0xdec681f9f4c31f31), UINT64_C(0x6405fa00e2ec94d5)},
+ {UINT64_C(0x8b3c113c38f9f37e), UINT64_C(0xde83bc408dd3dd05)},
+ {UINT64_C(0xae0b158b4738705e), UINT64_C(0x9624ab50b148d446)},
+ {UINT64_C(0xd98ddaee19068c76), UINT64_C(0x3badd624dd9b0958)},
+ {UINT64_C(0x87f8a8d4cfa417c9), UINT64_C(0xe54ca5d70a80e5d7)},
+ {UINT64_C(0xa9f6d30a038d1dbc), UINT64_C(0x5e9fcf4ccd211f4d)},
+ {UINT64_C(0xd47487cc8470652b), UINT64_C(0x7647c32000696720)},
+ {UINT64_C(0x84c8d4dfd2c63f3b), UINT64_C(0x29ecd9f40041e074)},
+ {UINT64_C(0xa5fb0a17c777cf09), UINT64_C(0xf468107100525891)},
+ {UINT64_C(0xcf79cc9db955c2cc), UINT64_C(0x7182148d4066eeb5)},
+ {UINT64_C(0x81ac1fe293d599bf), UINT64_C(0xc6f14cd848405531)},
+ {UINT64_C(0xa21727db38cb002f), UINT64_C(0xb8ada00e5a506a7d)},
+ {UINT64_C(0xca9cf1d206fdc03b), UINT64_C(0xa6d90811f0e4851d)},
+ {UINT64_C(0xfd442e4688bd304a), UINT64_C(0x908f4a166d1da664)},
+ {UINT64_C(0x9e4a9cec15763e2e), UINT64_C(0x9a598e4e043287ff)},
+ {UINT64_C(0xc5dd44271ad3cdba), UINT64_C(0x40eff1e1853f29fe)},
+ {UINT64_C(0xf7549530e188c128), UINT64_C(0xd12bee59e68ef47d)},
+ {UINT64_C(0x9a94dd3e8cf578b9), UINT64_C(0x82bb74f8301958cf)},
+ {UINT64_C(0xc13a148e3032d6e7), UINT64_C(0xe36a52363c1faf02)},
+ {UINT64_C(0xf18899b1bc3f8ca1), UINT64_C(0xdc44e6c3cb279ac2)},
+ {UINT64_C(0x96f5600f15a7b7e5), UINT64_C(0x29ab103a5ef8c0ba)},
+ {UINT64_C(0xbcb2b812db11a5de), UINT64_C(0x7415d448f6b6f0e8)},
+ {UINT64_C(0xebdf661791d60f56), UINT64_C(0x111b495b3464ad22)},
+ {UINT64_C(0x936b9fcebb25c995), UINT64_C(0xcab10dd900beec35)},
+ {UINT64_C(0xb84687c269ef3bfb), UINT64_C(0x3d5d514f40eea743)},
+ {UINT64_C(0xe65829b3046b0afa), UINT64_C(0x0cb4a5a3112a5113)},
+ {UINT64_C(0x8ff71a0fe2c2e6dc), UINT64_C(0x47f0e785eaba72ac)},
+ {UINT64_C(0xb3f4e093db73a093), UINT64_C(0x59ed216765690f57)},
+ {UINT64_C(0xe0f218b8d25088b8), UINT64_C(0x306869c13ec3532d)},
+ {UINT64_C(0x8c974f7383725573), UINT64_C(0x1e414218c73a13fc)},
+ {UINT64_C(0xafbd2350644eeacf), UINT64_C(0xe5d1929ef90898fb)},
+ {UINT64_C(0xdbac6c247d62a583), UINT64_C(0xdf45f746b74abf3a)},
+ {UINT64_C(0x894bc396ce5da772), UINT64_C(0x6b8bba8c328eb784)},
+ {UINT64_C(0xab9eb47c81f5114f), UINT64_C(0x066ea92f3f326565)},
+ {UINT64_C(0xd686619ba27255a2), UINT64_C(0xc80a537b0efefebe)},
+ {UINT64_C(0x8613fd0145877585), UINT64_C(0xbd06742ce95f5f37)},
+ {UINT64_C(0xa798fc4196e952e7), UINT64_C(0x2c48113823b73705)},
+ {UINT64_C(0xd17f3b51fca3a7a0), UINT64_C(0xf75a15862ca504c6)},
+ {UINT64_C(0x82ef85133de648c4), UINT64_C(0x9a984d73dbe722fc)},
+ {UINT64_C(0xa3ab66580d5fdaf5), UINT64_C(0xc13e60d0d2e0ebbb)},
+ {UINT64_C(0xcc963fee10b7d1b3), UINT64_C(0x318df905079926a9)},
+ {UINT64_C(0xffbbcfe994e5c61f), UINT64_C(0xfdf17746497f7053)},
+ {UINT64_C(0x9fd561f1fd0f9bd3), UINT64_C(0xfeb6ea8bedefa634)},
+ {UINT64_C(0xc7caba6e7c5382c8), UINT64_C(0xfe64a52ee96b8fc1)},
+ {UINT64_C(0xf9bd690a1b68637b), UINT64_C(0x3dfdce7aa3c673b1)},
+ {UINT64_C(0x9c1661a651213e2d), UINT64_C(0x06bea10ca65c084f)},
+ {UINT64_C(0xc31bfa0fe5698db8), UINT64_C(0x486e494fcff30a63)},
+ {UINT64_C(0xf3e2f893dec3f126), UINT64_C(0x5a89dba3c3efccfb)},
+ {UINT64_C(0x986ddb5c6b3a76b7), UINT64_C(0xf89629465a75e01d)},
+ {UINT64_C(0xbe89523386091465), UINT64_C(0xf6bbb397f1135824)},
+ {UINT64_C(0xee2ba6c0678b597f), UINT64_C(0x746aa07ded582e2d)},
+ {UINT64_C(0x94db483840b717ef), UINT64_C(0xa8c2a44eb4571cdd)},
+ {UINT64_C(0xba121a4650e4ddeb), UINT64_C(0x92f34d62616ce414)},
+ {UINT64_C(0xe896a0d7e51e1566), UINT64_C(0x77b020baf9c81d18)},
+ {UINT64_C(0x915e2486ef32cd60), UINT64_C(0x0ace1474dc1d122f)},
+ {UINT64_C(0xb5b5ada8aaff80b8), UINT64_C(0x0d819992132456bb)},
+ {UINT64_C(0xe3231912d5bf60e6), UINT64_C(0x10e1fff697ed6c6a)},
+ {UINT64_C(0x8df5efabc5979c8f), UINT64_C(0xca8d3ffa1ef463c2)},
+ {UINT64_C(0xb1736b96b6fd83b3), UINT64_C(0xbd308ff8a6b17cb3)},
+ {UINT64_C(0xddd0467c64bce4a0), UINT64_C(0xac7cb3f6d05ddbdf)},
+ {UINT64_C(0x8aa22c0dbef60ee4), UINT64_C(0x6bcdf07a423aa96c)},
+ {UINT64_C(0xad4ab7112eb3929d), UINT64_C(0x86c16c98d2c953c7)},
+ {UINT64_C(0xd89d64d57a607744), UINT64_C(0xe871c7bf077ba8b8)},
+ {UINT64_C(0x87625f056c7c4a8b), UINT64_C(0x11471cd764ad4973)},
+ {UINT64_C(0xa93af6c6c79b5d2d), UINT64_C(0xd598e40d3dd89bd0)},
+ {UINT64_C(0xd389b47879823479), UINT64_C(0x4aff1d108d4ec2c4)},
+ {UINT64_C(0x843610cb4bf160cb), UINT64_C(0xcedf722a585139bb)},
+ {UINT64_C(0xa54394fe1eedb8fe), UINT64_C(0xc2974eb4ee658829)},
+ {UINT64_C(0xce947a3da6a9273e), UINT64_C(0x733d226229feea33)},
+ {UINT64_C(0x811ccc668829b887), UINT64_C(0x0806357d5a3f5260)},
+ {UINT64_C(0xa163ff802a3426a8), UINT64_C(0xca07c2dcb0cf26f8)},
+ {UINT64_C(0xc9bcff6034c13052), UINT64_C(0xfc89b393dd02f0b6)},
+ {UINT64_C(0xfc2c3f3841f17c67), UINT64_C(0xbbac2078d443ace3)},
+ {UINT64_C(0x9d9ba7832936edc0), UINT64_C(0xd54b944b84aa4c0e)},
+ {UINT64_C(0xc5029163f384a931), UINT64_C(0x0a9e795e65d4df12)},
+ {UINT64_C(0xf64335bcf065d37d), UINT64_C(0x4d4617b5ff4a16d6)},
+ {UINT64_C(0x99ea0196163fa42e), UINT64_C(0x504bced1bf8e4e46)},
+ {UINT64_C(0xc06481fb9bcf8d39), UINT64_C(0xe45ec2862f71e1d7)},
+ {UINT64_C(0xf07da27a82c37088), UINT64_C(0x5d767327bb4e5a4d)},
+ {UINT64_C(0x964e858c91ba2655), UINT64_C(0x3a6a07f8d510f870)},
+ {UINT64_C(0xbbe226efb628afea), UINT64_C(0x890489f70a55368c)},
+ {UINT64_C(0xeadab0aba3b2dbe5), UINT64_C(0x2b45ac74ccea842f)},
+ {UINT64_C(0x92c8ae6b464fc96f), UINT64_C(0x3b0b8bc90012929e)},
+ {UINT64_C(0xb77ada0617e3bbcb), UINT64_C(0x09ce6ebb40173745)},
+ {UINT64_C(0xe55990879ddcaabd), UINT64_C(0xcc420a6a101d0516)},
+ {UINT64_C(0x8f57fa54c2a9eab6), UINT64_C(0x9fa946824a12232e)},
+ {UINT64_C(0xb32df8e9f3546564), UINT64_C(0x47939822dc96abfa)},
+ {UINT64_C(0xdff9772470297ebd), UINT64_C(0x59787e2b93bc56f8)},
+ {UINT64_C(0x8bfbea76c619ef36), UINT64_C(0x57eb4edb3c55b65b)},
+ {UINT64_C(0xaefae51477a06b03), UINT64_C(0xede622920b6b23f2)},
+ {UINT64_C(0xdab99e59958885c4), UINT64_C(0xe95fab368e45ecee)},
+ {UINT64_C(0x88b402f7fd75539b), UINT64_C(0x11dbcb0218ebb415)},
+ {UINT64_C(0xaae103b5fcd2a881), UINT64_C(0xd652bdc29f26a11a)},
+ {UINT64_C(0xd59944a37c0752a2), UINT64_C(0x4be76d3346f04960)},
+ {UINT64_C(0x857fcae62d8493a5), UINT64_C(0x6f70a4400c562ddc)},
+ {UINT64_C(0xa6dfbd9fb8e5b88e), UINT64_C(0xcb4ccd500f6bb953)},
+ {UINT64_C(0xd097ad07a71f26b2), UINT64_C(0x7e2000a41346a7a8)},
+ {UINT64_C(0x825ecc24c873782f), UINT64_C(0x8ed400668c0c28c9)},
+ {UINT64_C(0xa2f67f2dfa90563b), UINT64_C(0x728900802f0f32fb)},
+ {UINT64_C(0xcbb41ef979346bca), UINT64_C(0x4f2b40a03ad2ffba)},
+ {UINT64_C(0xfea126b7d78186bc), UINT64_C(0xe2f610c84987bfa9)},
+ {UINT64_C(0x9f24b832e6b0f436), UINT64_C(0x0dd9ca7d2df4d7ca)},
+ {UINT64_C(0xc6ede63fa05d3143), UINT64_C(0x91503d1c79720dbc)},
+ {UINT64_C(0xf8a95fcf88747d94), UINT64_C(0x75a44c6397ce912b)},
+ {UINT64_C(0x9b69dbe1b548ce7c), UINT64_C(0xc986afbe3ee11abb)},
+ {UINT64_C(0xc24452da229b021b), UINT64_C(0xfbe85badce996169)},
+ {UINT64_C(0xf2d56790ab41c2a2), UINT64_C(0xfae27299423fb9c4)},
+ {UINT64_C(0x97c560ba6b0919a5), UINT64_C(0xdccd879fc967d41b)},
+ {UINT64_C(0xbdb6b8e905cb600f), UINT64_C(0x5400e987bbc1c921)},
+ {UINT64_C(0xed246723473e3813), UINT64_C(0x290123e9aab23b69)},
+ {UINT64_C(0x9436c0760c86e30b), UINT64_C(0xf9a0b6720aaf6522)},
+ {UINT64_C(0xb94470938fa89bce), UINT64_C(0xf808e40e8d5b3e6a)},
+ {UINT64_C(0xe7958cb87392c2c2), UINT64_C(0xb60b1d1230b20e05)},
+ {UINT64_C(0x90bd77f3483bb9b9), UINT64_C(0xb1c6f22b5e6f48c3)},
+ {UINT64_C(0xb4ecd5f01a4aa828), UINT64_C(0x1e38aeb6360b1af4)},
+ {UINT64_C(0xe2280b6c20dd5232), UINT64_C(0x25c6da63c38de1b1)},
+ {UINT64_C(0x8d590723948a535f), UINT64_C(0x579c487e5a38ad0f)},
+ {UINT64_C(0xb0af48ec79ace837), UINT64_C(0x2d835a9df0c6d852)},
+ {UINT64_C(0xdcdb1b2798182244), UINT64_C(0xf8e431456cf88e66)},
+ {UINT64_C(0x8a08f0f8bf0f156b), UINT64_C(0x1b8e9ecb641b5900)},
+ {UINT64_C(0xac8b2d36eed2dac5), UINT64_C(0xe272467e3d222f40)},
+ {UINT64_C(0xd7adf884aa879177), UINT64_C(0x5b0ed81dcc6abb10)},
+ {UINT64_C(0x86ccbb52ea94baea), UINT64_C(0x98e947129fc2b4ea)},
+ {UINT64_C(0xa87fea27a539e9a5), UINT64_C(0x3f2398d747b36225)},
+ {UINT64_C(0xd29fe4b18e88640e), UINT64_C(0x8eec7f0d19a03aae)},
+ {UINT64_C(0x83a3eeeef9153e89), UINT64_C(0x1953cf68300424ad)},
+ {UINT64_C(0xa48ceaaab75a8e2b), UINT64_C(0x5fa8c3423c052dd8)},
+ {UINT64_C(0xcdb02555653131b6), UINT64_C(0x3792f412cb06794e)},
+ {UINT64_C(0x808e17555f3ebf11), UINT64_C(0xe2bbd88bbee40bd1)},
+ {UINT64_C(0xa0b19d2ab70e6ed6), UINT64_C(0x5b6aceaeae9d0ec5)},
+ {UINT64_C(0xc8de047564d20a8b), UINT64_C(0xf245825a5a445276)},
+ {UINT64_C(0xfb158592be068d2e), UINT64_C(0xeed6e2f0f0d56713)},
+ {UINT64_C(0x9ced737bb6c4183d), UINT64_C(0x55464dd69685606c)},
+ {UINT64_C(0xc428d05aa4751e4c), UINT64_C(0xaa97e14c3c26b887)},
+ {UINT64_C(0xf53304714d9265df), UINT64_C(0xd53dd99f4b3066a9)},
+ {UINT64_C(0x993fe2c6d07b7fab), UINT64_C(0xe546a8038efe402a)},
+ {UINT64_C(0xbf8fdb78849a5f96), UINT64_C(0xde98520472bdd034)},
+ {UINT64_C(0xef73d256a5c0f77c), UINT64_C(0x963e66858f6d4441)},
+ {UINT64_C(0x95a8637627989aad), UINT64_C(0xdde7001379a44aa9)},
+ {UINT64_C(0xbb127c53b17ec159), UINT64_C(0x5560c018580d5d53)},
+ {UINT64_C(0xe9d71b689dde71af), UINT64_C(0xaab8f01e6e10b4a7)},
+ {UINT64_C(0x9226712162ab070d), UINT64_C(0xcab3961304ca70e9)},
+ {UINT64_C(0xb6b00d69bb55c8d1), UINT64_C(0x3d607b97c5fd0d23)},
+ {UINT64_C(0xe45c10c42a2b3b05), UINT64_C(0x8cb89a7db77c506b)},
+ {UINT64_C(0x8eb98a7a9a5b04e3), UINT64_C(0x77f3608e92adb243)},
+ {UINT64_C(0xb267ed1940f1c61c), UINT64_C(0x55f038b237591ed4)},
+ {UINT64_C(0xdf01e85f912e37a3), UINT64_C(0x6b6c46dec52f6689)},
+ {UINT64_C(0x8b61313bbabce2c6), UINT64_C(0x2323ac4b3b3da016)},
+ {UINT64_C(0xae397d8aa96c1b77), UINT64_C(0xabec975e0a0d081b)},
+ {UINT64_C(0xd9c7dced53c72255), UINT64_C(0x96e7bd358c904a22)},
+ {UINT64_C(0x881cea14545c7575), UINT64_C(0x7e50d64177da2e55)},
+ {UINT64_C(0xaa242499697392d2), UINT64_C(0xdde50bd1d5d0b9ea)},
+ {UINT64_C(0xd4ad2dbfc3d07787), UINT64_C(0x955e4ec64b44e865)},
+ {UINT64_C(0x84ec3c97da624ab4), UINT64_C(0xbd5af13bef0b113f)},
+ {UINT64_C(0xa6274bbdd0fadd61), UINT64_C(0xecb1ad8aeacdd58f)},
+ {UINT64_C(0xcfb11ead453994ba), UINT64_C(0x67de18eda5814af3)},
+ {UINT64_C(0x81ceb32c4b43fcf4), UINT64_C(0x80eacf948770ced8)},
+ {UINT64_C(0xa2425ff75e14fc31), UINT64_C(0xa1258379a94d028e)},
+ {UINT64_C(0xcad2f7f5359a3b3e), UINT64_C(0x096ee45813a04331)},
+ {UINT64_C(0xfd87b5f28300ca0d), UINT64_C(0x8bca9d6e188853fd)},
+ {UINT64_C(0x9e74d1b791e07e48), UINT64_C(0x775ea264cf55347e)},
+ {UINT64_C(0xc612062576589dda), UINT64_C(0x95364afe032a819e)},
+ {UINT64_C(0xf79687aed3eec551), UINT64_C(0x3a83ddbd83f52205)},
+ {UINT64_C(0x9abe14cd44753b52), UINT64_C(0xc4926a9672793543)},
+ {UINT64_C(0xc16d9a0095928a27), UINT64_C(0x75b7053c0f178294)},
+ {UINT64_C(0xf1c90080baf72cb1), UINT64_C(0x5324c68b12dd6339)},
+ {UINT64_C(0x971da05074da7bee), UINT64_C(0xd3f6fc16ebca5e04)},
+ {UINT64_C(0xbce5086492111aea), UINT64_C(0x88f4bb1ca6bcf585)},
+ {UINT64_C(0xec1e4a7db69561a5), UINT64_C(0x2b31e9e3d06c32e6)},
+ {UINT64_C(0x9392ee8e921d5d07), UINT64_C(0x3aff322e62439fd0)},
+ {UINT64_C(0xb877aa3236a4b449), UINT64_C(0x09befeb9fad487c3)},
+ {UINT64_C(0xe69594bec44de15b), UINT64_C(0x4c2ebe687989a9b4)},
+ {UINT64_C(0x901d7cf73ab0acd9), UINT64_C(0x0f9d37014bf60a11)},
+ {UINT64_C(0xb424dc35095cd80f), UINT64_C(0x538484c19ef38c95)},
+ {UINT64_C(0xe12e13424bb40e13), UINT64_C(0x2865a5f206b06fba)},
+ {UINT64_C(0x8cbccc096f5088cb), UINT64_C(0xf93f87b7442e45d4)},
+ {UINT64_C(0xafebff0bcb24aafe), UINT64_C(0xf78f69a51539d749)},
+ {UINT64_C(0xdbe6fecebdedd5be), UINT64_C(0xb573440e5a884d1c)},
+ {UINT64_C(0x89705f4136b4a597), UINT64_C(0x31680a88f8953031)},
+ {UINT64_C(0xabcc77118461cefc), UINT64_C(0xfdc20d2b36ba7c3e)},
+ {UINT64_C(0xd6bf94d5e57a42bc), UINT64_C(0x3d32907604691b4d)},
+ {UINT64_C(0x8637bd05af6c69b5), UINT64_C(0xa63f9a49c2c1b110)},
+ {UINT64_C(0xa7c5ac471b478423), UINT64_C(0x0fcf80dc33721d54)},
+ {UINT64_C(0xd1b71758e219652b), UINT64_C(0xd3c36113404ea4a9)},
+ {UINT64_C(0x83126e978d4fdf3b), UINT64_C(0x645a1cac083126ea)},
+ {UINT64_C(0xa3d70a3d70a3d70a), UINT64_C(0x3d70a3d70a3d70a4)},
+ {UINT64_C(0xcccccccccccccccc), UINT64_C(0xcccccccccccccccd)},
+ {UINT64_C(0x8000000000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xa000000000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xc800000000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xfa00000000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0x9c40000000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xc350000000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xf424000000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0x9896800000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xbebc200000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xee6b280000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0x9502f90000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xba43b74000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xe8d4a51000000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0x9184e72a00000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xb5e620f480000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xe35fa931a0000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0x8e1bc9bf04000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xb1a2bc2ec5000000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xde0b6b3a76400000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0x8ac7230489e80000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xad78ebc5ac620000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xd8d726b7177a8000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0x878678326eac9000), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xa968163f0a57b400), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xd3c21bcecceda100), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0x84595161401484a0), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xa56fa5b99019a5c8), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0xcecb8f27f4200f3a), UINT64_C(0x0000000000000000)},
+ {UINT64_C(0x813f3978f8940984), UINT64_C(0x4000000000000000)},
+ {UINT64_C(0xa18f07d736b90be5), UINT64_C(0x5000000000000000)},
+ {UINT64_C(0xc9f2c9cd04674ede), UINT64_C(0xa400000000000000)},
+ {UINT64_C(0xfc6f7c4045812296), UINT64_C(0x4d00000000000000)},
+ {UINT64_C(0x9dc5ada82b70b59d), UINT64_C(0xf020000000000000)},
+ {UINT64_C(0xc5371912364ce305), UINT64_C(0x6c28000000000000)},
+ {UINT64_C(0xf684df56c3e01bc6), UINT64_C(0xc732000000000000)},
+ {UINT64_C(0x9a130b963a6c115c), UINT64_C(0x3c7f400000000000)},
+ {UINT64_C(0xc097ce7bc90715b3), UINT64_C(0x4b9f100000000000)},
+ {UINT64_C(0xf0bdc21abb48db20), UINT64_C(0x1e86d40000000000)},
+ {UINT64_C(0x96769950b50d88f4), UINT64_C(0x1314448000000000)},
+ {UINT64_C(0xbc143fa4e250eb31), UINT64_C(0x17d955a000000000)},
+ {UINT64_C(0xeb194f8e1ae525fd), UINT64_C(0x5dcfab0800000000)},
+ {UINT64_C(0x92efd1b8d0cf37be), UINT64_C(0x5aa1cae500000000)},
+ {UINT64_C(0xb7abc627050305ad), UINT64_C(0xf14a3d9e40000000)},
+ {UINT64_C(0xe596b7b0c643c719), UINT64_C(0x6d9ccd05d0000000)},
+ {UINT64_C(0x8f7e32ce7bea5c6f), UINT64_C(0xe4820023a2000000)},
+ {UINT64_C(0xb35dbf821ae4f38b), UINT64_C(0xdda2802c8a800000)},
+ {UINT64_C(0xe0352f62a19e306e), UINT64_C(0xd50b2037ad200000)},
+ {UINT64_C(0x8c213d9da502de45), UINT64_C(0x4526f422cc340000)},
+ {UINT64_C(0xaf298d050e4395d6), UINT64_C(0x9670b12b7f410000)},
+ {UINT64_C(0xdaf3f04651d47b4c), UINT64_C(0x3c0cdd765f114000)},
+ {UINT64_C(0x88d8762bf324cd0f), UINT64_C(0xa5880a69fb6ac800)},
+ {UINT64_C(0xab0e93b6efee0053), UINT64_C(0x8eea0d047a457a00)},
+ {UINT64_C(0xd5d238a4abe98068), UINT64_C(0x72a4904598d6d880)},
+ {UINT64_C(0x85a36366eb71f041), UINT64_C(0x47a6da2b7f864750)},
+ {UINT64_C(0xa70c3c40a64e6c51), UINT64_C(0x999090b65f67d924)},
+ {UINT64_C(0xd0cf4b50cfe20765), UINT64_C(0xfff4b4e3f741cf6d)},
+ {UINT64_C(0x82818f1281ed449f), UINT64_C(0xbff8f10e7a8921a5)},
+ {UINT64_C(0xa321f2d7226895c7), UINT64_C(0xaff72d52192b6a0e)},
+ {UINT64_C(0xcbea6f8ceb02bb39), UINT64_C(0x9bf4f8a69f764491)},
+ {UINT64_C(0xfee50b7025c36a08), UINT64_C(0x02f236d04753d5b5)},
+ {UINT64_C(0x9f4f2726179a2245), UINT64_C(0x01d762422c946591)},
+ {UINT64_C(0xc722f0ef9d80aad6), UINT64_C(0x424d3ad2b7b97ef6)},
+ {UINT64_C(0xf8ebad2b84e0d58b), UINT64_C(0xd2e0898765a7deb3)},
+ {UINT64_C(0x9b934c3b330c8577), UINT64_C(0x63cc55f49f88eb30)},
+ {UINT64_C(0xc2781f49ffcfa6d5), UINT64_C(0x3cbf6b71c76b25fc)},
+ {UINT64_C(0xf316271c7fc3908a), UINT64_C(0x8bef464e3945ef7b)},
+ {UINT64_C(0x97edd871cfda3a56), UINT64_C(0x97758bf0e3cbb5ad)},
+ {UINT64_C(0xbde94e8e43d0c8ec), UINT64_C(0x3d52eeed1cbea318)},
+ {UINT64_C(0xed63a231d4c4fb27), UINT64_C(0x4ca7aaa863ee4bde)},
+ {UINT64_C(0x945e455f24fb1cf8), UINT64_C(0x8fe8caa93e74ef6b)},
+ {UINT64_C(0xb975d6b6ee39e436), UINT64_C(0xb3e2fd538e122b45)},
+ {UINT64_C(0xe7d34c64a9c85d44), UINT64_C(0x60dbbca87196b617)},
+ {UINT64_C(0x90e40fbeea1d3a4a), UINT64_C(0xbc8955e946fe31ce)},
+ {UINT64_C(0xb51d13aea4a488dd), UINT64_C(0x6babab6398bdbe42)},
+ {UINT64_C(0xe264589a4dcdab14), UINT64_C(0xc696963c7eed2dd2)},
+ {UINT64_C(0x8d7eb76070a08aec), UINT64_C(0xfc1e1de5cf543ca3)},
+ {UINT64_C(0xb0de65388cc8ada8), UINT64_C(0x3b25a55f43294bcc)},
+ {UINT64_C(0xdd15fe86affad912), UINT64_C(0x49ef0eb713f39ebf)},
+ {UINT64_C(0x8a2dbf142dfcc7ab), UINT64_C(0x6e3569326c784338)},
+ {UINT64_C(0xacb92ed9397bf996), UINT64_C(0x49c2c37f07965405)},
+ {UINT64_C(0xd7e77a8f87daf7fb), UINT64_C(0xdc33745ec97be907)},
+ {UINT64_C(0x86f0ac99b4e8dafd), UINT64_C(0x69a028bb3ded71a4)},
+ {UINT64_C(0xa8acd7c0222311bc), UINT64_C(0xc40832ea0d68ce0d)},
+ {UINT64_C(0xd2d80db02aabd62b), UINT64_C(0xf50a3fa490c30191)},
+ {UINT64_C(0x83c7088e1aab65db), UINT64_C(0x792667c6da79e0fb)},
+ {UINT64_C(0xa4b8cab1a1563f52), UINT64_C(0x577001b891185939)},
+ {UINT64_C(0xcde6fd5e09abcf26), UINT64_C(0xed4c0226b55e6f87)},
+ {UINT64_C(0x80b05e5ac60b6178), UINT64_C(0x544f8158315b05b5)},
+ {UINT64_C(0xa0dc75f1778e39d6), UINT64_C(0x696361ae3db1c722)},
+ {UINT64_C(0xc913936dd571c84c), UINT64_C(0x03bc3a19cd1e38ea)},
+ {UINT64_C(0xfb5878494ace3a5f), UINT64_C(0x04ab48a04065c724)},
+ {UINT64_C(0x9d174b2dcec0e47b), UINT64_C(0x62eb0d64283f9c77)},
+ {UINT64_C(0xc45d1df942711d9a), UINT64_C(0x3ba5d0bd324f8395)},
+ {UINT64_C(0xf5746577930d6500), UINT64_C(0xca8f44ec7ee3647a)},
+ {UINT64_C(0x9968bf6abbe85f20), UINT64_C(0x7e998b13cf4e1ecc)},
+ {UINT64_C(0xbfc2ef456ae276e8), UINT64_C(0x9e3fedd8c321a67f)},
+ {UINT64_C(0xefb3ab16c59b14a2), UINT64_C(0xc5cfe94ef3ea101f)},
+ {UINT64_C(0x95d04aee3b80ece5), UINT64_C(0xbba1f1d158724a13)},
+ {UINT64_C(0xbb445da9ca61281f), UINT64_C(0x2a8a6e45ae8edc98)},
+ {UINT64_C(0xea1575143cf97226), UINT64_C(0xf52d09d71a3293be)},
+ {UINT64_C(0x924d692ca61be758), UINT64_C(0x593c2626705f9c57)},
+ {UINT64_C(0xb6e0c377cfa2e12e), UINT64_C(0x6f8b2fb00c77836d)},
+ {UINT64_C(0xe498f455c38b997a), UINT64_C(0x0b6dfb9c0f956448)},
+ {UINT64_C(0x8edf98b59a373fec), UINT64_C(0x4724bd4189bd5ead)},
+ {UINT64_C(0xb2977ee300c50fe7), UINT64_C(0x58edec91ec2cb658)},
+ {UINT64_C(0xdf3d5e9bc0f653e1), UINT64_C(0x2f2967b66737e3ee)},
+ {UINT64_C(0x8b865b215899f46c), UINT64_C(0xbd79e0d20082ee75)},
+ {UINT64_C(0xae67f1e9aec07187), UINT64_C(0xecd8590680a3aa12)},
+ {UINT64_C(0xda01ee641a708de9), UINT64_C(0xe80e6f4820cc9496)},
+ {UINT64_C(0x884134fe908658b2), UINT64_C(0x3109058d147fdcde)},
+ {UINT64_C(0xaa51823e34a7eede), UINT64_C(0xbd4b46f0599fd416)},
+ {UINT64_C(0xd4e5e2cdc1d1ea96), UINT64_C(0x6c9e18ac7007c91b)},
+ {UINT64_C(0x850fadc09923329e), UINT64_C(0x03e2cf6bc604ddb1)},
+ {UINT64_C(0xa6539930bf6bff45), UINT64_C(0x84db8346b786151d)},
+ {UINT64_C(0xcfe87f7cef46ff16), UINT64_C(0xe612641865679a64)},
+ {UINT64_C(0x81f14fae158c5f6e), UINT64_C(0x4fcb7e8f3f60c07f)},
+ {UINT64_C(0xa26da3999aef7749), UINT64_C(0xe3be5e330f38f09e)},
+ {UINT64_C(0xcb090c8001ab551c), UINT64_C(0x5cadf5bfd3072cc6)},
+ {UINT64_C(0xfdcb4fa002162a63), UINT64_C(0x73d9732fc7c8f7f7)},
+ {UINT64_C(0x9e9f11c4014dda7e), UINT64_C(0x2867e7fddcdd9afb)},
+ {UINT64_C(0xc646d63501a1511d), UINT64_C(0xb281e1fd541501b9)},
+ {UINT64_C(0xf7d88bc24209a565), UINT64_C(0x1f225a7ca91a4227)},
+ {UINT64_C(0x9ae757596946075f), UINT64_C(0x3375788de9b06959)},
+ {UINT64_C(0xc1a12d2fc3978937), UINT64_C(0x0052d6b1641c83af)},
+ {UINT64_C(0xf209787bb47d6b84), UINT64_C(0xc0678c5dbd23a49b)},
+ {UINT64_C(0x9745eb4d50ce6332), UINT64_C(0xf840b7ba963646e1)},
+ {UINT64_C(0xbd176620a501fbff), UINT64_C(0xb650e5a93bc3d899)},
+ {UINT64_C(0xec5d3fa8ce427aff), UINT64_C(0xa3e51f138ab4cebf)},
+ {UINT64_C(0x93ba47c980e98cdf), UINT64_C(0xc66f336c36b10138)},
+ {UINT64_C(0xb8a8d9bbe123f017), UINT64_C(0xb80b0047445d4185)},
+ {UINT64_C(0xe6d3102ad96cec1d), UINT64_C(0xa60dc059157491e6)},
+ {UINT64_C(0x9043ea1ac7e41392), UINT64_C(0x87c89837ad68db30)},
+ {UINT64_C(0xb454e4a179dd1877), UINT64_C(0x29babe4598c311fc)},
+ {UINT64_C(0xe16a1dc9d8545e94), UINT64_C(0xf4296dd6fef3d67b)},
+ {UINT64_C(0x8ce2529e2734bb1d), UINT64_C(0x1899e4a65f58660d)},
+ {UINT64_C(0xb01ae745b101e9e4), UINT64_C(0x5ec05dcff72e7f90)},
+ {UINT64_C(0xdc21a1171d42645d), UINT64_C(0x76707543f4fa1f74)},
+ {UINT64_C(0x899504ae72497eba), UINT64_C(0x6a06494a791c53a9)},
+ {UINT64_C(0xabfa45da0edbde69), UINT64_C(0x0487db9d17636893)},
+ {UINT64_C(0xd6f8d7509292d603), UINT64_C(0x45a9d2845d3c42b7)},
+ {UINT64_C(0x865b86925b9bc5c2), UINT64_C(0x0b8a2392ba45a9b3)},
+ {UINT64_C(0xa7f26836f282b732), UINT64_C(0x8e6cac7768d7141f)},
+ {UINT64_C(0xd1ef0244af2364ff), UINT64_C(0x3207d795430cd927)},
+ {UINT64_C(0x8335616aed761f1f), UINT64_C(0x7f44e6bd49e807b9)},
+ {UINT64_C(0xa402b9c5a8d3a6e7), UINT64_C(0x5f16206c9c6209a7)},
+ {UINT64_C(0xcd036837130890a1), UINT64_C(0x36dba887c37a8c10)},
+ {UINT64_C(0x802221226be55a64), UINT64_C(0xc2494954da2c978a)},
+ {UINT64_C(0xa02aa96b06deb0fd), UINT64_C(0xf2db9baa10b7bd6d)},
+ {UINT64_C(0xc83553c5c8965d3d), UINT64_C(0x6f92829494e5acc8)},
+ {UINT64_C(0xfa42a8b73abbf48c), UINT64_C(0xcb772339ba1f17fa)},
+ {UINT64_C(0x9c69a97284b578d7), UINT64_C(0xff2a760414536efc)},
+ {UINT64_C(0xc38413cf25e2d70d), UINT64_C(0xfef5138519684abb)},
+ {UINT64_C(0xf46518c2ef5b8cd1), UINT64_C(0x7eb258665fc25d6a)},
+ {UINT64_C(0x98bf2f79d5993802), UINT64_C(0xef2f773ffbd97a62)},
+ {UINT64_C(0xbeeefb584aff8603), UINT64_C(0xaafb550ffacfd8fb)},
+ {UINT64_C(0xeeaaba2e5dbf6784), UINT64_C(0x95ba2a53f983cf39)},
+ {UINT64_C(0x952ab45cfa97a0b2), UINT64_C(0xdd945a747bf26184)},
+ {UINT64_C(0xba756174393d88df), UINT64_C(0x94f971119aeef9e5)},
+ {UINT64_C(0xe912b9d1478ceb17), UINT64_C(0x7a37cd5601aab85e)},
+ {UINT64_C(0x91abb422ccb812ee), UINT64_C(0xac62e055c10ab33b)},
+ {UINT64_C(0xb616a12b7fe617aa), UINT64_C(0x577b986b314d600a)},
+ {UINT64_C(0xe39c49765fdf9d94), UINT64_C(0xed5a7e85fda0b80c)},
+ {UINT64_C(0x8e41ade9fbebc27d), UINT64_C(0x14588f13be847308)},
+ {UINT64_C(0xb1d219647ae6b31c), UINT64_C(0x596eb2d8ae258fc9)},
+ {UINT64_C(0xde469fbd99a05fe3), UINT64_C(0x6fca5f8ed9aef3bc)},
+ {UINT64_C(0x8aec23d680043bee), UINT64_C(0x25de7bb9480d5855)},
+ {UINT64_C(0xada72ccc20054ae9), UINT64_C(0xaf561aa79a10ae6b)},
+ {UINT64_C(0xd910f7ff28069da4), UINT64_C(0x1b2ba1518094da05)},
+ {UINT64_C(0x87aa9aff79042286), UINT64_C(0x90fb44d2f05d0843)},
+ {UINT64_C(0xa99541bf57452b28), UINT64_C(0x353a1607ac744a54)},
+ {UINT64_C(0xd3fa922f2d1675f2), UINT64_C(0x42889b8997915ce9)},
+ {UINT64_C(0x847c9b5d7c2e09b7), UINT64_C(0x69956135febada12)},
+ {UINT64_C(0xa59bc234db398c25), UINT64_C(0x43fab9837e699096)},
+ {UINT64_C(0xcf02b2c21207ef2e), UINT64_C(0x94f967e45e03f4bc)},
+ {UINT64_C(0x8161afb94b44f57d), UINT64_C(0x1d1be0eebac278f6)},
+ {UINT64_C(0xa1ba1ba79e1632dc), UINT64_C(0x6462d92a69731733)},
+ {UINT64_C(0xca28a291859bbf93), UINT64_C(0x7d7b8f7503cfdcff)},
+ {UINT64_C(0xfcb2cb35e702af78), UINT64_C(0x5cda735244c3d43f)},
+ {UINT64_C(0x9defbf01b061adab), UINT64_C(0x3a0888136afa64a8)},
+ {UINT64_C(0xc56baec21c7a1916), UINT64_C(0x088aaa1845b8fdd1)},
+ {UINT64_C(0xf6c69a72a3989f5b), UINT64_C(0x8aad549e57273d46)},
+ {UINT64_C(0x9a3c2087a63f6399), UINT64_C(0x36ac54e2f678864c)},
+ {UINT64_C(0xc0cb28a98fcf3c7f), UINT64_C(0x84576a1bb416a7de)},
+ {UINT64_C(0xf0fdf2d3f3c30b9f), UINT64_C(0x656d44a2a11c51d6)},
+ {UINT64_C(0x969eb7c47859e743), UINT64_C(0x9f644ae5a4b1b326)},
+ {UINT64_C(0xbc4665b596706114), UINT64_C(0x873d5d9f0dde1fef)},
+ {UINT64_C(0xeb57ff22fc0c7959), UINT64_C(0xa90cb506d155a7eb)},
+ {UINT64_C(0x9316ff75dd87cbd8), UINT64_C(0x09a7f12442d588f3)},
+ {UINT64_C(0xb7dcbf5354e9bece), UINT64_C(0x0c11ed6d538aeb30)},
+ {UINT64_C(0xe5d3ef282a242e81), UINT64_C(0x8f1668c8a86da5fb)},
+ {UINT64_C(0x8fa475791a569d10), UINT64_C(0xf96e017d694487bd)},
+ {UINT64_C(0xb38d92d760ec4455), UINT64_C(0x37c981dcc395a9ad)},
+ {UINT64_C(0xe070f78d3927556a), UINT64_C(0x85bbe253f47b1418)},
+ {UINT64_C(0x8c469ab843b89562), UINT64_C(0x93956d7478ccec8f)},
+ {UINT64_C(0xaf58416654a6babb), UINT64_C(0x387ac8d1970027b3)},
+ {UINT64_C(0xdb2e51bfe9d0696a), UINT64_C(0x06997b05fcc0319f)},
+ {UINT64_C(0x88fcf317f22241e2), UINT64_C(0x441fece3bdf81f04)},
+ {UINT64_C(0xab3c2fddeeaad25a), UINT64_C(0xd527e81cad7626c4)},
+ {UINT64_C(0xd60b3bd56a5586f1), UINT64_C(0x8a71e223d8d3b075)},
+ {UINT64_C(0x85c7056562757456), UINT64_C(0xf6872d5667844e4a)},
+ {UINT64_C(0xa738c6bebb12d16c), UINT64_C(0xb428f8ac016561dc)},
+ {UINT64_C(0xd106f86e69d785c7), UINT64_C(0xe13336d701beba53)},
+ {UINT64_C(0x82a45b450226b39c), UINT64_C(0xecc0024661173474)},
+ {UINT64_C(0xa34d721642b06084), UINT64_C(0x27f002d7f95d0191)},
+ {UINT64_C(0xcc20ce9bd35c78a5), UINT64_C(0x31ec038df7b441f5)},
+ {UINT64_C(0xff290242c83396ce), UINT64_C(0x7e67047175a15272)},
+ {UINT64_C(0x9f79a169bd203e41), UINT64_C(0x0f0062c6e984d387)},
+ {UINT64_C(0xc75809c42c684dd1), UINT64_C(0x52c07b78a3e60869)},
+ {UINT64_C(0xf92e0c3537826145), UINT64_C(0xa7709a56ccdf8a83)},
+ {UINT64_C(0x9bbcc7a142b17ccb), UINT64_C(0x88a66076400bb692)},
+ {UINT64_C(0xc2abf989935ddbfe), UINT64_C(0x6acff893d00ea436)},
+ {UINT64_C(0xf356f7ebf83552fe), UINT64_C(0x0583f6b8c4124d44)},
+ {UINT64_C(0x98165af37b2153de), UINT64_C(0xc3727a337a8b704b)},
+ {UINT64_C(0xbe1bf1b059e9a8d6), UINT64_C(0x744f18c0592e4c5d)},
+ {UINT64_C(0xeda2ee1c7064130c), UINT64_C(0x1162def06f79df74)},
+ {UINT64_C(0x9485d4d1c63e8be7), UINT64_C(0x8addcb5645ac2ba9)},
+ {UINT64_C(0xb9a74a0637ce2ee1), UINT64_C(0x6d953e2bd7173693)},
+ {UINT64_C(0xe8111c87c5c1ba99), UINT64_C(0xc8fa8db6ccdd0438)},
+ {UINT64_C(0x910ab1d4db9914a0), UINT64_C(0x1d9c9892400a22a3)},
+ {UINT64_C(0xb54d5e4a127f59c8), UINT64_C(0x2503beb6d00cab4c)},
+ {UINT64_C(0xe2a0b5dc971f303a), UINT64_C(0x2e44ae64840fd61e)},
+ {UINT64_C(0x8da471a9de737e24), UINT64_C(0x5ceaecfed289e5d3)},
+ {UINT64_C(0xb10d8e1456105dad), UINT64_C(0x7425a83e872c5f48)},
+ {UINT64_C(0xdd50f1996b947518), UINT64_C(0xd12f124e28f7771a)},
+ {UINT64_C(0x8a5296ffe33cc92f), UINT64_C(0x82bd6b70d99aaa70)},
+ {UINT64_C(0xace73cbfdc0bfb7b), UINT64_C(0x636cc64d1001550c)},
+ {UINT64_C(0xd8210befd30efa5a), UINT64_C(0x3c47f7e05401aa4f)},
+ {UINT64_C(0x8714a775e3e95c78), UINT64_C(0x65acfaec34810a72)},
+ {UINT64_C(0xa8d9d1535ce3b396), UINT64_C(0x7f1839a741a14d0e)},
+ {UINT64_C(0xd31045a8341ca07c), UINT64_C(0x1ede48111209a051)},
+ {UINT64_C(0x83ea2b892091e44d), UINT64_C(0x934aed0aab460433)},
+ {UINT64_C(0xa4e4b66b68b65d60), UINT64_C(0xf81da84d56178540)},
+ {UINT64_C(0xce1de40642e3f4b9), UINT64_C(0x36251260ab9d668f)},
+ {UINT64_C(0x80d2ae83e9ce78f3), UINT64_C(0xc1d72b7c6b42601a)},
+ {UINT64_C(0xa1075a24e4421730), UINT64_C(0xb24cf65b8612f820)},
+ {UINT64_C(0xc94930ae1d529cfc), UINT64_C(0xdee033f26797b628)},
+ {UINT64_C(0xfb9b7cd9a4a7443c), UINT64_C(0x169840ef017da3b2)},
+ {UINT64_C(0x9d412e0806e88aa5), UINT64_C(0x8e1f289560ee864f)},
+ {UINT64_C(0xc491798a08a2ad4e), UINT64_C(0xf1a6f2bab92a27e3)},
+ {UINT64_C(0xf5b5d7ec8acb58a2), UINT64_C(0xae10af696774b1dc)},
+ {UINT64_C(0x9991a6f3d6bf1765), UINT64_C(0xacca6da1e0a8ef2a)},
+ {UINT64_C(0xbff610b0cc6edd3f), UINT64_C(0x17fd090a58d32af4)},
+ {UINT64_C(0xeff394dcff8a948e), UINT64_C(0xddfc4b4cef07f5b1)},
+ {UINT64_C(0x95f83d0a1fb69cd9), UINT64_C(0x4abdaf101564f98f)},
+ {UINT64_C(0xbb764c4ca7a4440f), UINT64_C(0x9d6d1ad41abe37f2)},
+ {UINT64_C(0xea53df5fd18d5513), UINT64_C(0x84c86189216dc5ee)},
+ {UINT64_C(0x92746b9be2f8552c), UINT64_C(0x32fd3cf5b4e49bb5)},
+ {UINT64_C(0xb7118682dbb66a77), UINT64_C(0x3fbc8c33221dc2a2)},
+ {UINT64_C(0xe4d5e82392a40515), UINT64_C(0x0fabaf3feaa5334b)},
+ {UINT64_C(0x8f05b1163ba6832d), UINT64_C(0x29cb4d87f2a7400f)},
+ {UINT64_C(0xb2c71d5bca9023f8), UINT64_C(0x743e20e9ef511013)},
+ {UINT64_C(0xdf78e4b2bd342cf6), UINT64_C(0x914da9246b255417)},
+ {UINT64_C(0x8bab8eefb6409c1a), UINT64_C(0x1ad089b6c2f7548f)},
+ {UINT64_C(0xae9672aba3d0c320), UINT64_C(0xa184ac2473b529b2)},
+ {UINT64_C(0xda3c0f568cc4f3e8), UINT64_C(0xc9e5d72d90a2741f)},
+ {UINT64_C(0x8865899617fb1871), UINT64_C(0x7e2fa67c7a658893)},
+ {UINT64_C(0xaa7eebfb9df9de8d), UINT64_C(0xddbb901b98feeab8)},
+ {UINT64_C(0xd51ea6fa85785631), UINT64_C(0x552a74227f3ea566)},
+ {UINT64_C(0x8533285c936b35de), UINT64_C(0xd53a88958f872760)},
+ {UINT64_C(0xa67ff273b8460356), UINT64_C(0x8a892abaf368f138)},
+ {UINT64_C(0xd01fef10a657842c), UINT64_C(0x2d2b7569b0432d86)},
+ {UINT64_C(0x8213f56a67f6b29b), UINT64_C(0x9c3b29620e29fc74)},
+ {UINT64_C(0xa298f2c501f45f42), UINT64_C(0x8349f3ba91b47b90)},
+ {UINT64_C(0xcb3f2f7642717713), UINT64_C(0x241c70a936219a74)},
+ {UINT64_C(0xfe0efb53d30dd4d7), UINT64_C(0xed238cd383aa0111)},
+ {UINT64_C(0x9ec95d1463e8a506), UINT64_C(0xf4363804324a40ab)},
+ {UINT64_C(0xc67bb4597ce2ce48), UINT64_C(0xb143c6053edcd0d6)},
+ {UINT64_C(0xf81aa16fdc1b81da), UINT64_C(0xdd94b7868e94050b)},
+ {UINT64_C(0x9b10a4e5e9913128), UINT64_C(0xca7cf2b4191c8327)},
+ {UINT64_C(0xc1d4ce1f63f57d72), UINT64_C(0xfd1c2f611f63a3f1)},
+ {UINT64_C(0xf24a01a73cf2dccf), UINT64_C(0xbc633b39673c8ced)},
+ {UINT64_C(0x976e41088617ca01), UINT64_C(0xd5be0503e085d814)},
+ {UINT64_C(0xbd49d14aa79dbc82), UINT64_C(0x4b2d8644d8a74e19)},
+ {UINT64_C(0xec9c459d51852ba2), UINT64_C(0xddf8e7d60ed1219f)},
+ {UINT64_C(0x93e1ab8252f33b45), UINT64_C(0xcabb90e5c942b504)},
+ {UINT64_C(0xb8da1662e7b00a17), UINT64_C(0x3d6a751f3b936244)},
+ {UINT64_C(0xe7109bfba19c0c9d), UINT64_C(0x0cc512670a783ad5)},
+ {UINT64_C(0x906a617d450187e2), UINT64_C(0x27fb2b80668b24c6)},
+ {UINT64_C(0xb484f9dc9641e9da), UINT64_C(0xb1f9f660802dedf7)},
+ {UINT64_C(0xe1a63853bbd26451), UINT64_C(0x5e7873f8a0396974)},
+ {UINT64_C(0x8d07e33455637eb2), UINT64_C(0xdb0b487b6423e1e9)},
+ {UINT64_C(0xb049dc016abc5e5f), UINT64_C(0x91ce1a9a3d2cda63)},
+ {UINT64_C(0xdc5c5301c56b75f7), UINT64_C(0x7641a140cc7810fc)},
+ {UINT64_C(0x89b9b3e11b6329ba), UINT64_C(0xa9e904c87fcb0a9e)},
+ {UINT64_C(0xac2820d9623bf429), UINT64_C(0x546345fa9fbdcd45)},
+ {UINT64_C(0xd732290fbacaf133), UINT64_C(0xa97c177947ad4096)},
+ {UINT64_C(0x867f59a9d4bed6c0), UINT64_C(0x49ed8eabcccc485e)},
+ {UINT64_C(0xa81f301449ee8c70), UINT64_C(0x5c68f256bfff5a75)},
+ {UINT64_C(0xd226fc195c6a2f8c), UINT64_C(0x73832eec6fff3112)},
+ {UINT64_C(0x83585d8fd9c25db7), UINT64_C(0xc831fd53c5ff7eac)},
+ {UINT64_C(0xa42e74f3d032f525), UINT64_C(0xba3e7ca8b77f5e56)},
+ {UINT64_C(0xcd3a1230c43fb26f), UINT64_C(0x28ce1bd2e55f35ec)},
+ {UINT64_C(0x80444b5e7aa7cf85), UINT64_C(0x7980d163cf5b81b4)},
+ {UINT64_C(0xa0555e361951c366), UINT64_C(0xd7e105bcc3326220)},
+ {UINT64_C(0xc86ab5c39fa63440), UINT64_C(0x8dd9472bf3fefaa8)},
+ {UINT64_C(0xfa856334878fc150), UINT64_C(0xb14f98f6f0feb952)},
+ {UINT64_C(0x9c935e00d4b9d8d2), UINT64_C(0x6ed1bf9a569f33d4)},
+ {UINT64_C(0xc3b8358109e84f07), UINT64_C(0x0a862f80ec4700c9)},
+ {UINT64_C(0xf4a642e14c6262c8), UINT64_C(0xcd27bb612758c0fb)},
+ {UINT64_C(0x98e7e9cccfbd7dbd), UINT64_C(0x8038d51cb897789d)},
+ {UINT64_C(0xbf21e44003acdd2c), UINT64_C(0xe0470a63e6bd56c4)},
+ {UINT64_C(0xeeea5d5004981478), UINT64_C(0x1858ccfce06cac75)},
+ {UINT64_C(0x95527a5202df0ccb), UINT64_C(0x0f37801e0c43ebc9)},
+ {UINT64_C(0xbaa718e68396cffd), UINT64_C(0xd30560258f54e6bb)},
+ {UINT64_C(0xe950df20247c83fd), UINT64_C(0x47c6b82ef32a206a)},
+ {UINT64_C(0x91d28b7416cdd27e), UINT64_C(0x4cdc331d57fa5442)},
+ {UINT64_C(0xb6472e511c81471d), UINT64_C(0xe0133fe4adf8e953)},
+ {UINT64_C(0xe3d8f9e563a198e5), UINT64_C(0x58180fddd97723a7)},
+ {UINT64_C(0x8e679c2f5e44ff8f), UINT64_C(0x570f09eaa7ea7649)},
+ {UINT64_C(0xb201833b35d63f73), UINT64_C(0x2cd2cc6551e513db)},
+ {UINT64_C(0xde81e40a034bcf4f), UINT64_C(0xf8077f7ea65e58d2)},
+ {UINT64_C(0x8b112e86420f6191), UINT64_C(0xfb04afaf27faf783)},
+ {UINT64_C(0xadd57a27d29339f6), UINT64_C(0x79c5db9af1f9b564)},
+ {UINT64_C(0xd94ad8b1c7380874), UINT64_C(0x18375281ae7822bd)},
+ {UINT64_C(0x87cec76f1c830548), UINT64_C(0x8f2293910d0b15b6)},
+ {UINT64_C(0xa9c2794ae3a3c69a), UINT64_C(0xb2eb3875504ddb23)},
+ {UINT64_C(0xd433179d9c8cb841), UINT64_C(0x5fa60692a46151ec)},
+ {UINT64_C(0x849feec281d7f328), UINT64_C(0xdbc7c41ba6bcd334)},
+ {UINT64_C(0xa5c7ea73224deff3), UINT64_C(0x12b9b522906c0801)},
+ {UINT64_C(0xcf39e50feae16bef), UINT64_C(0xd768226b34870a01)},
+ {UINT64_C(0x81842f29f2cce375), UINT64_C(0xe6a1158300d46641)},
+ {UINT64_C(0xa1e53af46f801c53), UINT64_C(0x60495ae3c1097fd1)},
+ {UINT64_C(0xca5e89b18b602368), UINT64_C(0x385bb19cb14bdfc5)},
+ {UINT64_C(0xfcf62c1dee382c42), UINT64_C(0x46729e03dd9ed7b6)},
+ {UINT64_C(0x9e19db92b4e31ba9), UINT64_C(0x6c07a2c26a8346d2)},
+ {UINT64_C(0xc5a05277621be293), UINT64_C(0xc7098b7305241886)},
+ {UINT64_C(0xf70867153aa2db38), UINT64_C(0xb8cbee4fc66d1ea8)}}};
+ };
+#if !JKJ_HAS_INLINE_VARIABLE
+ // decltype(...) should not depend on Dummy; see
+ // https://stackoverflow.com/questions/76438400/decltype-on-static-variable-in-template-class.
+ template <class Dummy>
+ constexpr decltype(cache_holder<ieee754_binary64>::cache)
+ cache_holder<ieee754_binary64, Dummy>::cache;
+#endif
+
+ // Compressed cache.
+ template <class FloatFormat, class Dummy = void>
+ struct compressed_cache_holder {
+ using cache_entry_type = typename cache_holder<FloatFormat>::cache_entry_type;
+ static constexpr int cache_bits = cache_holder<FloatFormat>::cache_bits;
+ static constexpr int min_k = cache_holder<FloatFormat>::min_k;
+ static constexpr int max_k = cache_holder<FloatFormat>::max_k;
+
+ template <class ShiftAmountType, class DecimalExponentType>
+ static constexpr cache_entry_type get_cache(DecimalExponentType k) noexcept {
+ return cache_holder<FloatFormat>::cache[k - min_k];
+ }
+ };
+
+ template <class Dummy>
+ struct compressed_cache_holder<ieee754_binary32, Dummy> {
+ using cache_entry_type = cache_holder<ieee754_binary32>::cache_entry_type;
+ static constexpr int cache_bits = cache_holder<ieee754_binary32>::cache_bits;
+ static constexpr int min_k = cache_holder<ieee754_binary32>::min_k;
+ static constexpr int max_k = cache_holder<ieee754_binary32>::max_k;
+ static constexpr int compression_ratio = 13;
+ static constexpr detail::stdr::size_t compressed_table_size =
+ detail::stdr::size_t((max_k - min_k + compression_ratio) / compression_ratio);
+ static constexpr detail::stdr::size_t pow5_table_size =
+ detail::stdr::size_t((compression_ratio + 1) / 2);
+
+ using cache_holder_t = detail::array<cache_entry_type, compressed_table_size>;
+ using pow5_holder_t = detail::array<detail::stdr::uint_least16_t, pow5_table_size>;
+
+#if JKJ_HAS_CONSTEXPR17
+ static constexpr cache_holder_t cache JKJ_STATIC_DATA_SECTION = [] {
+ cache_holder_t res{};
+ for (detail::stdr::size_t i = 0; i < compressed_table_size; ++i) {
+ res[i] = cache_holder<ieee754_binary32>::cache[i * compression_ratio];
+ }
+ return res;
+ }();
+ static constexpr pow5_holder_t pow5_table JKJ_STATIC_DATA_SECTION = [] {
+ pow5_holder_t res{};
+ detail::stdr::uint_least16_t p = 1;
+ for (detail::stdr::size_t i = 0; i < pow5_table_size; ++i) {
+ res[i] = p;
+ p *= 5;
+ }
+ return res;
+ }();
+#else
+ template <detail::stdr::size_t... indices>
+ static constexpr cache_holder_t make_cache(detail::index_sequence<indices...>) {
+ return {cache_holder<ieee754_binary32>::cache[indices * compression_ratio]...};
+ }
+ static constexpr cache_holder_t cache JKJ_STATIC_DATA_SECTION =
+ make_cache(detail::make_index_sequence<compressed_table_size>{});
+
+ template <detail::stdr::size_t... indices>
+ static constexpr pow5_holder_t make_pow5_table(detail::index_sequence<indices...>) {
+ return {detail::compute_power<indices>(detail::stdr::uint_least16_t(5))...};
+ }
+ static constexpr pow5_holder_t pow5_table JKJ_STATIC_DATA_SECTION =
+ make_pow5_table(detail::make_index_sequence<pow5_table_size>{});
+#endif
+
+ template <class ShiftAmountType, class DecimalExponentType>
+ static JKJ_CONSTEXPR20 cache_entry_type get_cache(DecimalExponentType k) noexcept {
+ // Compute the base index.
+ // Supposed to compute (k - min_k) / compression_ratio.
+ static_assert(max_k - min_k <= 89 && compression_ratio == 13, "");
+ static_assert(max_k - min_k <= detail::stdr::numeric_limits<DecimalExponentType>::max(),
+ "");
+ auto const cache_index =
+ DecimalExponentType(detail::stdr::uint_fast16_t(DecimalExponentType(k - min_k) *
+ detail::stdr::int_fast16_t(79)) >>
+ 10);
+ auto const kb = DecimalExponentType(cache_index * compression_ratio + min_k);
+ auto const offset = DecimalExponentType(k - kb);
+
+ // Get the base cache.
+ auto const base_cache = cache[cache_index];
+
+ if (offset == 0) {
+ return base_cache;
+ }
+ else {
+ // Compute the required amount of bit-shift.
+ auto const alpha =
+ ShiftAmountType(detail::log::floor_log2_pow10<min_k, max_k>(k) -
+ detail::log::floor_log2_pow10<min_k, max_k>(kb) - offset);
+ assert(alpha > 0 && alpha < 64);
+
+ // Try to recover the real cache.
+ auto const pow5 =
+ offset >= 7
+ ? detail::stdr::uint_fast32_t(detail::stdr::uint_fast32_t(pow5_table[6]) *
+ pow5_table[offset - 6])
+ : detail::stdr::uint_fast32_t(pow5_table[offset]);
+ auto mul_result = detail::wuint::umul128(base_cache, pow5);
+ auto const recovered_cache =
+ cache_entry_type((((mul_result.high() << ShiftAmountType(64 - alpha)) |
+ (mul_result.low() >> alpha)) +
+ 1) &
+ UINT64_C(0xffffffffffffffff));
+ assert(recovered_cache != 0);
+
+ return recovered_cache;
+ }
+ }
+ };
+#if !JKJ_HAS_INLINE_VARIABLE
+ template <class Dummy>
+ constexpr typename compressed_cache_holder<ieee754_binary32, Dummy>::cache_holder_t
+ compressed_cache_holder<ieee754_binary32, Dummy>::cache;
+ template <class Dummy>
+ constexpr typename compressed_cache_holder<ieee754_binary32, Dummy>::pow5_holder_t
+ compressed_cache_holder<ieee754_binary32, Dummy>::pow5_table;
+#endif
+
+ template <class Dummy>
+ struct compressed_cache_holder<ieee754_binary64, Dummy> {
+ using cache_entry_type = cache_holder<ieee754_binary64>::cache_entry_type;
+ static constexpr int cache_bits = cache_holder<ieee754_binary64>::cache_bits;
+ static constexpr int min_k = cache_holder<ieee754_binary64>::min_k;
+ static constexpr int max_k = cache_holder<ieee754_binary64>::max_k;
+ static constexpr int compression_ratio = 27;
+ static constexpr detail::stdr::size_t compressed_table_size =
+ detail::stdr::size_t((max_k - min_k + compression_ratio) / compression_ratio);
+ static constexpr detail::stdr::size_t pow5_table_size =
+ detail::stdr::size_t(compression_ratio);
+
+ using cache_holder_t = detail::array<cache_entry_type, compressed_table_size>;
+ using pow5_holder_t = detail::array<detail::stdr::uint_least64_t, pow5_table_size>;
+
+#if JKJ_HAS_CONSTEXPR17
+ static constexpr cache_holder_t cache JKJ_STATIC_DATA_SECTION = [] {
+ cache_holder_t res{};
+ for (detail::stdr::size_t i = 0; i < compressed_table_size; ++i) {
+ res[i] = cache_holder<ieee754_binary64>::cache[i * compression_ratio];
+ }
+ return res;
+ }();
+ static constexpr pow5_holder_t pow5_table JKJ_STATIC_DATA_SECTION = [] {
+ pow5_holder_t res{};
+ detail::stdr::uint_least64_t p = 1;
+ for (detail::stdr::size_t i = 0; i < pow5_table_size; ++i) {
+ res[i] = p;
+ p *= 5;
+ }
+ return res;
+ }();
+#else
+ template <detail::stdr::size_t... indices>
+ static constexpr cache_holder_t make_cache(detail::index_sequence<indices...>) {
+ return {cache_holder<ieee754_binary64>::cache[indices * compression_ratio]...};
+ }
+ static constexpr cache_holder_t cache JKJ_STATIC_DATA_SECTION =
+ make_cache(detail::make_index_sequence<compressed_table_size>{});
+
+ template <detail::stdr::size_t... indices>
+ static constexpr pow5_holder_t make_pow5_table(detail::index_sequence<indices...>) {
+ return {detail::compute_power<indices>(detail::stdr::uint_least64_t(5))...};
+ }
+ static constexpr pow5_holder_t pow5_table JKJ_STATIC_DATA_SECTION =
+ make_pow5_table(detail::make_index_sequence<pow5_table_size>{});
+#endif
+
+ template <class ShiftAmountType, class DecimalExponentType>
+ static JKJ_CONSTEXPR20 cache_entry_type get_cache(DecimalExponentType k) noexcept {
+ // Compute the base index.
+ // Supposed to compute (k - min_k) / compression_ratio.
+ static_assert(max_k - min_k <= 619 && compression_ratio == 27, "");
+ static_assert(max_k - min_k <= detail::stdr::numeric_limits<DecimalExponentType>::max(),
+ "");
+ auto const cache_index =
+ DecimalExponentType(detail::stdr::uint_fast32_t(DecimalExponentType(k - min_k) *
+ detail::stdr::int_fast32_t(607)) >>
+ 14);
+ auto const kb = DecimalExponentType(cache_index * compression_ratio + min_k);
+ auto const offset = DecimalExponentType(k - kb);
+
+ // Get the base cache.
+ auto const base_cache = cache[cache_index];
+
+ if (offset == 0) {
+ return base_cache;
+ }
+ else {
+ // Compute the required amount of bit-shift.
+ auto const alpha =
+ ShiftAmountType(detail::log::floor_log2_pow10<min_k, max_k>(k) -
+ detail::log::floor_log2_pow10<min_k, max_k>(kb) - offset);
+ assert(alpha > 0 && alpha < 64);
+
+ // Try to recover the real cache.
+ auto const pow5 = pow5_table[offset];
+ auto recovered_cache = detail::wuint::umul128(base_cache.high(), pow5);
+ auto const middle_low = detail::wuint::umul128(base_cache.low(), pow5);
+
+ recovered_cache += middle_low.high();
+
+ auto const high_to_middle = detail::stdr::uint_least64_t(
+ (recovered_cache.high() << ShiftAmountType(64 - alpha)) &
+ UINT64_C(0xffffffffffffffff));
+ auto const middle_to_low = detail::stdr::uint_least64_t(
+ (recovered_cache.low() << ShiftAmountType(64 - alpha)) &
+ UINT64_C(0xffffffffffffffff));
+
+ recovered_cache = {(recovered_cache.low() >> alpha) | high_to_middle,
+ ((middle_low.low() >> alpha) | middle_to_low)};
+
+ assert(recovered_cache.low() != UINT64_C(0xffffffffffffffff));
+ recovered_cache = {recovered_cache.high(),
+ detail::stdr::uint_least64_t(recovered_cache.low() + 1)};
+
+ return recovered_cache;
+ }
+ }
+ };
+#if !JKJ_HAS_INLINE_VARIABLE
+ template <class Dummy>
+ constexpr typename compressed_cache_holder<ieee754_binary64, Dummy>::cache_holder_t
+ compressed_cache_holder<ieee754_binary64, Dummy>::cache;
+ template <class Dummy>
+ constexpr typename compressed_cache_holder<ieee754_binary64, Dummy>::pow5_holder_t
+ compressed_cache_holder<ieee754_binary64, Dummy>::pow5_table;
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Forward declarations of user-specializable templates used in the main algorithm.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ // Remove trailing zeros from significand and add the number of removed zeros into
+ // exponent.
+ template <class TrailingZeroPolicy, class Format, class DecimalSignificand,
+ class DecimalExponentType>
+ struct remove_trailing_zeros_traits;
+
+ // Users can specialize this traits class to make Dragonbox work with their own formats.
+ // However, this requires detailed knowledge on how the algorithm works, so it is recommended to
+ // read through the paper.
+ template <class FormatTraits, class CacheEntryType, detail::stdr::size_t cache_bits_>
+ struct multiplication_traits;
+
+ // A collection of some common definitions to reduce boilerplate.
+ template <class FormatTraits, class CacheEntryType, detail::stdr::size_t cache_bits_>
+ struct multiplication_traits_base {
+ using format = typename FormatTraits::format;
+ static constexpr int significand_bits = format::significand_bits;
+ static constexpr int total_bits = format::total_bits;
+ using carrier_uint = typename FormatTraits::carrier_uint;
+ using cache_entry_type = CacheEntryType;
+ static constexpr int cache_bits = int(cache_bits_);
+
+ struct compute_mul_result {
+ carrier_uint integer_part;
+ bool is_integer;
+ };
+ struct compute_mul_parity_result {
+ bool parity;
+ bool is_integer;
+ };
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Policies.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ namespace detail {
+ template <class T>
+ struct dummy {};
+ }
+
+ namespace policy {
+ namespace sign {
+ JKJ_INLINE_VARIABLE struct ignore_t {
+ using sign_policy = ignore_t;
+ static constexpr bool return_has_sign = false;
+
+#if defined(_MSC_VER) && !defined(__clang__)
+ // See
+ // https://developercommunity.visualstudio.com/t/Failure-to-optimize-intrinsics/10628226
+ template <class SignedSignificandBits, class DecimalSignificand,
+ class DecimalExponentType>
+ static constexpr decimal_fp<DecimalSignificand, DecimalExponentType, false, false>
+ handle_sign(
+ SignedSignificandBits,
+ decimal_fp<DecimalSignificand, DecimalExponentType, false, false> r) noexcept {
+ return {r.significand, r.exponent};
+ }
+ template <class SignedSignificandBits, class DecimalSignificand,
+ class DecimalExponentType>
+ static constexpr decimal_fp<DecimalSignificand, DecimalExponentType, false, true>
+ handle_sign(
+ SignedSignificandBits,
+ decimal_fp<DecimalSignificand, DecimalExponentType, false, true> r) noexcept {
+ return {r.significand, r.exponent, r.may_have_trailing_zeros};
+ }
+#else
+ template <class SignedSignificandBits, class UnsignedDecimalFp>
+ static constexpr UnsignedDecimalFp handle_sign(SignedSignificandBits,
+ UnsignedDecimalFp r) noexcept {
+ return r;
+ }
+#endif
+ } ignore = {};
+
+ JKJ_INLINE_VARIABLE struct return_sign_t {
+ using sign_policy = return_sign_t;
+ static constexpr bool return_has_sign = true;
+
+ template <class SignedSignificandBits, class UnsignedDecimalFp>
+ static constexpr detail::unsigned_decimal_fp_to_signed_t<UnsignedDecimalFp>
+ handle_sign(SignedSignificandBits s, UnsignedDecimalFp r) noexcept {
+ return add_sign_to_unsigned_decimal_fp(s.is_negative(), r);
+ }
+ } return_sign = {};
+ }
+
+ namespace trailing_zero {
+ JKJ_INLINE_VARIABLE struct ignore_t {
+ using trailing_zero_policy = ignore_t;
+ static constexpr bool report_trailing_zeros = false;
+
+ template <class Format, class DecimalSignificand, class DecimalExponentType>
+ static constexpr unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, false>
+ on_trailing_zeros(DecimalSignificand significand,
+ DecimalExponentType exponent) noexcept {
+ return {significand, exponent};
+ }
+
+ template <class Format, class DecimalSignificand, class DecimalExponentType>
+ static constexpr unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, false>
+ no_trailing_zeros(DecimalSignificand significand,
+ DecimalExponentType exponent) noexcept {
+ return {significand, exponent};
+ }
+ } ignore = {};
+
+ JKJ_INLINE_VARIABLE struct remove_t {
+ using trailing_zero_policy = remove_t;
+ static constexpr bool report_trailing_zeros = false;
+
+ template <class Format, class DecimalSignificand, class DecimalExponentType>
+ JKJ_FORCEINLINE static JKJ_CONSTEXPR14
+ unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, false>
+ on_trailing_zeros(DecimalSignificand significand,
+ DecimalExponentType exponent) noexcept {
+ remove_trailing_zeros_traits<
+ remove_t, Format, DecimalSignificand,
+ DecimalExponentType>::remove_trailing_zeros(significand, exponent);
+ return {significand, exponent};
+ }
+
+ template <class Format, class DecimalSignificand, class DecimalExponentType>
+ static constexpr unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, false>
+ no_trailing_zeros(DecimalSignificand significand,
+ DecimalExponentType exponent) noexcept {
+ return {significand, exponent};
+ }
+ } remove = {};
+
+ JKJ_INLINE_VARIABLE struct remove_compact_t {
+ using trailing_zero_policy = remove_compact_t;
+ static constexpr bool report_trailing_zeros = false;
+
+ template <class Format, class DecimalSignificand, class DecimalExponentType>
+ JKJ_FORCEINLINE static JKJ_CONSTEXPR14
+ unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, false>
+ on_trailing_zeros(DecimalSignificand significand,
+ DecimalExponentType exponent) noexcept {
+ remove_trailing_zeros_traits<
+ remove_compact_t, Format, DecimalSignificand,
+ DecimalExponentType>::remove_trailing_zeros(significand, exponent);
+ return {significand, exponent};
+ }
+
+ template <class Format, class DecimalSignificand, class DecimalExponentType>
+ static constexpr unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, false>
+ no_trailing_zeros(DecimalSignificand significand,
+ DecimalExponentType exponent) noexcept {
+ return {significand, exponent};
+ }
+ } remove_compact = {};
+
+ JKJ_INLINE_VARIABLE struct report_t {
+ using trailing_zero_policy = report_t;
+ static constexpr bool report_trailing_zeros = true;
+
+ template <class Format, class DecimalSignificand, class DecimalExponentType>
+ static constexpr unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, true>
+ on_trailing_zeros(DecimalSignificand significand,
+ DecimalExponentType exponent) noexcept {
+ return {significand, exponent, true};
+ }
+
+ template <class Format, class DecimalSignificand, class DecimalExponentType>
+ static constexpr unsigned_decimal_fp<DecimalSignificand, DecimalExponentType, true>
+ no_trailing_zeros(DecimalSignificand significand,
+ DecimalExponentType exponent) noexcept {
+ return {significand, exponent, false};
+ }
+ } report = {};
+ }
+
+ namespace decimal_to_binary_rounding {
+ enum class tag_t { to_nearest, left_closed_directed, right_closed_directed };
+
+ namespace interval_type {
+ struct symmetric_boundary {
+ static constexpr bool is_symmetric = true;
+ bool is_closed;
+ constexpr bool include_left_endpoint() const noexcept { return is_closed; }
+ constexpr bool include_right_endpoint() const noexcept { return is_closed; }
+ };
+ struct asymmetric_boundary {
+ static constexpr bool is_symmetric = false;
+ bool is_left_closed;
+ constexpr bool include_left_endpoint() const noexcept { return is_left_closed; }
+ constexpr bool include_right_endpoint() const noexcept {
+ return !is_left_closed;
+ }
+ };
+ struct closed {
+ static constexpr bool is_symmetric = true;
+ static constexpr bool include_left_endpoint() noexcept { return true; }
+ static constexpr bool include_right_endpoint() noexcept { return true; }
+ };
+ struct open {
+ static constexpr bool is_symmetric = true;
+ static constexpr bool include_left_endpoint() noexcept { return false; }
+ static constexpr bool include_right_endpoint() noexcept { return false; }
+ };
+ struct left_closed_right_open {
+ static constexpr bool is_symmetric = false;
+ static constexpr bool include_left_endpoint() noexcept { return true; }
+ static constexpr bool include_right_endpoint() noexcept { return false; }
+ };
+ struct right_closed_left_open {
+ static constexpr bool is_symmetric = false;
+ static constexpr bool include_left_endpoint() noexcept { return false; }
+ static constexpr bool include_right_endpoint() noexcept { return true; }
+ };
+ }
+
+ JKJ_INLINE_VARIABLE struct nearest_to_even_t {
+ using decimal_to_binary_rounding_policy = nearest_to_even_t;
+ using interval_type_provider = nearest_to_even_t;
+ static constexpr auto tag = tag_t::to_nearest;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
+ dragonbox::detail::declval<nearest_to_even_t>(), Args{}...))
+ delegate(SignedSignificandBits, Func f, Args... args) noexcept {
+ return f(nearest_to_even_t{}, args...);
+ }
+
+ template <class SignedSignificandBits>
+ static constexpr interval_type::symmetric_boundary
+ normal_interval(SignedSignificandBits s) noexcept {
+ return {s.has_even_significand_bits()};
+ }
+
+ template <class SignedSignificandBits>
+ static constexpr interval_type::closed
+ shorter_interval(SignedSignificandBits) noexcept {
+ return {};
+ }
+ } nearest_to_even = {};
+
+ JKJ_INLINE_VARIABLE struct nearest_to_odd_t {
+ using decimal_to_binary_rounding_policy = nearest_to_odd_t;
+ using interval_type_provider = nearest_to_odd_t;
+ static constexpr auto tag = tag_t::to_nearest;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
+ dragonbox::detail::declval<nearest_to_odd_t>(), Args{}...))
+ delegate(SignedSignificandBits, Func f, Args... args) noexcept {
+ return f(nearest_to_odd_t{}, args...);
+ }
+
+ template <class SignedSignificandBits>
+ static constexpr interval_type::symmetric_boundary
+ normal_interval(SignedSignificandBits s) noexcept {
+ return {!s.has_even_significand_bits()};
+ }
+ template <class SignedSignificandBits>
+ static constexpr interval_type::open
+ shorter_interval(SignedSignificandBits) noexcept {
+ return {};
+ }
+ } nearest_to_odd = {};
+
+ JKJ_INLINE_VARIABLE struct nearest_toward_plus_infinity_t {
+ using decimal_to_binary_rounding_policy = nearest_toward_plus_infinity_t;
+ using interval_type_provider = nearest_toward_plus_infinity_t;
+ static constexpr auto tag = tag_t::to_nearest;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
+ dragonbox::detail::declval<nearest_toward_plus_infinity_t>(), Args{}...))
+ delegate(SignedSignificandBits, Func f, Args... args) noexcept {
+ return f(nearest_toward_plus_infinity_t{}, args...);
+ }
+
+ template <class SignedSignificandBits>
+ static constexpr interval_type::asymmetric_boundary
+ normal_interval(SignedSignificandBits s) noexcept {
+ return {!s.is_negative()};
+ }
+ template <class SignedSignificandBits>
+ static constexpr interval_type::asymmetric_boundary
+ shorter_interval(SignedSignificandBits s) noexcept {
+ return {!s.is_negative()};
+ }
+ } nearest_toward_plus_infinity = {};
+
+ JKJ_INLINE_VARIABLE struct nearest_toward_minus_infinity_t {
+ using decimal_to_binary_rounding_policy = nearest_toward_minus_infinity_t;
+ using interval_type_provider = nearest_toward_minus_infinity_t;
+ static constexpr auto tag = tag_t::to_nearest;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
+ dragonbox::detail::declval<nearest_toward_minus_infinity_t>(), Args{}...))
+ delegate(SignedSignificandBits, Func f, Args... args) noexcept {
+ return f(nearest_toward_minus_infinity_t{}, args...);
+ }
+
+ template <class SignedSignificandBits>
+ static constexpr interval_type::asymmetric_boundary
+ normal_interval(SignedSignificandBits s) noexcept {
+ return {s.is_negative()};
+ }
+ template <class SignedSignificandBits>
+ static constexpr interval_type::asymmetric_boundary
+ shorter_interval(SignedSignificandBits s) noexcept {
+ return {s.is_negative()};
+ }
+ } nearest_toward_minus_infinity = {};
+
+ JKJ_INLINE_VARIABLE struct nearest_toward_zero_t {
+ using decimal_to_binary_rounding_policy = nearest_toward_zero_t;
+ using interval_type_provider = nearest_toward_zero_t;
+ static constexpr auto tag = tag_t::to_nearest;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
+ dragonbox::detail::declval<nearest_toward_zero_t>(), Args{}...))
+ delegate(SignedSignificandBits, Func f, Args... args) noexcept {
+ return f(nearest_toward_zero_t{}, args...);
+ }
+
+ template <class SignedSignificandBits>
+ static constexpr interval_type::right_closed_left_open
+ normal_interval(SignedSignificandBits) noexcept {
+ return {};
+ }
+ template <class SignedSignificandBits>
+ static constexpr interval_type::right_closed_left_open
+ shorter_interval(SignedSignificandBits) noexcept {
+ return {};
+ }
+ } nearest_toward_zero = {};
+
+ JKJ_INLINE_VARIABLE struct nearest_away_from_zero_t {
+ using decimal_to_binary_rounding_policy = nearest_away_from_zero_t;
+ using interval_type_provider = nearest_away_from_zero_t;
+ static constexpr auto tag = tag_t::to_nearest;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
+ dragonbox::detail::declval<nearest_away_from_zero_t>(), Args{}...))
+ delegate(SignedSignificandBits, Func f, Args... args) noexcept {
+ return f(nearest_away_from_zero_t{}, args...);
+ }
+
+ template <class SignedSignificandBits>
+ static constexpr interval_type::left_closed_right_open
+ normal_interval(SignedSignificandBits) noexcept {
+ return {};
+ }
+ template <class SignedSignificandBits>
+ static constexpr interval_type::left_closed_right_open
+ shorter_interval(SignedSignificandBits) noexcept {
+ return {};
+ }
+ } nearest_away_from_zero = {};
+
+ namespace detail {
+ struct nearest_always_closed_t {
+ using interval_type_provider = nearest_always_closed_t;
+ static constexpr auto tag = tag_t::to_nearest;
+
+ template <class SignedSignificandBits>
+ static constexpr interval_type::closed
+ normal_interval(SignedSignificandBits) noexcept {
+ return {};
+ }
+ template <class SignedSignificandBits>
+ static constexpr interval_type::closed
+ shorter_interval(SignedSignificandBits) noexcept {
+ return {};
+ }
+ };
+ struct nearest_always_open_t {
+ using interval_type_provider = nearest_always_open_t;
+ static constexpr auto tag = tag_t::to_nearest;
+
+ template <class SignedSignificandBits>
+ static constexpr interval_type::open
+ normal_interval(SignedSignificandBits) noexcept {
+ return {};
+ }
+ template <class SignedSignificandBits>
+ static constexpr interval_type::open
+ shorter_interval(SignedSignificandBits) noexcept {
+ return {};
+ }
+ };
+ }
+
+ JKJ_INLINE_VARIABLE struct nearest_to_even_static_boundary_t {
+ using decimal_to_binary_rounding_policy = nearest_to_even_static_boundary_t;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
+ detail::nearest_always_closed_t{}, Args{}...))
+ delegate(SignedSignificandBits s, Func f, Args... args) noexcept {
+ return s.has_even_significand_bits()
+ ? f(detail::nearest_always_closed_t{}, args...)
+ : f(detail::nearest_always_open_t{}, args...);
+ }
+ } nearest_to_even_static_boundary = {};
+
+ JKJ_INLINE_VARIABLE struct nearest_to_odd_static_boundary_t {
+ using decimal_to_binary_rounding_policy = nearest_to_odd_static_boundary_t;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
+ detail::nearest_always_closed_t{}, Args{}...))
+ delegate(SignedSignificandBits s, Func f, Args... args) noexcept {
+ return s.has_even_significand_bits()
+ ? f(detail::nearest_always_open_t{}, args...)
+ : f(detail::nearest_always_closed_t{}, args...);
+ }
+ } nearest_to_odd_static_boundary = {};
+
+ JKJ_INLINE_VARIABLE struct nearest_toward_plus_infinity_static_boundary_t {
+ using decimal_to_binary_rounding_policy =
+ nearest_toward_plus_infinity_static_boundary_t;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE
+ JKJ_SAFEBUFFERS static constexpr decltype(Func{}(nearest_toward_zero,
+ Args{}...))
+ delegate(SignedSignificandBits s, Func f, Args... args) noexcept {
+ return s.is_negative() ? f(nearest_toward_zero, args...)
+ : f(nearest_away_from_zero, args...);
+ }
+ } nearest_toward_plus_infinity_static_boundary = {};
+
+ JKJ_INLINE_VARIABLE struct nearest_toward_minus_infinity_static_boundary_t {
+ using decimal_to_binary_rounding_policy =
+ nearest_toward_minus_infinity_static_boundary_t;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE
+ JKJ_SAFEBUFFERS static constexpr decltype(Func{}(nearest_toward_zero,
+ Args{}...))
+ delegate(SignedSignificandBits s, Func f, Args... args) noexcept {
+ return s.is_negative() ? f(nearest_away_from_zero, args...)
+ : f(nearest_toward_zero, args...);
+ }
+ } nearest_toward_minus_infinity_static_boundary = {};
+
+ namespace detail {
+ struct left_closed_directed_t {
+ static constexpr auto tag = tag_t::left_closed_directed;
+ };
+ struct right_closed_directed_t {
+ static constexpr auto tag = tag_t::right_closed_directed;
+ };
+ }
+
+ JKJ_INLINE_VARIABLE struct toward_plus_infinity_t {
+ using decimal_to_binary_rounding_policy = toward_plus_infinity_t;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
+ detail::left_closed_directed_t{}, Args{}...))
+ delegate(SignedSignificandBits s, Func f, Args... args) noexcept {
+ return s.is_negative() ? f(detail::left_closed_directed_t{}, args...)
+ : f(detail::right_closed_directed_t{}, args...);
+ }
+ } toward_plus_infinity = {};
+
+ JKJ_INLINE_VARIABLE struct toward_minus_infinity_t {
+ using decimal_to_binary_rounding_policy = toward_minus_infinity_t;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
+ detail::left_closed_directed_t{}, Args{}...))
+ delegate(SignedSignificandBits s, Func f, Args... args) noexcept {
+ return s.is_negative() ? f(detail::right_closed_directed_t{}, args...)
+ : f(detail::left_closed_directed_t{}, args...);
+ }
+ } toward_minus_infinity = {};
+
+ JKJ_INLINE_VARIABLE struct toward_zero_t {
+ using decimal_to_binary_rounding_policy = toward_zero_t;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
+ detail::left_closed_directed_t{}, Args{}...))
+ delegate(SignedSignificandBits, Func f, Args... args) noexcept {
+ return f(detail::left_closed_directed_t{}, args...);
+ }
+ } toward_zero = {};
+
+ JKJ_INLINE_VARIABLE struct away_from_zero_t {
+ using decimal_to_binary_rounding_policy = away_from_zero_t;
+
+ template <class SignedSignificandBits, class Func, class... Args>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static constexpr decltype(Func{}(
+ detail::right_closed_directed_t{}, Args{}...))
+ delegate(SignedSignificandBits, Func f, Args... args) noexcept {
+ return f(detail::right_closed_directed_t{}, args...);
+ }
+ } away_from_zero = {};
+ }
+
+ namespace binary_to_decimal_rounding {
+ // (Always assumes nearest rounding modes, as there can be no tie for other rounding
+ // modes.)
+ enum class tag_t { do_not_care, to_even, to_odd, away_from_zero, toward_zero };
+
+ // The parameter significand corresponds to 10\tilde{s}+t in the paper.
+
+ JKJ_INLINE_VARIABLE struct do_not_care_t {
+ using binary_to_decimal_rounding_policy = do_not_care_t;
+ static constexpr auto tag = tag_t::do_not_care;
+
+ template <class CarrierUInt>
+ static constexpr bool prefer_round_down(CarrierUInt) noexcept {
+ return false;
+ }
+ } do_not_care = {};
+
+ JKJ_INLINE_VARIABLE struct to_even_t {
+ using binary_to_decimal_rounding_policy = to_even_t;
+ static constexpr auto tag = tag_t::to_even;
+
+ template <class CarrierUInt>
+ static constexpr bool prefer_round_down(CarrierUInt significand) noexcept {
+ return significand % 2 != 0;
+ }
+ } to_even = {};
+
+ JKJ_INLINE_VARIABLE struct to_odd_t {
+ using binary_to_decimal_rounding_policy = to_odd_t;
+ static constexpr auto tag = tag_t::to_odd;
+
+ template <class CarrierUInt>
+ static constexpr bool prefer_round_down(CarrierUInt significand) noexcept {
+ return significand % 2 == 0;
+ }
+ } to_odd = {};
+
+ JKJ_INLINE_VARIABLE struct away_from_zero_t {
+ using binary_to_decimal_rounding_policy = away_from_zero_t;
+ static constexpr auto tag = tag_t::away_from_zero;
+
+ template <class CarrierUInt>
+ static constexpr bool prefer_round_down(CarrierUInt) noexcept {
+ return false;
+ }
+ } away_from_zero = {};
+
+ JKJ_INLINE_VARIABLE struct toward_zero_t {
+ using binary_to_decimal_rounding_policy = toward_zero_t;
+ static constexpr auto tag = tag_t::toward_zero;
+
+ template <class CarrierUInt>
+ static constexpr bool prefer_round_down(CarrierUInt) noexcept {
+ return true;
+ }
+ } toward_zero = {};
+ }
+
+ namespace cache {
+ JKJ_INLINE_VARIABLE struct full_t {
+ using cache_policy = full_t;
+ template <class FloatFormat>
+ using cache_holder_type = cache_holder<FloatFormat>;
+
+ template <class FloatFormat, class ShiftAmountType, class DecimalExponentType>
+ static constexpr typename cache_holder_type<FloatFormat>::cache_entry_type
+ get_cache(DecimalExponentType k) noexcept {
+#if JKJ_HAS_CONSTEXPR14
+ assert(k >= cache_holder_type<FloatFormat>::min_k &&
+ k <= cache_holder_type<FloatFormat>::max_k);
+#endif
+ return cache_holder_type<FloatFormat>::cache[detail::stdr::size_t(
+ k - cache_holder_type<FloatFormat>::min_k)];
+ }
+ } full = {};
+
+ JKJ_INLINE_VARIABLE struct compact_t {
+ using cache_policy = compact_t;
+ template <class FloatFormat>
+ using cache_holder_type = compressed_cache_holder<FloatFormat>;
+
+ template <class FloatFormat, class ShiftAmountType, class DecimalExponentType>
+ static JKJ_CONSTEXPR20 typename cache_holder<FloatFormat>::cache_entry_type
+ get_cache(DecimalExponentType k) noexcept {
+ assert(k >= cache_holder<FloatFormat>::min_k &&
+ k <= cache_holder<FloatFormat>::max_k);
+
+ return cache_holder_type<FloatFormat>::template get_cache<ShiftAmountType>(k);
+ }
+ } compact = {};
+ }
+
+ namespace preferred_integer_types {
+ JKJ_INLINE_VARIABLE struct match_t {
+ using preferred_integer_types_policy = match_t;
+
+ template <class FormatTraits, detail::stdr::uint_least64_t upper_bound>
+ using remainder_type = typename FormatTraits::carrier_uint;
+
+ template <class FormatTraits, detail::stdr::int_least32_t lower_bound,
+ detail::stdr::uint_least32_t upper_bound>
+ using decimal_exponent_type = typename FormatTraits::exponent_int;
+
+ template <class FormatTraits>
+ using shift_amount_type = typename FormatTraits::exponent_int;
+ } match;
+
+ JKJ_INLINE_VARIABLE struct prefer_32_t {
+ using preferred_integer_types_policy = prefer_32_t;
+
+ template <class FormatTraits, detail::stdr::uint_least64_t upper_bound>
+ using remainder_type = typename detail::stdr::conditional<
+ upper_bound <=
+ detail::stdr::numeric_limits<detail::stdr::uint_least32_t>::max(),
+ detail::stdr::uint_least32_t, typename FormatTraits::carrier_uint>::type;
+
+ template <class FormatTraits, detail::stdr::int_least32_t lower_bound,
+ detail::stdr::uint_least32_t upper_bound>
+ using decimal_exponent_type = typename detail::stdr::conditional<
+ FormatTraits::format::exponent_bits <=
+ detail::value_bits<detail::stdr::int_least32_t>::value,
+ detail::stdr::int_least32_t, typename FormatTraits::exponent_int>::type;
+
+ template <class FormatTraits>
+ using shift_amount_type = detail::stdr::int_least32_t;
+ } prefer_32;
+
+ JKJ_INLINE_VARIABLE struct minimal_t {
+ using preferred_integer_types_policy = minimal_t;
+
+ template <class FormatTraits, detail::stdr::uint_least64_t upper_bound>
+ using remainder_type = typename detail::stdr::conditional<
+ upper_bound <= detail::stdr::numeric_limits<detail::stdr::uint_least8_t>::max(),
+ detail::stdr::uint_least8_t,
+ typename detail::stdr::conditional<
+ upper_bound <=
+ detail::stdr::numeric_limits<detail::stdr::uint_least16_t>::max(),
+ detail::stdr::uint_least16_t,
+ typename detail::stdr::conditional<
+ upper_bound <=
+ detail::stdr::numeric_limits<detail::stdr::uint_least32_t>::max(),
+ detail::stdr::uint_least32_t,
+ typename detail::stdr::conditional<
+ upper_bound <= detail::stdr::numeric_limits<
+ detail::stdr::uint_least64_t>::max(),
+ detail::stdr::uint_least64_t,
+ typename FormatTraits::carrier_uint>::type>::type>::type>::type;
+
+ template <class FormatTraits, detail::stdr::int_least32_t lower_bound,
+ detail::stdr::uint_least32_t upper_bound>
+ using decimal_exponent_type = typename detail::stdr::conditional<
+ lower_bound >=
+ detail::stdr::numeric_limits<detail::stdr::int_least8_t>::min() &&
+ upper_bound <=
+ detail::stdr::numeric_limits<detail::stdr::int_least8_t>::max(),
+ detail::stdr::int_least8_t,
+ typename detail::stdr::conditional<
+ lower_bound >=
+ detail::stdr::numeric_limits<detail::stdr::int_least16_t>::min() &&
+ upper_bound <=
+ detail::stdr::numeric_limits<detail::stdr::int_least16_t>::max(),
+ detail::stdr::int_least16_t,
+ typename detail::stdr::conditional<
+ lower_bound >= detail::stdr::numeric_limits<
+ detail::stdr::int_least32_t>::min() &&
+ upper_bound <= detail::stdr::numeric_limits<
+ detail::stdr::int_least32_t>::max(),
+ detail::stdr::int_least32_t,
+ typename FormatTraits::exponent_int>::type>::type>::type;
+
+ template <class FormatTraits>
+ using shift_amount_type = detail::stdr::int_least8_t;
+ } minimal;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Specializations of user-specializable templates used in the main algorithm.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ template <class DecimalExponentType>
+ struct remove_trailing_zeros_traits<policy::trailing_zero::remove_t, ieee754_binary32,
+ detail::stdr::uint_least32_t, DecimalExponentType> {
+ JKJ_FORCEINLINE static JKJ_CONSTEXPR14 void
+ remove_trailing_zeros(detail::stdr::uint_least32_t& significand,
+ DecimalExponentType& exponent) noexcept {
+ // See https://github.com/jk-jeon/rtz_benchmark.
+ // The idea of branchless search below is by reddit users r/pigeon768 and
+ // r/TheoreticalDumbass.
+
+ auto r = detail::bits::rotr<32>(
+ detail::stdr::uint_least32_t(significand * UINT32_C(184254097)), 4);
+ auto b = r < UINT32_C(429497);
+ auto s = detail::stdr::size_t(b);
+ significand = b ? r : significand;
+
+ r = detail::bits::rotr<32>(
+ detail::stdr::uint_least32_t(significand * UINT32_C(42949673)), 2);
+ b = r < UINT32_C(42949673);
+ s = s * 2 + b;
+ significand = b ? r : significand;
+
+ r = detail::bits::rotr<32>(
+ detail::stdr::uint_least32_t(significand * UINT32_C(1288490189)), 1);
+ b = r < UINT32_C(429496730);
+ s = s * 2 + b;
+ significand = b ? r : significand;
+
+ exponent += s;
+ }
+ };
+
+ template <class DecimalExponentType>
+ struct remove_trailing_zeros_traits<policy::trailing_zero::remove_t, ieee754_binary64,
+ detail::stdr::uint_least64_t, DecimalExponentType> {
+ JKJ_FORCEINLINE static JKJ_CONSTEXPR14 void
+ remove_trailing_zeros(detail::stdr::uint_least64_t& significand,
+ DecimalExponentType& exponent) noexcept {
+ // See https://github.com/jk-jeon/rtz_benchmark.
+ // The idea of branchless search below is by reddit users r/pigeon768 and
+ // r/TheoreticalDumbass.
+
+ auto r = detail::bits::rotr<64>(
+ detail::stdr::uint_least64_t(significand * UINT64_C(28999941890838049)), 8);
+ auto b = r < UINT64_C(184467440738);
+ auto s = detail::stdr::size_t(b);
+ significand = b ? r : significand;
+
+ r = detail::bits::rotr<64>(
+ detail::stdr::uint_least64_t(significand * UINT64_C(182622766329724561)), 4);
+ b = r < UINT64_C(1844674407370956);
+ s = s * 2 + b;
+ significand = b ? r : significand;
+
+ r = detail::bits::rotr<64>(
+ detail::stdr::uint_least64_t(significand * UINT64_C(10330176681277348905)), 2);
+ b = r < UINT64_C(184467440737095517);
+ s = s * 2 + b;
+ significand = b ? r : significand;
+
+ r = detail::bits::rotr<64>(
+ detail::stdr::uint_least64_t(significand * UINT32_C(14757395258967641293)), 1);
+ b = r < UINT64_C(1844674407370955162);
+ s = s * 2 + b;
+ significand = b ? r : significand;
+
+ exponent += s;
+ }
+ };
+
+ template <class DecimalExponentType>
+ struct remove_trailing_zeros_traits<policy::trailing_zero::remove_compact_t, ieee754_binary32,
+ detail::stdr::uint_least32_t, DecimalExponentType> {
+ JKJ_FORCEINLINE static JKJ_CONSTEXPR14 void
+ remove_trailing_zeros(detail::stdr::uint_least32_t& significand,
+ DecimalExponentType& exponent) noexcept {
+ // See https://github.com/jk-jeon/rtz_benchmark.
+ while (true) {
+ auto const r = detail::stdr::uint_least32_t(significand * UINT32_C(1288490189));
+ if (r < UINT32_C(429496731)) {
+ significand = detail::stdr::uint_least32_t(r >> 1);
+ exponent += 1;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ };
+
+ template <class DecimalExponentType>
+ struct remove_trailing_zeros_traits<policy::trailing_zero::remove_compact_t, ieee754_binary64,
+ detail::stdr::uint_least64_t, DecimalExponentType> {
+ JKJ_FORCEINLINE static JKJ_CONSTEXPR14 void
+ remove_trailing_zeros(detail::stdr::uint_least64_t& significand,
+ DecimalExponentType& exponent) noexcept {
+ // See https://github.com/jk-jeon/rtz_benchmark.
+ while (true) {
+ auto const r =
+ detail::stdr::uint_least64_t(significand * UINT64_C(5534023222112865485));
+ if (r < UINT64_C(1844674407370955163)) {
+ significand = detail::stdr::uint_least64_t(r >> 1);
+ exponent += 1;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ };
+
+ template <class ExponentInt>
+ struct multiplication_traits<
+ ieee754_binary_traits<ieee754_binary32, detail::stdr::uint_least32_t, ExponentInt>,
+ detail::stdr::uint_least64_t, 64>
+ : public multiplication_traits_base<
+ ieee754_binary_traits<ieee754_binary32, detail::stdr::uint_least32_t>,
+ detail::stdr::uint_least64_t, 64> {
+ static JKJ_CONSTEXPR20 compute_mul_result
+ compute_mul(carrier_uint u, cache_entry_type const& cache) noexcept {
+ auto const r = detail::wuint::umul96_upper64(u, cache);
+ return {carrier_uint(r >> 32), carrier_uint(r) == 0};
+ }
+
+ template <class ShiftAmountType>
+ static constexpr detail::stdr::uint_least64_t compute_delta(cache_entry_type const& cache,
+ ShiftAmountType beta) noexcept {
+ return detail::stdr::uint_least64_t(cache >> ShiftAmountType(cache_bits - 1 - beta));
+ }
+
+ template <class ShiftAmountType>
+ static JKJ_CONSTEXPR20 compute_mul_parity_result compute_mul_parity(
+ carrier_uint two_f, cache_entry_type const& cache, ShiftAmountType beta) noexcept {
+ assert(beta >= 1);
+ assert(beta <= 32);
+
+ auto const r = detail::wuint::umul96_lower64(two_f, cache);
+ return {((r >> ShiftAmountType(64 - beta)) & 1) != 0,
+ (UINT32_C(0xffffffff) & (r >> ShiftAmountType(32 - beta))) == 0};
+ }
+
+ template <class ShiftAmountType>
+ static constexpr carrier_uint
+ compute_left_endpoint_for_shorter_interval_case(cache_entry_type const& cache,
+ ShiftAmountType beta) noexcept {
+ return carrier_uint((cache - (cache >> (significand_bits + 2))) >>
+ ShiftAmountType(cache_bits - significand_bits - 1 - beta));
+ }
+
+ template <class ShiftAmountType>
+ static constexpr carrier_uint
+ compute_right_endpoint_for_shorter_interval_case(cache_entry_type const& cache,
+ ShiftAmountType beta) noexcept {
+ return carrier_uint((cache + (cache >> (significand_bits + 1))) >>
+ ShiftAmountType(cache_bits - significand_bits - 1 - beta));
+ }
+
+ template <class ShiftAmountType>
+ static constexpr carrier_uint
+ compute_round_up_for_shorter_interval_case(cache_entry_type const& cache,
+ ShiftAmountType beta) noexcept {
+ return (carrier_uint(cache >>
+ ShiftAmountType(cache_bits - significand_bits - 2 - beta)) +
+ 1) /
+ 2;
+ }
+ };
+
+ template <class ExponentInt>
+ struct multiplication_traits<
+ ieee754_binary_traits<ieee754_binary64, detail::stdr::uint_least64_t, ExponentInt>,
+ detail::wuint::uint128, 128>
+ : public multiplication_traits_base<
+ ieee754_binary_traits<ieee754_binary64, detail::stdr::uint_least64_t>,
+ detail::wuint::uint128, 128> {
+ static JKJ_CONSTEXPR20 compute_mul_result
+ compute_mul(carrier_uint u, cache_entry_type const& cache) noexcept {
+ auto const r = detail::wuint::umul192_upper128(u, cache);
+ return {r.high(), r.low() == 0};
+ }
+
+ template <class ShiftAmountType>
+ static constexpr detail::stdr::uint_least64_t compute_delta(cache_entry_type const& cache,
+ ShiftAmountType beta) noexcept {
+ return detail::stdr::uint_least64_t(cache.high() >>
+ ShiftAmountType(total_bits - 1 - beta));
+ }
+
+ template <class ShiftAmountType>
+ static JKJ_CONSTEXPR20 compute_mul_parity_result compute_mul_parity(
+ carrier_uint two_f, cache_entry_type const& cache, ShiftAmountType beta) noexcept {
+ assert(beta >= 1);
+ assert(beta < 64);
+
+ auto const r = detail::wuint::umul192_lower128(two_f, cache);
+ return {((r.high() >> ShiftAmountType(64 - beta)) & 1) != 0,
+ (((r.high() << beta) & UINT64_C(0xffffffffffffffff)) |
+ (r.low() >> ShiftAmountType(64 - beta))) == 0};
+ }
+
+ template <class ShiftAmountType>
+ static constexpr carrier_uint
+ compute_left_endpoint_for_shorter_interval_case(cache_entry_type const& cache,
+ ShiftAmountType beta) noexcept {
+ return (cache.high() - (cache.high() >> (significand_bits + 2))) >>
+ ShiftAmountType(total_bits - significand_bits - 1 - beta);
+ }
+
+ template <class ShiftAmountType>
+ static constexpr carrier_uint
+ compute_right_endpoint_for_shorter_interval_case(cache_entry_type const& cache,
+ ShiftAmountType beta) noexcept {
+ return (cache.high() + (cache.high() >> (significand_bits + 1))) >>
+ ShiftAmountType(total_bits - significand_bits - 1 - beta);
+ }
+
+ template <class ShiftAmountType>
+ static constexpr carrier_uint
+ compute_round_up_for_shorter_interval_case(cache_entry_type const& cache,
+ ShiftAmountType beta) noexcept {
+ return ((cache.high() >> ShiftAmountType(total_bits - significand_bits - 2 - beta)) +
+ 1) /
+ 2;
+ }
+ };
+
+ namespace detail {
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // The main algorithm.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ template <class FormatTraits>
+ struct impl : private FormatTraits::format {
+ using format = typename FormatTraits::format;
+ using carrier_uint = typename FormatTraits::carrier_uint;
+ static constexpr int carrier_bits = FormatTraits::carrier_bits;
+ using exponent_int = typename FormatTraits::exponent_int;
+
+ using format::significand_bits;
+ using format::min_exponent;
+ using format::max_exponent;
+ using format::exponent_bias;
+
+ static constexpr int kappa =
+ log::floor_log10_pow2(carrier_bits - significand_bits - 2) - 1;
+ static_assert(kappa >= 1, "");
+ static_assert(carrier_bits >= significand_bits + 2 + log::floor_log2_pow10(kappa + 1),
+ "");
+
+ static constexpr int min(int x, int y) noexcept { return x < y ? x : y; }
+ static constexpr int max(int x, int y) noexcept { return x > y ? x : y; }
+
+ static constexpr int min_k =
+ min(-log::floor_log10_pow2_minus_log10_4_over_3(max_exponent - significand_bits),
+ -log::floor_log10_pow2(max_exponent - significand_bits) + kappa);
+
+ // We do invoke shorter_interval_case for exponent == min_exponent case,
+ // so we should not add 1 here.
+ static constexpr int max_k =
+ max(-log::floor_log10_pow2_minus_log10_4_over_3(min_exponent -
+ significand_bits /*+ 1*/),
+ -log::floor_log10_pow2(min_exponent - significand_bits) + kappa);
+
+ static constexpr int case_shorter_interval_left_endpoint_lower_threshold = 2;
+ static constexpr int case_shorter_interval_left_endpoint_upper_threshold =
+ 2 +
+ log::floor_log2(
+ compute_power<
+ count_factors<5>((carrier_uint(1) << (significand_bits + 2)) - 1) + 1>(10) /
+ 3);
+
+ static constexpr int case_shorter_interval_right_endpoint_lower_threshold = 0;
+ static constexpr int case_shorter_interval_right_endpoint_upper_threshold =
+ 2 +
+ log::floor_log2(
+ compute_power<
+ count_factors<5>((carrier_uint(1) << (significand_bits + 1)) + 1) + 1>(10) /
+ 3);
+
+ static constexpr int shorter_interval_tie_lower_threshold =
+ -log::floor_log5_pow2_minus_log5_3(significand_bits + 4) - 2 - significand_bits;
+ static constexpr int shorter_interval_tie_upper_threshold =
+ -log::floor_log5_pow2(significand_bits + 2) - 2 - significand_bits;
+
+ template <class PreferredIntegerTypesPolicy>
+ using remainder_type = typename PreferredIntegerTypesPolicy::template remainder_type<
+ FormatTraits, compute_power<kappa + 1>(detail::stdr::uint_least64_t(10))>;
+
+ template <class PreferredIntegerTypesPolicy>
+ using decimal_exponent_type =
+ typename PreferredIntegerTypesPolicy::template decimal_exponent_type<
+ FormatTraits, detail::stdr::int_least32_t(min(-max_k, min_k)),
+ detail::stdr::int_least32_t(max(max_k, -min_k + kappa + 1))>;
+
+ template <class SignPolicy, class TrailingZeroPolicy, class PreferredIntegerTypesPolicy>
+ using return_type =
+ decimal_fp<carrier_uint, decimal_exponent_type<PreferredIntegerTypesPolicy>,
+ SignPolicy::return_has_sign, TrailingZeroPolicy::report_trailing_zeros>;
+
+ //// The main algorithm assumes the input is a normal/subnormal finite number.
+
+ template <class SignPolicy, class TrailingZeroPolicy, class IntervalTypeProvider,
+ class BinaryToDecimalRoundingPolicy, class CachePolicy,
+ class PreferredIntegerTypesPolicy>
+ JKJ_SAFEBUFFERS static JKJ_CONSTEXPR20
+ return_type<SignPolicy, TrailingZeroPolicy, PreferredIntegerTypesPolicy>
+ compute_nearest(signed_significand_bits<FormatTraits> s,
+ exponent_int exponent_bits) noexcept {
+ using cache_holder_type = typename CachePolicy::template cache_holder_type<format>;
+ static_assert(
+ min_k >= cache_holder_type::min_k && max_k <= cache_holder_type::max_k, "");
+
+ using remainder_type_ = remainder_type<PreferredIntegerTypesPolicy>;
+ using decimal_exponent_type_ = decimal_exponent_type<PreferredIntegerTypesPolicy>;
+ using shift_amount_type =
+ typename PreferredIntegerTypesPolicy::template shift_amount_type<FormatTraits>;
+
+ using multiplication_traits_ =
+ multiplication_traits<FormatTraits,
+ typename cache_holder_type::cache_entry_type,
+ cache_holder_type::cache_bits>;
+
+ auto two_fc = s.remove_sign_bit_and_shift();
+ auto binary_exponent = exponent_bits;
+
+ // Is the input a normal number?
+ if (binary_exponent != 0) {
+ binary_exponent += format::exponent_bias - format::significand_bits;
+
+ // Shorter interval case; proceed like Schubfach.
+ // One might think this condition is wrong, since when exponent_bits ==
+ // 1 and two_fc == 0, the interval is actually regular. However, it
+ // turns out that this seemingly wrong condition is actually fine,
+ // because the end result is anyway the same.
+ //
+ // [binary32]
+ // (fc-1/2) * 2^e = 1.175'494'28... * 10^-38
+ // (fc-1/4) * 2^e = 1.175'494'31... * 10^-38
+ // fc * 2^e = 1.175'494'35... * 10^-38
+ // (fc+1/2) * 2^e = 1.175'494'42... * 10^-38
+ //
+ // Hence, shorter_interval_case will return 1.175'494'4 * 10^-38.
+ // 1.175'494'3 * 10^-38 is also a correct shortest representation that
+ // will be rejected if we assume shorter interval, but 1.175'494'4 *
+ // 10^-38 is closer to the true value so it doesn't matter.
+ //
+ // [binary64]
+ // (fc-1/2) * 2^e = 2.225'073'858'507'201'13... * 10^-308
+ // (fc-1/4) * 2^e = 2.225'073'858'507'201'25... * 10^-308
+ // fc * 2^e = 2.225'073'858'507'201'38... * 10^-308
+ // (fc+1/2) * 2^e = 2.225'073'858'507'201'63... * 10^-308
+ //
+ // Hence, shorter_interval_case will return 2.225'073'858'507'201'4 *
+ // 10^-308. This is indeed of the shortest length, and it is the unique
+ // one closest to the true value among valid representations of the same
+ // length.
+ static_assert(stdr::is_same<format, ieee754_binary32>::value ||
+ stdr::is_same<format, ieee754_binary64>::value,
+ "");
+
+ // Shorter interval case.
+ if (two_fc == 0) {
+ auto interval_type = IntervalTypeProvider::shorter_interval(s);
+
+ // Compute k and beta.
+ auto const minus_k = log::floor_log10_pow2_minus_log10_4_over_3<
+ min_exponent - format::significand_bits,
+ max_exponent - format::significand_bits, decimal_exponent_type_>(
+ binary_exponent);
+ auto const beta = shift_amount_type(
+ binary_exponent +
+ log::floor_log2_pow10<min_k, max_k>(decimal_exponent_type_(-minus_k)));
+
+ // Compute xi and zi.
+ auto const cache =
+ CachePolicy::template get_cache<format, shift_amount_type>(
+ decimal_exponent_type_(-minus_k));
+
+ auto xi =
+ multiplication_traits_::compute_left_endpoint_for_shorter_interval_case(
+ cache, beta);
+ auto zi = multiplication_traits_::
+ compute_right_endpoint_for_shorter_interval_case(cache, beta);
+
+ // If we don't accept the right endpoint and
+ // if the right endpoint is an integer, decrease it.
+ if (!interval_type.include_right_endpoint() &&
+ is_right_endpoint_integer_shorter_interval(binary_exponent)) {
+ --zi;
+ }
+ // If we don't accept the left endpoint or
+ // if the left endpoint is not an integer, increase it.
+ if (!interval_type.include_left_endpoint() ||
+ !is_left_endpoint_integer_shorter_interval(binary_exponent)) {
+ ++xi;
+ }
+
+ // Try bigger divisor.
+ // zi is at most floor((f_c + 1/2) * 2^e * 10^k0).
+ // Substituting f_c = 2^p and k0 = -floor(log10(3 * 2^(e-2))), we get
+ // zi <= floor((2^(p+1) + 1) * 20/3) <= ceil((2^(p+1) + 1)/3) * 20.
+ // This computation does not overflow for any of the formats I care about.
+ carrier_uint decimal_significand = div::divide_by_pow10<
+ 1, carrier_uint,
+ carrier_uint(
+ ((((carrier_uint(1) << (significand_bits + 1)) + 1) / 3) + 1) *
+ 20)>(zi);
+
+ // If succeed, remove trailing zeros if necessary and return.
+ if (decimal_significand * 10 >= xi) {
+ return SignPolicy::handle_sign(
+ s, TrailingZeroPolicy::template on_trailing_zeros<format>(
+ decimal_significand, decimal_exponent_type_(minus_k + 1)));
+ }
+
+ // Otherwise, compute the round-up of y.
+ decimal_significand =
+ multiplication_traits_::compute_round_up_for_shorter_interval_case(
+ cache, beta);
+
+ // When tie occurs, choose one of them according to the rule.
+ if (BinaryToDecimalRoundingPolicy::prefer_round_down(decimal_significand) &&
+ binary_exponent >= shorter_interval_tie_lower_threshold &&
+ binary_exponent <= shorter_interval_tie_upper_threshold) {
+ --decimal_significand;
+ }
+ else if (decimal_significand < xi) {
+ ++decimal_significand;
+ }
+ return SignPolicy::handle_sign(
+ s, TrailingZeroPolicy::template no_trailing_zeros<format>(
+ decimal_significand, decimal_exponent_type_(minus_k)));
+ }
+
+ // Normal interval case.
+ two_fc |= (carrier_uint(1) << (format::significand_bits + 1));
+ }
+ // Is the input a subnormal number?
+ else {
+ // Normal interval case.
+ binary_exponent = format::min_exponent - format::significand_bits;
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 1: Schubfach multiplier calculation.
+ //////////////////////////////////////////////////////////////////////
+
+ auto interval_type = IntervalTypeProvider::normal_interval(s);
+
+ // Compute k and beta.
+ auto const minus_k = decimal_exponent_type_(
+ log::floor_log10_pow2<min_exponent - format::significand_bits,
+ max_exponent - format::significand_bits,
+ decimal_exponent_type_>(binary_exponent) -
+ kappa);
+ auto const cache = CachePolicy::template get_cache<format, shift_amount_type>(
+ decimal_exponent_type_(-minus_k));
+ auto const beta =
+ shift_amount_type(binary_exponent + log::floor_log2_pow10<min_k, max_k>(
+ decimal_exponent_type_(-minus_k)));
+
+ // Compute zi and deltai.
+ // 10^kappa <= deltai < 10^(kappa + 1)
+ auto const deltai = static_cast<remainder_type_>(
+ multiplication_traits_::compute_delta(cache, beta));
+ // For the case of binary32, the result of integer check is not correct for
+ // 29711844 * 2^-82
+ // = 6.1442653300000000008655037797566933477355632930994033813476... * 10^-18
+ // and 29711844 * 2^-81
+ // = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17,
+ // and they are the unique counterexamples. However, since 29711844 is even,
+ // this does not cause any problem for the endpoints calculations; it can only
+ // cause a problem when we need to perform integer check for the center.
+ // Fortunately, with these inputs, that branch is never executed, so we are
+ // fine.
+ auto const z_result =
+ multiplication_traits_::compute_mul(carrier_uint((two_fc | 1) << beta), cache);
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 2: Try larger divisor; remove trailing zeros if necessary.
+ //////////////////////////////////////////////////////////////////////
+
+ constexpr auto big_divisor = compute_power<kappa + 1>(remainder_type_(10));
+ constexpr auto small_divisor = compute_power<kappa>(remainder_type_(10));
+
+ // Using an upper bound on zi, we might be able to optimize the division
+ // better than the compiler; we are computing zi / big_divisor here.
+ carrier_uint decimal_significand = div::divide_by_pow10<
+ kappa + 1, carrier_uint,
+ carrier_uint((carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1)>(
+ z_result.integer_part);
+ auto r = remainder_type_(z_result.integer_part - big_divisor * decimal_significand);
+
+ do {
+ if (r < deltai) {
+ // Exclude the right endpoint if necessary.
+ if ((r | remainder_type_(!z_result.is_integer) |
+ remainder_type_(interval_type.include_right_endpoint())) == 0) {
+ JKJ_IF_CONSTEXPR(
+ BinaryToDecimalRoundingPolicy::tag ==
+ policy::binary_to_decimal_rounding::tag_t::do_not_care) {
+ decimal_significand *= 10;
+ --decimal_significand;
+ return SignPolicy::handle_sign(
+ s, TrailingZeroPolicy::template no_trailing_zeros<format>(
+ decimal_significand,
+ decimal_exponent_type_(minus_k + kappa)));
+ }
+ else {
+ --decimal_significand;
+ r = big_divisor;
+ break;
+ }
+ }
+ }
+ else if (r > deltai) {
+ break;
+ }
+ else {
+ // r == deltai; compare fractional parts.
+ auto const x_result = multiplication_traits_::compute_mul_parity(
+ carrier_uint(two_fc - 1), cache, beta);
+
+ if (!(x_result.parity |
+ (x_result.is_integer & interval_type.include_left_endpoint()))) {
+ break;
+ }
+ }
+
+ // We may need to remove trailing zeros.
+ return SignPolicy::handle_sign(
+ s, TrailingZeroPolicy::template on_trailing_zeros<format>(
+ decimal_significand, decimal_exponent_type_(minus_k + kappa + 1)));
+ } while (false);
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 3: Find the significand with the smaller divisor.
+ //////////////////////////////////////////////////////////////////////
+
+ decimal_significand *= 10;
+
+ JKJ_IF_CONSTEXPR(BinaryToDecimalRoundingPolicy::tag ==
+ policy::binary_to_decimal_rounding::tag_t::do_not_care) {
+ // Normally, we want to compute
+ // significand += r / small_divisor
+ // and return, but we need to take care of the case that the resulting
+ // value is exactly the right endpoint, while that is not included in the
+ // interval.
+ if (!interval_type.include_right_endpoint()) {
+ // Is r divisible by 10^kappa?
+ if (div::check_divisibility_and_divide_by_pow10<kappa>(r) &&
+ z_result.is_integer) {
+ // This should be in the interval.
+ decimal_significand += r - 1;
+ }
+ else {
+ decimal_significand += r;
+ }
+ }
+ else {
+ decimal_significand += div::small_division_by_pow10<kappa>(r);
+ }
+ }
+ else {
+ // delta is equal to 10^(kappa + elog10(2) - floor(elog10(2))), so dist cannot
+ // be larger than r.
+ auto dist = remainder_type_(r - (deltai / 2) + (small_divisor / 2));
+ bool const approx_y_parity = ((dist ^ (small_divisor / 2)) & 1) != 0;
+
+ // Is dist divisible by 10^kappa?
+ bool const divisible_by_small_divisor =
+ div::check_divisibility_and_divide_by_pow10<kappa>(dist);
+
+ // Add dist / 10^kappa to the significand.
+ decimal_significand += dist;
+
+ if (divisible_by_small_divisor) {
+ // Check z^(f) >= epsilon^(f).
+ // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1,
+ // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f).
+ // Since there are only 2 possibilities, we only need to care about the
+ // parity. Also, zi and r should have the same parity since the divisor
+ // is an even number.
+ auto const y_result =
+ multiplication_traits_::compute_mul_parity(two_fc, cache, beta);
+ if (y_result.parity != approx_y_parity) {
+ --decimal_significand;
+ }
+ else {
+ // If z^(f) >= epsilon^(f), we might have a tie
+ // when z^(f) == epsilon^(f), or equivalently, when y is an integer.
+ // For tie-to-up case, we can just choose the upper one.
+ if (BinaryToDecimalRoundingPolicy::prefer_round_down(
+ decimal_significand) &
+ y_result.is_integer) {
+ --decimal_significand;
+ }
+ }
+ }
+ }
+ return SignPolicy::handle_sign(
+ s, TrailingZeroPolicy::template no_trailing_zeros<format>(
+ decimal_significand, decimal_exponent_type_(minus_k + kappa)));
+ }
+
+ template <class SignPolicy, class TrailingZeroPolicy, class CachePolicy,
+ class PreferredIntegerTypesPolicy>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static JKJ_CONSTEXPR20
+ return_type<SignPolicy, TrailingZeroPolicy, PreferredIntegerTypesPolicy>
+ compute_left_closed_directed(signed_significand_bits<FormatTraits> s,
+ exponent_int exponent_bits) noexcept {
+ using cache_holder_type = typename CachePolicy::template cache_holder_type<format>;
+ static_assert(
+ min_k >= cache_holder_type::min_k && max_k <= cache_holder_type::max_k, "");
+
+ using remainder_type_ = remainder_type<PreferredIntegerTypesPolicy>;
+ using decimal_exponent_type_ = decimal_exponent_type<PreferredIntegerTypesPolicy>;
+ using shift_amount_type =
+ typename PreferredIntegerTypesPolicy::template shift_amount_type<FormatTraits>;
+
+ using multiplication_traits_ =
+ multiplication_traits<FormatTraits,
+ typename cache_holder_type::cache_entry_type,
+ cache_holder_type::cache_bits>;
+
+ auto two_fc = s.remove_sign_bit_and_shift();
+ auto binary_exponent = exponent_bits;
+
+ // Is the input a normal number?
+ if (binary_exponent != 0) {
+ binary_exponent += format::exponent_bias - format::significand_bits;
+ two_fc |= (carrier_uint(1) << (format::significand_bits + 1));
+ }
+ // Is the input a subnormal number?
+ else {
+ binary_exponent = format::min_exponent - format::significand_bits;
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 1: Schubfach multiplier calculation.
+ //////////////////////////////////////////////////////////////////////
+
+ // Compute k and beta.
+ auto const minus_k = decimal_exponent_type_(
+ log::floor_log10_pow2<format::min_exponent - format::significand_bits,
+ format::max_exponent - format::significand_bits,
+ decimal_exponent_type_>(binary_exponent) -
+ kappa);
+ auto const cache = CachePolicy::template get_cache<format, shift_amount_type>(
+ decimal_exponent_type_(-minus_k));
+ auto const beta =
+ shift_amount_type(binary_exponent + log::floor_log2_pow10<min_k, max_k>(
+ decimal_exponent_type_(-minus_k)));
+
+ // Compute xi and deltai.
+ // 10^kappa <= deltai < 10^(kappa + 1)
+ auto const deltai = static_cast<remainder_type_>(
+ multiplication_traits_::compute_delta(cache, beta));
+ auto x_result =
+ multiplication_traits_::compute_mul(carrier_uint(two_fc << beta), cache);
+
+ // Deal with the unique exceptional cases
+ // 29711844 * 2^-82
+ // = 6.1442653300000000008655037797566933477355632930994033813476... * 10^-18
+ // and 29711844 * 2^-81
+ // = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17
+ // for binary32.
+ JKJ_IF_CONSTEXPR(stdr::is_same<format, ieee754_binary32>::value) {
+ if (binary_exponent <= -80) {
+ x_result.is_integer = false;
+ }
+ }
+
+ if (!x_result.is_integer) {
+ ++x_result.integer_part;
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 2: Try larger divisor; remove trailing zeros if necessary.
+ //////////////////////////////////////////////////////////////////////
+
+ constexpr auto big_divisor = compute_power<kappa + 1>(remainder_type_(10));
+
+ // Using an upper bound on xi, we might be able to optimize the division
+ // better than the compiler; we are computing xi / big_divisor here.
+ carrier_uint decimal_significand = div::divide_by_pow10<
+ kappa + 1, carrier_uint,
+ carrier_uint((carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1)>(
+ x_result.integer_part);
+ auto r = remainder_type_(x_result.integer_part - big_divisor * decimal_significand);
+
+ if (r != 0) {
+ ++decimal_significand;
+ r = remainder_type_(big_divisor - r);
+ }
+
+ do {
+ if (r > deltai) {
+ break;
+ }
+ else if (r == deltai) {
+ // Compare the fractional parts.
+ // This branch is never taken for the exceptional cases
+ // 2f_c = 29711482, e = -81
+ // (6.1442649164096937243516663440523473127541365101933479309082... *
+ // 10^-18) and 2f_c = 29711482, e = -80
+ // (1.2288529832819387448703332688104694625508273020386695861816... *
+ // 10^-17).
+ // For the case of compressed cache for binary32, there is another
+ // exceptional case 2f_c = 33554430, e = -10 (16383.9990234375). In this
+ // case, the recovered cache is two large to make compute_mul_parity
+ // mistakenly conclude that z is not an integer, but actually z = 16384 is
+ // an integer.
+ JKJ_IF_CONSTEXPR(
+ stdr::is_same<cache_holder_type,
+ compressed_cache_holder<ieee754_binary32>>::value) {
+ if (two_fc == 33554430 && binary_exponent == -10) {
+ break;
+ }
+ }
+ auto const z_result = multiplication_traits_::compute_mul_parity(
+ carrier_uint(two_fc + 2), cache, beta);
+ if (z_result.parity || z_result.is_integer) {
+ break;
+ }
+ }
+
+ // The ceiling is inside, so we are done.
+ return SignPolicy::handle_sign(
+ s, TrailingZeroPolicy::template on_trailing_zeros<format>(
+ decimal_significand, decimal_exponent_type_(minus_k + kappa + 1)));
+ } while (false);
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 3: Find the significand with the smaller divisor.
+ //////////////////////////////////////////////////////////////////////
+
+ decimal_significand *= 10;
+ decimal_significand -= div::small_division_by_pow10<kappa>(r);
+ return SignPolicy::handle_sign(
+ s, TrailingZeroPolicy::template no_trailing_zeros<format>(
+ decimal_significand, decimal_exponent_type_(minus_k + kappa)));
+ }
+
+ template <class SignPolicy, class TrailingZeroPolicy, class CachePolicy,
+ class PreferredIntegerTypesPolicy>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS static JKJ_CONSTEXPR20
+ return_type<SignPolicy, TrailingZeroPolicy, PreferredIntegerTypesPolicy>
+ compute_right_closed_directed(signed_significand_bits<FormatTraits> s,
+ exponent_int exponent_bits) noexcept {
+ using cache_holder_type = typename CachePolicy::template cache_holder_type<format>;
+ static_assert(
+ min_k >= cache_holder_type::min_k && max_k <= cache_holder_type::max_k, "");
+
+ using remainder_type_ = remainder_type<PreferredIntegerTypesPolicy>;
+ using decimal_exponent_type_ = decimal_exponent_type<PreferredIntegerTypesPolicy>;
+ using shift_amount_type =
+ typename PreferredIntegerTypesPolicy::template shift_amount_type<FormatTraits>;
+
+ using multiplication_traits_ =
+ multiplication_traits<FormatTraits,
+ typename cache_holder_type::cache_entry_type,
+ cache_holder_type::cache_bits>;
+
+ auto two_fc = s.remove_sign_bit_and_shift();
+ auto binary_exponent = exponent_bits;
+ bool shorter_interval = false;
+
+ // Is the input a normal number?
+ if (binary_exponent != 0) {
+ if (two_fc == 0 && binary_exponent != 1) {
+ shorter_interval = true;
+ }
+ binary_exponent += format::exponent_bias - format::significand_bits;
+ two_fc |= (carrier_uint(1) << (format::significand_bits + 1));
+ }
+ // Is the input a subnormal number?
+ else {
+ binary_exponent = format::min_exponent - format::significand_bits;
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 1: Schubfach multiplier calculation.
+ //////////////////////////////////////////////////////////////////////
+
+ // Compute k and beta.
+ auto const minus_k = decimal_exponent_type_(
+ log::floor_log10_pow2<format::min_exponent - format::significand_bits,
+ format::max_exponent - format::significand_bits,
+ decimal_exponent_type_>(
+ exponent_int(binary_exponent - (shorter_interval ? 1 : 0))) -
+ kappa);
+ auto const cache = CachePolicy::template get_cache<format, shift_amount_type>(
+ decimal_exponent_type_(-minus_k));
+ auto const beta = shift_amount_type(
+ binary_exponent + log::floor_log2_pow10(decimal_exponent_type_(-minus_k)));
+
+ // Compute zi and deltai.
+ // 10^kappa <= deltai < 10^(kappa + 1)
+ auto const deltai =
+ static_cast<remainder_type_>(multiplication_traits_::compute_delta(
+ cache, shift_amount_type(beta - (shorter_interval ? 1 : 0))));
+ carrier_uint const zi =
+ multiplication_traits_::compute_mul(carrier_uint(two_fc << beta), cache)
+ .integer_part;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 2: Try larger divisor; remove trailing zeros if necessary.
+ //////////////////////////////////////////////////////////////////////
+
+ constexpr auto big_divisor = compute_power<kappa + 1>(remainder_type_(10));
+
+ // Using an upper bound on zi, we might be able to optimize the division better
+ // than the compiler; we are computing zi / big_divisor here.
+ carrier_uint decimal_significand = div::divide_by_pow10<
+ kappa + 1, carrier_uint,
+ carrier_uint((carrier_uint(1) << (significand_bits + 1)) * big_divisor - 1)>(
+ zi);
+ auto const r = remainder_type_(zi - big_divisor * decimal_significand);
+
+ do {
+ if (r > deltai) {
+ break;
+ }
+ else if (r == deltai) {
+ // Compare the fractional parts.
+ if (!multiplication_traits_::compute_mul_parity(
+ carrier_uint(two_fc - (shorter_interval ? 1 : 2)), cache, beta)
+ .parity) {
+ break;
+ }
+ }
+
+ // The floor is inside, so we are done.
+ return SignPolicy::handle_sign(
+ s, TrailingZeroPolicy::template on_trailing_zeros<format>(
+ decimal_significand, decimal_exponent_type_(minus_k + kappa + 1)));
+ } while (false);
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Step 3: Find the significand with the small divisor.
+ //////////////////////////////////////////////////////////////////////
+
+ decimal_significand *= 10;
+ decimal_significand += div::small_division_by_pow10<kappa>(r);
+ return SignPolicy::handle_sign(
+ s, TrailingZeroPolicy::template no_trailing_zeros<format>(
+ decimal_significand, decimal_exponent_type_(minus_k + kappa)));
+ }
+
+ static constexpr bool
+ is_right_endpoint_integer_shorter_interval(exponent_int binary_exponent) noexcept {
+ return binary_exponent >= case_shorter_interval_right_endpoint_lower_threshold &&
+ binary_exponent <= case_shorter_interval_right_endpoint_upper_threshold;
+ }
+
+ static constexpr bool
+ is_left_endpoint_integer_shorter_interval(exponent_int binary_exponent) noexcept {
+ return binary_exponent >= case_shorter_interval_left_endpoint_lower_threshold &&
+ binary_exponent <= case_shorter_interval_left_endpoint_upper_threshold;
+ }
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Policy holder.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ // The library will specify a list of accepted kinds of policies and their defaults,
+ // and the user will pass a list of policies parameters. The policy parameters are
+ // supposed to be stateless and only convey information through their types.
+ // The aim of the helper classes/functions given below is to do the following:
+ // 1. Check if the policy parameters given by the user are all valid; that means,
+ // each of them should be at least of one of the kinds specified by the library.
+ // If that's not the case, then the compilation fails.
+ // 2. Check if multiple policy parameters for the same kind is specified by the
+ // user. If that's the case, then the compilation fails.
+ // 3. Build a class deriving from all policies the user have given, and also from
+ // the default policies if the user did not specify one for some kinds.
+ // The library considers a certain policy parameter to belong to a specific kind if and only
+ // if the parameter's type has a member type with a specific name; for example, it belongs
+ // to "sign policy" kind if there is a member type sign_policy.
+
+ // For a given kind, find a policy belonging to that kind.
+ // Check if there are more than one such policies.
+ enum class policy_found_info { not_found, unique, repeated };
+ template <class Policy, policy_found_info info>
+ struct found_policy_pair {
+ // Either the policy parameter type given by the user, or the default policy.
+ using policy = Policy;
+ static constexpr auto found_info = info;
+ };
+
+ template <class KindDetector, class DefaultPolicy>
+ struct detector_default_pair {
+ using kind_detector = KindDetector;
+
+ // Iterate through all given policy parameter types and see if there is a policy
+ // parameter type belonging to the policy kind specified by KindDetector.
+ // 1. If there is none, get_found_policy_pair returns
+ // found_policy_pair<DefaultPolicy, policy_found_info::not_found>.
+ // 2. If there is only one parameter type belonging to the specified kind, then
+ // get_found_policy_pair returns
+ // found_policy_pair<Policy, policy_found_info::unique>
+ // where Policy is the unique parameter type belonging to the specified kind.
+ // 3. If there are multiple parameter types belonging to the specified kind, then
+ // get_found_policy_pair returns
+ // found_policy_pair<FirstPolicy, policy_found_info::repeated>
+ // where FirstPolicy is the first parameter type belonging to the specified kind.
+ // The compilation must fail if this happens.
+ // This is done by first setting FoundPolicyInfo below to
+ // found_policy_pair<DefaultPolicy, policy_found_info::not_found>, and then iterate
+ // over Policies, replacing FoundPolicyInfo by the appropriate one if a parameter
+ // type belonging to the specified kind is found.
+
+ template <class FoundPolicyInfo, class... Policies>
+ struct get_found_policy_pair_impl;
+
+ template <class FoundPolicyInfo>
+ struct get_found_policy_pair_impl<FoundPolicyInfo> {
+ using type = FoundPolicyInfo;
+ };
+
+ template <class FoundPolicyInfo, class FirstPolicy, class... RemainingPolicies>
+ struct get_found_policy_pair_impl<FoundPolicyInfo, FirstPolicy, RemainingPolicies...> {
+ using type = typename stdr::conditional<
+ KindDetector{}(dummy<FirstPolicy>{}),
+ typename stdr::conditional<
+ FoundPolicyInfo::found_info == policy_found_info::not_found,
+ typename get_found_policy_pair_impl<
+ found_policy_pair<FirstPolicy, policy_found_info::unique>,
+ RemainingPolicies...>::type,
+ typename get_found_policy_pair_impl<
+ found_policy_pair<FirstPolicy, policy_found_info::repeated>,
+ RemainingPolicies...>::type>::type,
+ typename get_found_policy_pair_impl<FoundPolicyInfo,
+ RemainingPolicies...>::type>::type;
+ };
+
+ template <class... Policies>
+ using get_found_policy_pair = typename get_found_policy_pair_impl<
+ found_policy_pair<DefaultPolicy, policy_found_info::not_found>, Policies...>::type;
+ };
+
+ // Simple typelist of detector_default_pair's.
+ template <class... DetectorDefaultPairs>
+ struct detector_default_pair_list {};
+
+ // Check if a given policy belongs to one of the kinds specified by the library.
+ template <class Policy>
+ constexpr bool check_policy_validity(dummy<Policy>, detector_default_pair_list<>) noexcept {
+ return false;
+ }
+ template <class Policy, class FirstDetectorDefaultPair,
+ class... RemainingDetectorDefaultPairs>
+ constexpr bool check_policy_validity(
+ dummy<Policy>, detector_default_pair_list<FirstDetectorDefaultPair,
+ RemainingDetectorDefaultPairs...>) noexcept {
+ return typename FirstDetectorDefaultPair::kind_detector{}(dummy<Policy>{}) ||
+ check_policy_validity(
+ dummy<Policy>{},
+ detector_default_pair_list<RemainingDetectorDefaultPairs...>{});
+ }
+
+ // Check if all of policies belong to some of the kinds specified by the library.
+ template <class DetectorDefaultPairList>
+ constexpr bool check_policy_list_validity(DetectorDefaultPairList) noexcept {
+ return true;
+ }
+ template <class DetectorDefaultPairList, class FirstPolicy, class... RemainingPolicies>
+ constexpr bool check_policy_list_validity(DetectorDefaultPairList,
+ dummy<FirstPolicy> first_policy,
+ dummy<RemainingPolicies>... remaining_policies) {
+ return check_policy_validity(first_policy, DetectorDefaultPairList{}) &&
+ check_policy_list_validity(DetectorDefaultPairList{}, remaining_policies...);
+ }
+
+ // Actual policy holder class deriving from all specified policy types.
+ template <class... Policies>
+ struct policy_holder : Policies... {};
+
+ // Iterate through the library-specified list of base-default pairs, i.e., the list of
+ // policy kinds and their defaults. For each base-default pair, call
+ // base_default_pair::get_found_policy_pair on the list of user-specified list of
+ // policies to get found_policy_pair, and build the list of them.
+
+ template <bool repeated_, class... FoundPolicyPairs>
+ struct found_policy_pair_list {
+ // This will be set to be true if and only if there exists at least one
+ // found_policy_pair inside FoundPolicyPairs with
+ // found_info == policy_found_info::repeated, in which case the compilation must
+ // fail.
+ static constexpr bool repeated = repeated_;
+ };
+
+ // Iterate through DetectorDefaultPairList and augment FoundPolicyPairList by one at each
+ // iteration.
+ template <class DetectorDefaultPairList, class FoundPolicyPairList, class... Policies>
+ struct make_policy_pair_list_impl;
+
+ // When there is no more detector-default pair to iterate, then the current
+ // found_policy_pair_list is the final result.
+ template <bool repeated, class... FoundPolicyPairs, class... Policies>
+ struct make_policy_pair_list_impl<detector_default_pair_list<>,
+ found_policy_pair_list<repeated, FoundPolicyPairs...>,
+ Policies...> {
+ using type = found_policy_pair_list<repeated, FoundPolicyPairs...>;
+ };
+
+ // For the first detector-default pair in the remaining list, call
+ // detector_default_pair::get_found_policy_pair on Policies and add the returned
+ // found_policy_pair into the current list of found_policy_pair's, and move to the next
+ // detector-default pair.
+ template <class FirstDetectorDefaultPair, class... RemainingDetectorDefaultPairs,
+ bool repeated, class... FoundPolicyPairs, class... Policies>
+ struct make_policy_pair_list_impl<
+ detector_default_pair_list<FirstDetectorDefaultPair, RemainingDetectorDefaultPairs...>,
+ found_policy_pair_list<repeated, FoundPolicyPairs...>, Policies...> {
+ using new_found_policy_pair =
+ typename FirstDetectorDefaultPair::template get_found_policy_pair<Policies...>;
+
+ using type = typename make_policy_pair_list_impl<
+ detector_default_pair_list<RemainingDetectorDefaultPairs...>,
+ found_policy_pair_list<(repeated || new_found_policy_pair::found_info ==
+ policy_found_info::repeated),
+ new_found_policy_pair, FoundPolicyPairs...>,
+ Policies...>::type;
+ };
+
+ template <class DetectorDefaultPairList, class... Policies>
+ using policy_pair_list =
+ typename make_policy_pair_list_impl<DetectorDefaultPairList,
+ found_policy_pair_list<false>, Policies...>::type;
+
+ // Unpack FoundPolicyPairList into found_policy_pair's and build the policy_holder type
+ // from the corresponding typelist of found_policy_pair::policy's.
+ template <class FoundPolicyPairList, class... RawPolicies>
+ struct convert_to_policy_holder_impl;
+
+ template <bool repeated, class... RawPolicies>
+ struct convert_to_policy_holder_impl<found_policy_pair_list<repeated>, RawPolicies...> {
+ using type = policy_holder<RawPolicies...>;
+ };
+
+ template <bool repeated, class FirstFoundPolicyPair, class... RemainingFoundPolicyPairs,
+ class... RawPolicies>
+ struct convert_to_policy_holder_impl<
+ found_policy_pair_list<repeated, FirstFoundPolicyPair, RemainingFoundPolicyPairs...>,
+ RawPolicies...> {
+ using type = typename convert_to_policy_holder_impl<
+ found_policy_pair_list<repeated, RemainingFoundPolicyPairs...>,
+ typename FirstFoundPolicyPair::policy, RawPolicies...>::type;
+ };
+
+ template <class FoundPolicyPairList>
+ using convert_to_policy_holder =
+ typename convert_to_policy_holder_impl<FoundPolicyPairList>::type;
+
+ template <class DetectorDefaultPairList, class... Policies>
+ struct make_policy_holder_impl {
+ static_assert(check_policy_list_validity(DetectorDefaultPairList{},
+ dummy<Policies>{}...),
+ "jkj::dragonbox: an invalid policy is specified");
+
+ static_assert(
+ !policy_pair_list<DetectorDefaultPairList, Policies...>::repeated,
+ "jkj::dragonbox: at most one policy should be specified for each policy kind");
+
+ using type =
+ convert_to_policy_holder<policy_pair_list<DetectorDefaultPairList, Policies...>>;
+ };
+
+ template <class DetectorDefaultPairList, class... Policies>
+ using make_policy_holder =
+ typename make_policy_holder_impl<DetectorDefaultPairList, Policies...>::type;
+
+
+ // Policy kind detectors.
+ struct is_sign_policy {
+ constexpr bool operator()(...) const noexcept { return false; }
+ template <class Policy, class = typename Policy::sign_policy>
+ constexpr bool operator()(dummy<Policy>) const noexcept {
+ return true;
+ }
+ };
+ struct is_trailing_zero_policy {
+ constexpr bool operator()(...) const noexcept { return false; }
+ template <class Policy, class = typename Policy::trailing_zero_policy>
+ constexpr bool operator()(dummy<Policy>) const noexcept {
+ return true;
+ }
+ };
+ struct is_decimal_to_binary_rounding_policy {
+ constexpr bool operator()(...) const noexcept { return false; }
+ template <class Policy, class = typename Policy::decimal_to_binary_rounding_policy>
+ constexpr bool operator()(dummy<Policy>) const noexcept {
+ return true;
+ }
+ };
+ struct is_binary_to_decimal_rounding_policy {
+ constexpr bool operator()(...) const noexcept { return false; }
+ template <class Policy, class = typename Policy::binary_to_decimal_rounding_policy>
+ constexpr bool operator()(dummy<Policy>) const noexcept {
+ return true;
+ }
+ };
+ struct is_cache_policy {
+ constexpr bool operator()(...) const noexcept { return false; }
+ template <class Policy, class = typename Policy::cache_policy>
+ constexpr bool operator()(dummy<Policy>) const noexcept {
+ return true;
+ }
+ };
+ struct is_preferred_integer_types_policy {
+ constexpr bool operator()(...) const noexcept { return false; }
+ template <class Policy, class = typename Policy::preferred_integer_types_policy>
+ constexpr bool operator()(dummy<Policy>) const noexcept {
+ return true;
+ }
+ };
+
+ template <class... Policies>
+ using to_decimal_policy_holder = make_policy_holder<
+ detector_default_pair_list<
+ detector_default_pair<is_sign_policy, policy::sign::return_sign_t>,
+ detector_default_pair<is_trailing_zero_policy, policy::trailing_zero::remove_t>,
+ detector_default_pair<is_decimal_to_binary_rounding_policy,
+ policy::decimal_to_binary_rounding::nearest_to_even_t>,
+ detector_default_pair<is_binary_to_decimal_rounding_policy,
+ policy::binary_to_decimal_rounding::to_even_t>,
+ detector_default_pair<is_cache_policy, policy::cache::full_t>,
+ detector_default_pair<is_preferred_integer_types_policy,
+ policy::preferred_integer_types::match_t>>,
+ Policies...>;
+
+ template <class FormatTraits, class... Policies>
+ using to_decimal_return_type = typename impl<FormatTraits>::template return_type<
+ typename to_decimal_policy_holder<Policies...>::sign_policy,
+ typename to_decimal_policy_holder<Policies...>::trailing_zero_policy,
+ typename to_decimal_policy_holder<Policies...>::preferred_integer_types_policy>;
+
+ template <class FormatTraits, class PolicyHolder>
+ struct to_decimal_dispatcher {
+ using sign_policy = typename PolicyHolder::sign_policy;
+ using trailing_zero_policy = typename PolicyHolder::trailing_zero_policy;
+ using binary_to_decimal_rounding_policy =
+ typename PolicyHolder::binary_to_decimal_rounding_policy;
+ using cache_policy = typename PolicyHolder::cache_policy;
+ using preferred_integer_types_policy =
+ typename PolicyHolder::preferred_integer_types_policy;
+ using return_type =
+ typename impl<FormatTraits>::template return_type<sign_policy, trailing_zero_policy,
+ preferred_integer_types_policy>;
+
+ template <class IntervalTypeProvider>
+ JKJ_FORCEINLINE JKJ_SAFEBUFFERS JKJ_CONSTEXPR20 return_type
+ operator()(IntervalTypeProvider, signed_significand_bits<FormatTraits> s,
+ typename FormatTraits::exponent_int exponent_bits) noexcept {
+ constexpr auto tag = IntervalTypeProvider::tag;
+
+ JKJ_IF_CONSTEXPR(tag == policy::decimal_to_binary_rounding::tag_t::to_nearest) {
+ return impl<FormatTraits>::template compute_nearest<
+ sign_policy, trailing_zero_policy, IntervalTypeProvider,
+ binary_to_decimal_rounding_policy, cache_policy,
+ preferred_integer_types_policy>(s, exponent_bits);
+ }
+ else JKJ_IF_CONSTEXPR(
+ tag == policy::decimal_to_binary_rounding::tag_t::left_closed_directed) {
+ return impl<FormatTraits>::template compute_left_closed_directed<
+ sign_policy, trailing_zero_policy, cache_policy,
+ preferred_integer_types_policy>(s, exponent_bits);
+ }
+ else {
+#if JKJ_HAS_IF_CONSTEXPR
+ static_assert(
+ tag == policy::decimal_to_binary_rounding::tag_t::right_closed_directed,
+ "");
+#endif
+ return impl<FormatTraits>::template compute_right_closed_directed<
+ sign_policy, trailing_zero_policy, cache_policy,
+ preferred_integer_types_policy>(s, exponent_bits);
+ }
+ }
+ };
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // The interface function.
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ template <class FormatTraits, class ExponentBits, class... Policies>
+ JKJ_FORCEINLINE
+ JKJ_SAFEBUFFERS JKJ_CONSTEXPR20 detail::to_decimal_return_type<FormatTraits, Policies...>
+ to_decimal_ex(signed_significand_bits<FormatTraits> s, ExponentBits exponent_bits,
+ Policies...) noexcept {
+ // Build policy holder type.
+ using policy_holder = detail::to_decimal_policy_holder<Policies...>;
+
+ return policy_holder::delegate(
+ s, detail::to_decimal_dispatcher<FormatTraits, policy_holder>{}, s, exponent_bits);
+ }
+
+ template <class Float,
+ class ConversionTraits = default_float_bit_carrier_conversion_traits<Float>,
+ class FormatTraits = ieee754_binary_traits<typename ConversionTraits::format,
+ typename ConversionTraits::carrier_uint>,
+ class... Policies>
+ JKJ_FORCEINLINE
+ JKJ_SAFEBUFFERS JKJ_CONSTEXPR20 detail::to_decimal_return_type<FormatTraits, Policies...>
+ to_decimal(Float x, Policies... policies) noexcept {
+ auto const br = make_float_bits<Float, ConversionTraits, FormatTraits>(x);
+ auto const exponent_bits = br.extract_exponent_bits();
+ auto const s = br.remove_exponent_bits();
+ assert(br.is_finite() && br.is_nonzero());
+
+ return to_decimal_ex(s, exponent_bits, policies...);
+ }
+ }
+}
+}
+
+#undef JKJ_HAS_BUILTIN
+#undef JKJ_FORCEINLINE
+#undef JKJ_SAFEBUFFERS
+#undef JKJ_CONSTEXPR20
+#undef JKJ_USE_IS_CONSTANT_EVALUATED
+#undef JKJ_CAN_BRANCH_ON_CONSTEVAL
+#undef JKJ_IF_NOT_CONSTEVAL
+#undef JKJ_IF_CONSTEVAL
+#undef JKJ_HAS_BIT_CAST
+#undef JKJ_IF_CONSTEXPR
+#undef JKJ_HAS_IF_CONSTEXPR
+#undef JKJ_INLINE_VARIABLE
+#undef JKJ_HAS_INLINE_VARIABLE
+#undef JKJ_HAS_CONSTEXPR17
+#undef JKJ_CONSTEXPR14
+#undef JKJ_HAS_CONSTEXPR14
+#if JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED
+ #undef JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED
+#else
+ #undef JKJ_STD_REPLACEMENT_NAMESPACE
+#endif
+#if JKJ_STATIC_DATA_SECTION_DEFINED
+ #undef JKJ_STATIC_DATA_SECTION_DEFINED
+#else
+ #undef JKJ_STATIC_DATA_SECTION
+#endif
+
+#endif
diff --git a/lib/yamlcpp/src/emitfromevents.cpp b/lib/yamlcpp/src/emitfromevents.cpp
index 2e97187b90..350bde6488 100644
--- a/lib/yamlcpp/src/emitfromevents.cpp
+++ b/lib/yamlcpp/src/emitfromevents.cpp
@@ -116,8 +116,13 @@ void EmitFromEvents::BeginNode() {
}
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
- if (!tag.empty() && tag != "?" && tag != "!")
- m_emitter << VerbatimTag(tag);
+ if (!tag.empty() && tag != "?" && tag != "!"){
+ if (tag[0] == '!') {
+ m_emitter << LocalTag(std::string(tag.begin()+1, tag.end()));
+ } else {
+ m_emitter << VerbatimTag(tag);
+ }
+ }
if (anchor)
m_emitter << Anchor(ToString(anchor));
}
diff --git a/lib/yamlcpp/src/emitter.cpp b/lib/yamlcpp/src/emitter.cpp
index 4d483075bd..e5fc0ea3f0 100644
--- a/lib/yamlcpp/src/emitter.cpp
+++ b/lib/yamlcpp/src/emitter.cpp
@@ -213,7 +213,8 @@ void Emitter::EmitEndSeq() {
if (m_pState->CurGroupFlowType() == FlowType::Flow) {
if (m_stream.comment())
m_stream << "\n";
- m_stream << IndentTo(m_pState->CurIndent());
+ if (originalType == FlowType::Block || m_pState->HasBegunNode())
+ m_stream << IndentTo(m_pState->CurIndent());
if (originalType == FlowType::Block) {
m_stream << "[";
} else {
@@ -715,33 +716,33 @@ StringEscaping::value GetStringEscapingStyle(const EMITTER_MANIP emitterManip) {
}
}
-Emitter& Emitter::Write(const std::string& str) {
+Emitter& Emitter::Write(const char* str, std::size_t size) {
if (!good())
return *this;
StringEscaping::value stringEscaping = GetStringEscapingStyle(m_pState->GetOutputCharset());
const StringFormat::value strFormat =
- Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
+ Utils::ComputeStringFormat(str, size, m_pState->GetStringFormat(),
m_pState->CurGroupFlowType(), stringEscaping == StringEscaping::NonAscii);
- if (strFormat == StringFormat::Literal || str.size() > 1024)
+ if (strFormat == StringFormat::Literal || size > 1024)
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
PrepareNode(EmitterNodeType::Scalar);
switch (strFormat) {
case StringFormat::Plain:
- m_stream << str;
+ m_stream.write(str, size);
break;
case StringFormat::SingleQuoted:
- Utils::WriteSingleQuotedString(m_stream, str);
+ Utils::WriteSingleQuotedString(m_stream, str, size);
break;
case StringFormat::DoubleQuoted:
- Utils::WriteDoubleQuotedString(m_stream, str, stringEscaping);
+ Utils::WriteDoubleQuotedString(m_stream, str, size, stringEscaping);
break;
case StringFormat::Literal:
- Utils::WriteLiteralString(m_stream, str,
+ Utils::WriteLiteralString(m_stream, str, size,
m_pState->CurIndent() + m_pState->GetIndent());
break;
}
@@ -751,6 +752,10 @@ Emitter& Emitter::Write(const std::string& str) {
return *this;
}
+Emitter& Emitter::Write(const std::string& str) {
+ return Write(str.data(), str.size());
+}
+
std::size_t Emitter::GetFloatPrecision() const {
return m_pState->GetFloatPrecision();
}
@@ -864,7 +869,7 @@ Emitter& Emitter::Write(const _Alias& alias) {
PrepareNode(EmitterNodeType::Scalar);
- if (!Utils::WriteAlias(m_stream, alias.content)) {
+ if (!Utils::WriteAlias(m_stream, alias.content.data(), alias.content.size())) {
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
return *this;
}
@@ -887,7 +892,7 @@ Emitter& Emitter::Write(const _Anchor& anchor) {
PrepareNode(EmitterNodeType::Property);
- if (!Utils::WriteAnchor(m_stream, anchor.content)) {
+ if (!Utils::WriteAnchor(m_stream, anchor.content.data(), anchor.content.size())) {
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
return *this;
}
@@ -936,7 +941,7 @@ Emitter& Emitter::Write(const _Comment& comment) {
if (m_stream.col() > 0)
m_stream << Indentation(m_pState->GetPreCommentIndent());
- Utils::WriteComment(m_stream, comment.content,
+ Utils::WriteComment(m_stream, comment.content.data(), comment.content.size(),
m_pState->GetPostCommentIndent());
m_pState->SetNonContent();
diff --git a/lib/yamlcpp/src/emitterutils.cpp b/lib/yamlcpp/src/emitterutils.cpp
index 6cdf6de7e2..1541e17d0e 100644
--- a/lib/yamlcpp/src/emitterutils.cpp
+++ b/lib/yamlcpp/src/emitterutils.cpp
@@ -1,4 +1,5 @@
#include <algorithm>
+#include <cstdint>
#include <iomanip>
#include <sstream>
@@ -88,8 +89,8 @@ int Utf8BytesIndicated(char ch) {
bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
bool GetNextCodePointAndAdvance(int& codePoint,
- std::string::const_iterator& first,
- std::string::const_iterator last) {
+ const char*& first,
+ const char* last) {
if (first == last)
return false;
@@ -152,39 +153,39 @@ void WriteCodePoint(ostream_wrapper& out, int codePoint) {
}
}
-bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
+bool IsValidPlainScalar(const char* str, std::size_t size, FlowType::value flowType,
bool allowOnlyAscii) {
// check against null
- if (IsNullString(str)) {
+ if (IsNullString(str, size)) {
return false;
}
// check the start
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
: Exp::PlainScalar());
- if (!start.Matches(str)) {
+ if (!start.Matches(StringCharSource(str, size))) {
return false;
}
// and check the end for plain whitespace (which can't be faithfully kept in a
// plain scalar)
- if (!str.empty() && *str.rbegin() == ' ') {
+ if (size != 0 && str[size - 1] == ' ') {
return false;
}
// then check until something is disallowed
- static const RegEx& disallowed_flow =
+ static const RegEx disallowed_flow =
Exp::EndScalarInFlow() | (Exp::BlankOrBreak() + Exp::Comment()) |
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
Exp::Tab() | Exp::Ampersand();
- static const RegEx& disallowed_block =
+ static const RegEx disallowed_block =
Exp::EndScalar() | (Exp::BlankOrBreak() + Exp::Comment()) |
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
Exp::Tab() | Exp::Ampersand();
const RegEx& disallowed =
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
- StringCharSource buffer(str.c_str(), str.size());
+ StringCharSource buffer(str, size);
while (buffer) {
if (disallowed.Matches(buffer)) {
return false;
@@ -198,22 +199,22 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
return true;
}
-bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
+bool IsValidSingleQuotedScalar(const char* str, std::size_t size, bool escapeNonAscii) {
// TODO: check for non-printable characters?
- return std::none_of(str.begin(), str.end(), [=](char ch) {
+ return std::none_of(str, str + size, [=](char ch) {
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) ||
(ch == '\n');
});
}
-bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
+bool IsValidLiteralScalar(const char* str, std::size_t size, FlowType::value flowType,
bool escapeNonAscii) {
if (flowType == FlowType::Flow) {
return false;
}
// TODO: check for non-printable characters?
- return std::none_of(str.begin(), str.end(), [=](char ch) {
+ return std::none_of(str, str + size, [=](char ch) {
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch)));
});
}
@@ -253,10 +254,10 @@ void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint, StringE
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
}
-bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
+bool WriteAliasName(ostream_wrapper& out, const char* str, std::size_t size) {
int codePoint;
- for (std::string::const_iterator i = str.begin();
- GetNextCodePointAndAdvance(codePoint, i, str.end());) {
+ for (const char* i = str;
+ GetNextCodePointAndAdvance(codePoint, i, str + size);) {
if (!IsAnchorChar(codePoint)) {
return false;
}
@@ -267,25 +268,25 @@ bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
}
} // namespace
-StringFormat::value ComputeStringFormat(const std::string& str,
+StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
EMITTER_MANIP strFormat,
FlowType::value flowType,
bool escapeNonAscii) {
switch (strFormat) {
case Auto:
- if (IsValidPlainScalar(str, flowType, escapeNonAscii)) {
+ if (IsValidPlainScalar(str, size, flowType, escapeNonAscii)) {
return StringFormat::Plain;
}
return StringFormat::DoubleQuoted;
case SingleQuoted:
- if (IsValidSingleQuotedScalar(str, escapeNonAscii)) {
+ if (IsValidSingleQuotedScalar(str, size, escapeNonAscii)) {
return StringFormat::SingleQuoted;
}
return StringFormat::DoubleQuoted;
case DoubleQuoted:
return StringFormat::DoubleQuoted;
case Literal:
- if (IsValidLiteralScalar(str, flowType, escapeNonAscii)) {
+ if (IsValidLiteralScalar(str, size, flowType, escapeNonAscii)) {
return StringFormat::Literal;
}
return StringFormat::DoubleQuoted;
@@ -296,11 +297,11 @@ StringFormat::value ComputeStringFormat(const std::string& str,
return StringFormat::DoubleQuoted;
}
-bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
+bool WriteSingleQuotedString(ostream_wrapper& out, const char* str, std::size_t size) {
out << "'";
int codePoint;
- for (std::string::const_iterator i = str.begin();
- GetNextCodePointAndAdvance(codePoint, i, str.end());) {
+ for (const char* i = str;
+ GetNextCodePointAndAdvance(codePoint, i, str + size);) {
if (codePoint == '\n') {
return false; // We can't handle a new line and the attendant indentation
// yet
@@ -316,12 +317,12 @@ bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
return true;
}
-bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
+bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t size,
StringEscaping::value stringEscaping) {
out << "\"";
int codePoint;
- for (std::string::const_iterator i = str.begin();
- GetNextCodePointAndAdvance(codePoint, i, str.end());) {
+ for (const char* i = str;
+ GetNextCodePointAndAdvance(codePoint, i, str + size);) {
switch (codePoint) {
case '\"':
out << "\\\"";
@@ -363,12 +364,12 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
return true;
}
-bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
+bool WriteLiteralString(ostream_wrapper& out, const char* str, std::size_t size,
std::size_t indent) {
out << "|\n";
int codePoint;
- for (std::string::const_iterator i = str.begin();
- GetNextCodePointAndAdvance(codePoint, i, str.end());) {
+ for (const char* i = str;
+ GetNextCodePointAndAdvance(codePoint, i, str + size);) {
if (codePoint == '\n') {
out << "\n";
} else {
@@ -406,14 +407,14 @@ bool WriteChar(ostream_wrapper& out, char ch, StringEscaping::value stringEscapi
return true;
}
-bool WriteComment(ostream_wrapper& out, const std::string& str,
+bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
std::size_t postCommentIndent) {
const std::size_t curIndent = out.col();
out << "#" << Indentation(postCommentIndent);
out.set_comment();
int codePoint;
- for (std::string::const_iterator i = str.begin();
- GetNextCodePointAndAdvance(codePoint, i, str.end());) {
+ for (const char* i = str;
+ GetNextCodePointAndAdvance(codePoint, i, str + size);) {
if (codePoint == '\n') {
out << "\n"
<< IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
@@ -425,14 +426,14 @@ bool WriteComment(ostream_wrapper& out, const std::string& str,
return true;
}
-bool WriteAlias(ostream_wrapper& out, const std::string& str) {
+bool WriteAlias(ostream_wrapper& out, const char* str, std::size_t size) {
out << "*";
- return WriteAliasName(out, str);
+ return WriteAliasName(out, str, size);
}
-bool WriteAnchor(ostream_wrapper& out, const std::string& str) {
+bool WriteAnchor(ostream_wrapper& out, const char* str, std::size_t size) {
out << "&";
- return WriteAliasName(out, str);
+ return WriteAliasName(out, str, size);
}
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
@@ -489,7 +490,8 @@ bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
}
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
- WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
+ std::string encoded = EncodeBase64(binary.data(), binary.size());
+ WriteDoubleQuotedString(out, encoded.data(), encoded.size(),
StringEscaping::None);
return true;
}
diff --git a/lib/yamlcpp/src/emitterutils.h b/lib/yamlcpp/src/emitterutils.h
index 3a7d598252..0c0dcbb927 100644
--- a/lib/yamlcpp/src/emitterutils.h
+++ b/lib/yamlcpp/src/emitterutils.h
@@ -29,22 +29,22 @@ struct StringEscaping {
};
namespace Utils {
-StringFormat::value ComputeStringFormat(const std::string& str,
+StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
EMITTER_MANIP strFormat,
FlowType::value flowType,
bool escapeNonAscii);
-bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
-bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
+bool WriteSingleQuotedString(ostream_wrapper& out, const char* str, std::size_t size);
+bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t size,
StringEscaping::value stringEscaping);
-bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
+bool WriteLiteralString(ostream_wrapper& out, const char* str, std::size_t size,
std::size_t indent);
bool WriteChar(ostream_wrapper& out, char ch,
StringEscaping::value stringEscapingStyle);
-bool WriteComment(ostream_wrapper& out, const std::string& str,
+bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
std::size_t postCommentIndent);
-bool WriteAlias(ostream_wrapper& out, const std::string& str);
-bool WriteAnchor(ostream_wrapper& out, const std::string& str);
+bool WriteAlias(ostream_wrapper& out, const char* str, std::size_t size);
+bool WriteAnchor(ostream_wrapper& out, const char* str, std::size_t size);
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
const std::string& tag);
diff --git a/lib/yamlcpp/src/fptostring.cpp b/lib/yamlcpp/src/fptostring.cpp
new file mode 100644
index 0000000000..e1722aeed1
--- /dev/null
+++ b/lib/yamlcpp/src/fptostring.cpp
@@ -0,0 +1,255 @@
+#include "yaml-cpp/fptostring.h"
+#include "contrib/dragonbox.h"
+
+#include <array>
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <sstream>
+#include <tuple>
+
+namespace YAML {
+namespace detail {
+namespace fp_formatting {
+
+/**
+ * Converts a integer into its ASCII digits.
+ *
+ * @param begin/end - a buffer, must be at least 20bytes long.
+ * @param value - input value.
+ * @param width - minimum number of digits, fill with '0' to the left. Must be equal or smaller than the buffer size.
+ * @return - number of digits filled into the buffer (or -1 if preconditions are not meet)
+ *
+ * Example:
+ * std::array<char, 20> buffer;
+ * auto ct = ConvertToChars(buffer.begin(), buffer.end(), 23, 3);
+ * assert(ct = 3);
+ * assert(buffer[0] == '0');
+ * assert(buffer[1] == '2');
+ * assert(buffer[2] == '3');
+ */
+int ConvertToChars(char* begin, char* end, size_t value, int width=1) {
+ // precondition of this function (will trigger in debug build)
+ assert(width >= 1);
+ assert(end >= begin); // end must be after begin
+ assert(end-begin >= width); // Buffer must be large enough
+ assert(end-begin >= 20); // 2^64 has 20digits, so at least 20 digits must be available
+
+ // defensive programming, abort if precondition are not met (will trigger in release build)
+ if (width < 1) {
+ return -1;
+ }
+ if (end < begin) {
+ return -1;
+ }
+ if (end-begin < width) {
+ return -1;
+ }
+ if (end-begin < 20) {
+ return -1;
+ }
+
+
+ // count number of digits, and fill digits array accordingly
+ int digits_ct{};
+ while (value > 0) {
+ char c = value % 10 + '0';
+ value = value / 10;
+ digits_ct += 1;
+ *(end-digits_ct) = c;
+ }
+ while(digits_ct < width) {
+ assert(digits_ct < 64);
+ digits_ct += 1;
+ *(end-digits_ct) = '0';
+ }
+ // move data to the front of the array
+ std::memmove(begin, end-digits_ct, digits_ct);
+ return digits_ct;
+}
+
+/**
+ * Converts a float or double to a string.
+ *
+ * converts a value 'v' to a string. Uses dragonbox for formatting.
+ */
+template <typename T>
+std::string FpToString(T v, int precision = 0) {
+ // hard coded constant, at which exponent should switch to a scientific notation
+ int const lowerExponentThreshold = -5;
+ int const upperExponentThreshold = (precision==0)?6:precision;
+ if (precision == 0) {
+ precision = 6;
+ }
+
+ // dragonbox/to_decimal does not handle value 0, inf, NaN
+ if (v == 0 || std::isinf(v) || std::isnan(v)) {
+ std::stringstream ss;
+ ss.imbue(std::locale::classic());
+ ss << v;
+ return ss.str();
+ }
+
+ auto r = jkj::dragonbox::to_decimal(v);
+
+ auto digits = std::array<char, 20>{}; // max digits of size_t is 20.
+ auto digits_ct = ConvertToChars(digits.data(), digits.data() + digits.size(), r.significand);
+
+ // defensive programming, ConvertToChars arguments are invalid
+ if (digits_ct == -1) {
+ std::stringstream ss;
+ ss.imbue(std::locale::classic());
+ ss << v;
+ return ss.str();
+ }
+
+ // check if requested precision is lower than
+ // required digits for exact representation
+ if (digits_ct > precision) {
+ auto diff = digits_ct - precision;
+ r.exponent += diff;
+ digits_ct = precision;
+
+ // round numbers if required
+ if (digits[digits_ct] >= '5') {
+ int i{digits_ct-1};
+ digits[i] += 1;
+ while (digits[i] == '9'+1) {
+ digits_ct -= 1;
+ r.exponent += 1;
+ if (i > 0) {
+ digits[i-1] += 1;
+ i -= 1;
+ } else {
+ digits_ct = 1;
+ digits[0] = '1';
+ break;
+ }
+ }
+ }
+ }
+
+ // Case 1 - scientific notation: max digits of size_t plus sign, a dot and 2 letters for 'e+' or 'e-' and 4 letters for the exponent
+ // Case 2 - default notation: require up to precision number of digits and one for a potential sign
+ std::array<char, 28> output_buffer;
+ auto output_ptr = &output_buffer[0];
+
+ // Helper variable that in Case 2 counts the overflowing number of zeros that do not fit into the buffer.
+ int overflow_zeros = 0;
+
+ // print '-' symbol for negative numbers
+ if (r.is_negative) {
+ *(output_ptr++) = '-';
+ }
+
+ // exponent if only a single non-zero digit is before the decimal point
+ int const exponent = r.exponent + digits_ct - 1;
+
+ // case 1: scientific notation
+ if (exponent >= upperExponentThreshold || exponent <= lowerExponentThreshold) {
+ // print first digit
+ *(output_ptr++) = digits[0];
+
+ // print digits after decimal point
+ if (digits_ct > 1) {
+ *(output_ptr++) = '.';
+ // print significant numbers after decimal point
+ for (int i{1}; i < digits_ct; ++i) {
+ *(output_ptr++) = digits[i];
+ }
+ }
+ *(output_ptr++) = 'e';
+ *(output_ptr++) = (exponent>=0)?'+':'-';
+ auto exp_digits = std::array<char, 20>{};
+ auto exp_digits_ct = ConvertToChars(exp_digits.data(), exp_digits.data() + exp_digits.size(), std::abs(exponent), /*.precision=*/ 2);
+
+ // defensive programming, ConvertToChars arguments are invalid
+ if (exp_digits_ct == -1) {
+ std::stringstream ss;
+ ss.imbue(std::locale::classic());
+ ss << v;
+ return ss.str();
+ }
+
+ for (int i{0}; i < exp_digits_ct; ++i) {
+ *(output_ptr++) = exp_digits[i];
+ }
+
+ // case 2: default notation
+ } else {
+ auto const digits_end = digits.begin() + digits_ct;
+ auto digits_iter = digits.begin();
+
+ // print digits before point
+ int const before_decimal_digits = digits_ct + r.exponent;
+ if (before_decimal_digits > 0) {
+ // print non-zero digits before point
+ for (int i{0}; i < std::min(before_decimal_digits, digits_ct); ++i) {
+ *(output_ptr++) = *(digits_iter++);
+ }
+
+ // number of digits that have to be zero
+ int const zero_digits_ct = before_decimal_digits - digits_ct;
+
+ // space left in the output_buffer (-1 because we need it for null-termination)
+ int const buffer_empty_space = output_buffer.data() + output_buffer.size() - output_ptr - 1;
+
+ // print all zeros not fitting into the buffer at the end of the function
+ overflow_zeros = std::max(0, zero_digits_ct - buffer_empty_space);
+
+ // print trailing zeros before point
+ for (int i{0}; i < zero_digits_ct - overflow_zeros; ++i) {
+ *(output_ptr++) = '0';
+ }
+
+ // print 0 before point if none where printed before
+ } else {
+ *(output_ptr++) = '0';
+ }
+
+ if (digits_iter != digits_end) {
+ *(output_ptr++) = '.';
+ // print 0 after decimal point, to fill until first digits
+ int const after_decimal_zeros = -digits_ct - r.exponent;
+ for (int i{0}; i < after_decimal_zeros; ++i) {
+ *(output_ptr++) = '0';
+ }
+
+ // print significant numbers after decimal point
+ for (;digits_iter < digits_end; ++digits_iter) {
+ *(output_ptr++) = *digits_iter;
+ }
+ }
+ }
+ *output_ptr = '\0';
+ auto ret_value = std::string{&output_buffer[0], output_ptr};
+ ret_value.resize(ret_value.size() + overflow_zeros, '0');
+ return ret_value;
+}
+
+}
+}
+
+std::string FpToString(float v, size_t precision) {
+ return detail::fp_formatting::FpToString(v, precision);
+}
+
+std::string FpToString(double v, size_t precision) {
+ return detail::fp_formatting::FpToString(v, precision);
+}
+
+/**
+ * dragonbox only works for floats/doubles not long double
+ */
+std::string FpToString(long double v, size_t precision) {
+ std::stringstream ss;
+ ss.imbue(std::locale::classic());
+ if (precision == 0) {
+ precision = std::numeric_limits<long double>::max_digits10;
+ }
+ ss.precision(precision);
+ ss << v;
+ return ss.str();
+}
+
+}
diff --git a/lib/yamlcpp/src/indentation.h b/lib/yamlcpp/src/indentation.h
index 1a2ccaea2e..2a0137e8ee 100644
--- a/lib/yamlcpp/src/indentation.h
+++ b/lib/yamlcpp/src/indentation.h
@@ -7,7 +7,6 @@
#pragma once
#endif
-#include <iostream>
#include <cstddef>
#include "yaml-cpp/ostream_wrapper.h"
diff --git a/lib/yamlcpp/src/memory.cpp b/lib/yamlcpp/src/memory.cpp
index 676e4c7f15..7a544e6f22 100644
--- a/lib/yamlcpp/src/memory.cpp
+++ b/lib/yamlcpp/src/memory.cpp
@@ -9,6 +9,10 @@ void memory_holder::merge(memory_holder& rhs) {
if (m_pMemory == rhs.m_pMemory)
return;
+ if (m_pMemory->size() < rhs.m_pMemory->size()) {
+ std::swap(m_pMemory, rhs.m_pMemory);
+ }
+
m_pMemory->merge(*rhs.m_pMemory);
rhs.m_pMemory = m_pMemory;
}
@@ -22,5 +26,9 @@ node& memory::create_node() {
void memory::merge(const memory& rhs) {
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
}
+
+size_t memory::size() const {
+ return m_nodes.size();
+}
} // namespace detail
} // namespace YAML
diff --git a/lib/yamlcpp/src/node_data.cpp b/lib/yamlcpp/src/node_data.cpp
index 8f5422ae6e..6653bc17a8 100644
--- a/lib/yamlcpp/src/node_data.cpp
+++ b/lib/yamlcpp/src/node_data.cpp
@@ -310,6 +310,7 @@ void node_data::convert_sequence_to_map(const shared_memory_holder& pMemory) {
reset_map();
for (std::size_t i = 0; i < m_sequence.size(); i++) {
std::stringstream stream;
+ stream.imbue(std::locale::classic());
stream << i;
node& key = pMemory->create_node();
diff --git a/lib/yamlcpp/src/null.cpp b/lib/yamlcpp/src/null.cpp
index db7daebf1d..eb75b12a21 100644
--- a/lib/yamlcpp/src/null.cpp
+++ b/lib/yamlcpp/src/null.cpp
@@ -1,10 +1,17 @@
#include "yaml-cpp/null.h"
+#include <cstring>
namespace YAML {
_Null Null;
-bool IsNullString(const std::string& str) {
- return str.empty() || str == "~" || str == "null" || str == "Null" ||
- str == "NULL";
+template <std::size_t N>
+static bool same(const char* str, std::size_t size, const char (&literal)[N]) {
+ constexpr int literalSize = N - 1; // minus null terminator
+ return size == literalSize && std::strncmp(str, literal, literalSize) == 0;
+}
+
+bool IsNullString(const char* str, std::size_t size) {
+ return size == 0 || same(str, size, "~") || same(str, size, "null") ||
+ same(str, size, "Null") || same(str, size, "NULL");
}
} // namespace YAML
diff --git a/lib/yamlcpp/src/ostream_wrapper.cpp b/lib/yamlcpp/src/ostream_wrapper.cpp
index 047a9f7c8e..2936007279 100644
--- a/lib/yamlcpp/src/ostream_wrapper.cpp
+++ b/lib/yamlcpp/src/ostream_wrapper.cpp
@@ -2,7 +2,7 @@
#include <algorithm>
#include <cstring>
-#include <iostream>
+#include <ostream>
namespace YAML {
ostream_wrapper::ostream_wrapper()
diff --git a/lib/yamlcpp/src/parse.cpp b/lib/yamlcpp/src/parse.cpp
index 262536b85a..4cfab77b28 100644
--- a/lib/yamlcpp/src/parse.cpp
+++ b/lib/yamlcpp/src/parse.cpp
@@ -53,7 +53,7 @@ std::vector<Node> LoadAll(std::istream& input) {
Parser parser(input);
while (true) {
NodeBuilder builder;
- if (!parser.HandleNextDocument(builder)) {
+ if (!parser.HandleNextDocument(builder) || builder.Root().IsNull()) {
break;
}
docs.push_back(builder.Root());
diff --git a/lib/yamlcpp/src/parser.cpp b/lib/yamlcpp/src/parser.cpp
index b8b78ebabc..04e194665b 100644
--- a/lib/yamlcpp/src/parser.cpp
+++ b/lib/yamlcpp/src/parser.cpp
@@ -77,6 +77,7 @@ void Parser::HandleYamlDirective(const Token& token) {
}
std::stringstream str(token.params[0]);
+ str.imbue(std::locale::classic());
str >> m_pDirectives->version.major;
str.get();
str >> m_pDirectives->version.minor;
diff --git a/lib/yamlcpp/src/regeximpl.h b/lib/yamlcpp/src/regeximpl.h
index a742cdc305..bc3c69b6ca 100644
--- a/lib/yamlcpp/src/regeximpl.h
+++ b/lib/yamlcpp/src/regeximpl.h
@@ -27,6 +27,10 @@ inline bool RegEx::Matches(const Stream& in) const { return Match(in) >= 0; }
template <typename Source>
inline bool RegEx::Matches(const Source& source) const {
+#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201103L) || __cplusplus >= 201103L)
+ static_assert(!std::is_same<Source, const char*>::value,
+#endif
+ "Must use StringCharSource instead of plain C-string");
return Match(source) >= 0;
}
diff --git a/lib/yamlcpp/src/scanner.cpp b/lib/yamlcpp/src/scanner.cpp
index ea5511a114..d0eb03cc74 100644
--- a/lib/yamlcpp/src/scanner.cpp
+++ b/lib/yamlcpp/src/scanner.cpp
@@ -13,6 +13,7 @@ Scanner::Scanner(std::istream& in)
m_startedStream(false),
m_endedStream(false),
m_simpleKeyAllowed(false),
+ m_scalarValueAllowed(false),
m_canBeJSONFlow(false),
m_simpleKeys{},
m_indents{},
@@ -127,6 +128,17 @@ void Scanner::ScanNextToken() {
}
if (INPUT.peek() == Keys::FlowEntry) {
+ // values starting with `,` are not allowed.
+ // eg: reject `,foo`
+ if (INPUT.column() == 0) {
+ throw ParserException(INPUT.mark(), ErrorMsg::UNEXPECTED_FLOW);
+ }
+ // if we already parsed a quoted scalar value and we are not in a flow,
+ // then `,` is not a valid character.
+ // eg: reject `"foo",`
+ if (!m_scalarValueAllowed) {
+ throw ParserException(INPUT.mark(), ErrorMsg::UNEXPECTED_SCALAR);
+ }
return ScanFlowEntry();
}
@@ -159,6 +171,13 @@ void Scanner::ScanNextToken() {
return ScanBlockScalar();
}
+ // if we already parsed a quoted scalar value in this line,
+ // another scalar value is an error.
+ // eg: reject `"foo" "bar"`
+ if (!m_scalarValueAllowed) {
+ throw ParserException(INPUT.mark(), ErrorMsg::UNEXPECTED_SCALAR);
+ }
+
if (INPUT.peek() == '\'' || INPUT.peek() == '\"') {
return ScanQuotedScalar();
}
@@ -203,6 +222,9 @@ void Scanner::ScanToNextToken() {
// oh yeah, and let's get rid of that simple key
InvalidateSimpleKey();
+ // new line - we accept a scalar value now
+ m_scalarValueAllowed = true;
+
// new line - we may be able to accept a simple key now
if (InBlockContext()) {
m_simpleKeyAllowed = true;
@@ -245,6 +267,7 @@ const RegEx& Scanner::GetValueRegex() const {
void Scanner::StartStream() {
m_startedStream = true;
m_simpleKeyAllowed = true;
+ m_scalarValueAllowed = true;
std::unique_ptr<IndentMarker> pIndent(
new IndentMarker(-1, IndentMarker::NONE));
m_indentRefs.push_back(std::move(pIndent));
@@ -261,6 +284,7 @@ void Scanner::EndStream() {
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
+ m_scalarValueAllowed = false;
m_endedStream = true;
}
diff --git a/lib/yamlcpp/src/scanner.h b/lib/yamlcpp/src/scanner.h
index 4af938e69c..a3bfb662dd 100644
--- a/lib/yamlcpp/src/scanner.h
+++ b/lib/yamlcpp/src/scanner.h
@@ -177,6 +177,7 @@ class Scanner {
// state info
bool m_startedStream, m_endedStream;
bool m_simpleKeyAllowed;
+ bool m_scalarValueAllowed;
bool m_canBeJSONFlow;
std::stack<SimpleKey> m_simpleKeys;
std::stack<IndentMarker *> m_indents;
diff --git a/lib/yamlcpp/src/scantoken.cpp b/lib/yamlcpp/src/scantoken.cpp
index 1a94ab1d7d..b13d21133b 100644
--- a/lib/yamlcpp/src/scantoken.cpp
+++ b/lib/yamlcpp/src/scantoken.cpp
@@ -211,6 +211,9 @@ void Scanner::ScanValue() {
m_simpleKeyAllowed = InBlockContext();
}
+ // we are parsing a `key: value` pair; scalars are always allowed
+ m_scalarValueAllowed = true;
+
// eat
Mark mark = INPUT.mark();
INPUT.eat(1);
@@ -360,6 +363,10 @@ void Scanner::ScanQuotedScalar() {
// and scan
scalar = ScanScalar(INPUT, params);
m_simpleKeyAllowed = false;
+ // we just scanned a quoted scalar;
+ // we can only have another scalar in this line
+ // if we are in a flow, eg: `[ "foo", "bar" ]` is ok, but `"foo", "bar"` isn't.
+ m_scalarValueAllowed = InFlowContext();
m_canBeJSONFlow = true;
Token token(Token::NON_PLAIN_SCALAR, mark);
diff --git a/lib/yamlcpp/src/singledocparser.cpp b/lib/yamlcpp/src/singledocparser.cpp
index 22913d198c..04ea4f2876 100644
--- a/lib/yamlcpp/src/singledocparser.cpp
+++ b/lib/yamlcpp/src/singledocparser.cpp
@@ -1,4 +1,3 @@
-#include <algorithm>
#include <cstdio>
#include <sstream>
@@ -93,9 +92,9 @@ void SingleDocParser::HandleNode(EventHandler& eventHandler) {
// add non-specific tags
if (tag.empty())
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
-
- if (token.type == Token::PLAIN_SCALAR
- && tag.compare("?") == 0 && IsNullString(token.value)) {
+
+ if (token.type == Token::PLAIN_SCALAR
+ && tag.compare("?") == 0 && IsNullString(token.value.data(), token.value.size())) {
eventHandler.OnNull(mark, anchor);
m_scanner.pop();
return;
diff --git a/lib/yamlcpp/src/stream.cpp b/lib/yamlcpp/src/stream.cpp
index b1aa092f69..794ae873a5 100644
--- a/lib/yamlcpp/src/stream.cpp
+++ b/lib/yamlcpp/src/stream.cpp
@@ -1,4 +1,4 @@
-#include <iostream>
+#include <istream>
#include "stream.h"
@@ -262,7 +262,24 @@ char Stream::get() {
AdvanceCurrent();
m_mark.column++;
- if (ch == '\n') {
+ // if line ending symbol is unknown, set it to the first
+ // encountered line ending.
+ // if line ending '\r' set ending symbol to '\r'
+ // other wise set it to '\n'
+ if (!m_lineEndingSymbol) {
+ if (ch == '\n') { // line ending is '\n'
+ m_lineEndingSymbol = '\n';
+ } else if (ch == '\r') {
+ auto ch2 = peek();
+ if (ch2 == '\n') { // line ending is '\r\n'
+ m_lineEndingSymbol = '\n';
+ } else { // line ending is '\r'
+ m_lineEndingSymbol = '\r';
+ }
+ }
+ }
+
+ if (ch == m_lineEndingSymbol) {
m_mark.column = 0;
m_mark.line++;
}
diff --git a/lib/yamlcpp/src/stream.h b/lib/yamlcpp/src/stream.h
index 2bc7a15216..c5e3798c8b 100644
--- a/lib/yamlcpp/src/stream.h
+++ b/lib/yamlcpp/src/stream.h
@@ -11,7 +11,7 @@
#include <cstddef>
#include <deque>
#include <ios>
-#include <iostream>
+#include <istream>
#include <set>
#include <string>
@@ -53,6 +53,7 @@ class Stream {
Mark m_mark;
CharacterSet m_charSet;
+ char m_lineEndingSymbol{}; // 0 means it is not determined yet, must be '\n' or '\r'
mutable std::deque<char> m_readahead;
unsigned char* const m_pPrefetched;
mutable size_t m_nPrefetchedAvailable;
diff --git a/lib/yamlcpp/src/token.h b/lib/yamlcpp/src/token.h
index 9c9a5b7798..d93ad2b8e7 100644
--- a/lib/yamlcpp/src/token.h
+++ b/lib/yamlcpp/src/token.h
@@ -8,17 +8,18 @@
#endif
#include "yaml-cpp/mark.h"
-#include <iostream>
+#include <ostream>
#include <string>
#include <vector>
namespace YAML {
-const std::string TokenNames[] = {
+constexpr const char* TokenNames[] = {
"DIRECTIVE", "DOC_START", "DOC_END", "BLOCK_SEQ_START",
"BLOCK_MAP_START", "BLOCK_SEQ_END", "BLOCK_MAP_END", "BLOCK_ENTRY",
"FLOW_SEQ_START", "FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END",
"FLOW_MAP_COMPACT", "FLOW_ENTRY", "KEY", "VALUE",
- "ANCHOR", "ALIAS", "TAG", "SCALAR"};
+ "ANCHOR", "ALIAS", "TAG", "SCALAR",
+ "NON_PLAIN_SCALAR"};
struct Token {
// enums
diff --git a/lib/yamlcpp/test/BUILD.bazel b/lib/yamlcpp/test/BUILD.bazel
index d30fa73cb2..dfc37647ea 100644
--- a/lib/yamlcpp/test/BUILD.bazel
+++ b/lib/yamlcpp/test/BUILD.bazel
@@ -1,14 +1,30 @@
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+
+package(default_visibility = ["//test:__subpackages__"])
+
+cc_library(
+ name = "mock_event_handler",
+ hdrs = ["mock_event_handler.h"],
+ strip_include_prefix = "//test",
+)
+
+cc_library(
+ name = "specexamples",
+ hdrs = ["specexamples.h"],
+ strip_include_prefix = "//test",
+)
+
cc_test(
name = "test",
srcs = glob([
"*.cpp",
- "*.h",
- "integrations/*.cpp",
"node/*.cpp",
]),
deps = [
+ ":mock_event_handler",
+ ":specexamples",
"//:yaml-cpp",
"//:yaml-cpp_internal",
- "@com_google_googletest//:gtest_main",
+ "@googletest//:gtest_main",
],
)
diff --git a/lib/yamlcpp/test/CMakeLists.txt b/lib/yamlcpp/test/CMakeLists.txt
index 351b03f810..693139f2c3 100644
--- a/lib/yamlcpp/test/CMakeLists.txt
+++ b/lib/yamlcpp/test/CMakeLists.txt
@@ -2,13 +2,19 @@ find_package(Threads REQUIRED)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
set(BUILD_MOCK ON CACHE BOOL "" FORCE)
-set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
-
-add_subdirectory(
- "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.11.0"
- "${CMAKE_CURRENT_BINARY_DIR}/prefix")
-
-include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.11.0/googletest/include")
+set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
+
+if(YAML_USE_SYSTEM_GTEST)
+ find_package(GTest)
+ if (NOT GTEST_FOUND)
+ message(FATAL_ERROR "system googletest was requested but not found")
+ endif()
+else()
+ add_subdirectory(
+ "${CMAKE_CURRENT_SOURCE_DIR}/googletest-1.13.0"
+ "${CMAKE_CURRENT_BINARY_DIR}/prefix")
+ include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/googletest-1.13.0/googletest/include")
+endif()
set(test-new-api-pattern "new-api/*.cpp")
set(test-source-pattern "*.cpp" "integration/*.cpp" "node/*.cpp")
@@ -33,11 +39,12 @@ target_include_directories(yaml-cpp-tests
target_compile_options(yaml-cpp-tests
PRIVATE
$<$<CXX_COMPILER_ID:Clang>:-Wno-c99-extensions -Wno-variadic-macros -Wno-sign-compare>
- $<$<CXX_COMPILER_ID:GNU>:-Wno-variadic-macros -Wno-sign-compare>)
+ $<$<CXX_COMPILER_ID:GNU>:-Wno-variadic-macros -Wno-sign-compare -Wno-narrowing>)
target_link_libraries(yaml-cpp-tests
PRIVATE
Threads::Threads
yaml-cpp
+ gtest
gmock)
set_property(TARGET yaml-cpp-tests PROPERTY CXX_STANDARD_REQUIRED ON)
diff --git a/lib/yamlcpp/test/cmake/CMakeLists.txt b/lib/yamlcpp/test/cmake/CMakeLists.txt
new file mode 100644
index 0000000000..a2b8e78a8c
--- /dev/null
+++ b/lib/yamlcpp/test/cmake/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 3.5)
+project(yaml-cpp-consumer LANGUAGES CXX)
+
+find_package(yaml-cpp CONFIG REQUIRED)
+get_target_property(LIBRARY_TYPE yaml-cpp::yaml-cpp TYPE)
+
+if(LIBRARY_TYPE STREQUAL "SHARED_LIBRARY")
+ if(NOT YAML_CPP_SHARED_LIBS_BUILT)
+ message(FATAL_ERROR "Library type (${LIBRARY_TYPE}) contradicts config: ${YAML_CPP_SHARED_LIBS_BUILT}")
+ endif()
+else()
+ if(YAML_CPP_SHARED_LIBS_BUILT)
+ message(FATAL_ERROR "Library type (${LIBRARY_TYPE}) contradicts config: ${YAML_CPP_SHARED_LIBS_BUILT}")
+ endif()
+endif()
+
+add_executable(main main.cpp)
+if (NOT DEFINED CMAKE_CXX_STANDARD)
+ set_target_properties(main PROPERTIES CXX_STANDARD 11)
+endif()
+target_link_libraries(main PRIVATE ${YAML_CPP_LIBRARIES})
diff --git a/lib/yamlcpp/test/cmake/main.cpp b/lib/yamlcpp/test/cmake/main.cpp
new file mode 100644
index 0000000000..bce9ea62cd
--- /dev/null
+++ b/lib/yamlcpp/test/cmake/main.cpp
@@ -0,0 +1,3 @@
+#include "yaml-cpp/yaml.h"
+
+int main(int, char**) { YAML::Parser foo{}; }
diff --git a/lib/yamlcpp/test/fptostring_test.cpp b/lib/yamlcpp/test/fptostring_test.cpp
new file mode 100644
index 0000000000..818b78a114
--- /dev/null
+++ b/lib/yamlcpp/test/fptostring_test.cpp
@@ -0,0 +1,249 @@
+#include "yaml-cpp/fptostring.h"
+#include "gtest/gtest.h"
+
+#include <iomanip>
+
+namespace YAML {
+namespace {
+
+/**
+ * Helper function, that converts double to string as std::stringstream would do
+ */
+template <typename T>
+static std::string convert_with_stringstream(T v, size_t precision = 0) {
+ std::stringstream ss;
+ ss.imbue(std::locale::classic());
+ if (precision > 0) {
+ ss << std::setprecision(precision);
+ }
+ ss << v;
+ return ss.str();
+}
+
+// Caution: Test involving 'convert_with_stringstream' are based on std::stringstream
+// having certain printing behavior, if these changes, the unit test might fail.
+// This is not a fault of FpToString just a weakness of the way these
+// tests are constructed
+
+TEST(FpToStringTest, conversion_double) {
+ // Issue motivating FpToString function,
+ // https://github.com/jbeder/yaml-cpp/issues/1289
+ // Original problem at hand:
+ EXPECT_EQ("34.34", FpToString(34.34));
+ EXPECT_EQ("56.56", FpToString(56.56));
+ EXPECT_EQ("12.12", FpToString(12.12));
+ EXPECT_EQ("78.78", FpToString(78.78));
+
+ // Special challenge with rounding
+ // https://github.com/jbeder/yaml-cpp/issues/1289#issuecomment-2211705536
+ EXPECT_EQ("1.54743e+26", FpToString(1.5474250491e+26f));
+ EXPECT_EQ(convert_with_stringstream(1.5474250491e+26f), FpToString(1.5474250491e+26f));
+ EXPECT_EQ("1.5474251e+26", FpToString(1.5474250491e+26f, 8));
+
+ // prints the same way as std::stringstream
+ EXPECT_EQ(convert_with_stringstream(1.), FpToString(1.));
+ EXPECT_EQ(convert_with_stringstream(1e0), FpToString(1e0));
+ EXPECT_EQ(convert_with_stringstream(1e1), FpToString(1e1));
+ EXPECT_EQ(convert_with_stringstream(1e2), FpToString(1e2));
+ EXPECT_EQ(convert_with_stringstream(1e3), FpToString(1e3));
+ EXPECT_EQ(convert_with_stringstream(1e4), FpToString(1e4));
+ EXPECT_EQ(convert_with_stringstream(1e5), FpToString(1e5));
+ EXPECT_EQ(convert_with_stringstream(1e6), FpToString(1e6));
+ EXPECT_EQ(convert_with_stringstream(1e7), FpToString(1e7));
+ EXPECT_EQ(convert_with_stringstream(1e8), FpToString(1e8));
+ EXPECT_EQ(convert_with_stringstream(1e9), FpToString(1e9));
+
+ // Print by default values below 1e6 without scientific notation
+ EXPECT_EQ("1", FpToString(1.));
+ EXPECT_EQ("1", FpToString(1e0));
+ EXPECT_EQ("10", FpToString(1e1));
+ EXPECT_EQ("100", FpToString(1e2));
+ EXPECT_EQ("1000", FpToString(1e3));
+ EXPECT_EQ("10000", FpToString(1e4));
+ EXPECT_EQ("100000", FpToString(1e5));
+ EXPECT_EQ("1e+06", FpToString(1e6));
+ EXPECT_EQ("1e+07", FpToString(1e7));
+ EXPECT_EQ("1e+08", FpToString(1e8));
+ EXPECT_EQ("1e+09", FpToString(1e9));
+
+ // prints the same way as std::stringstream
+ EXPECT_EQ(convert_with_stringstream(1.), FpToString(1.));
+ EXPECT_EQ(convert_with_stringstream(1e-0), FpToString(1e-0));
+ EXPECT_EQ(convert_with_stringstream(1e-1), FpToString(1e-1));
+ EXPECT_EQ(convert_with_stringstream(1e-2), FpToString(1e-2));
+ EXPECT_EQ(convert_with_stringstream(1e-3), FpToString(1e-3));
+ EXPECT_EQ(convert_with_stringstream(1e-4), FpToString(1e-4));
+ EXPECT_EQ(convert_with_stringstream(1e-5), FpToString(1e-5));
+ EXPECT_EQ(convert_with_stringstream(1e-6), FpToString(1e-6));
+ EXPECT_EQ(convert_with_stringstream(1e-7), FpToString(1e-7));
+ EXPECT_EQ(convert_with_stringstream(1e-8), FpToString(1e-8));
+ EXPECT_EQ(convert_with_stringstream(1e-9), FpToString(1e-9));
+
+ // Print by default values above 1e-5 without scientific notation
+ EXPECT_EQ("1", FpToString(1.));
+ EXPECT_EQ("1", FpToString(1e-0));
+ EXPECT_EQ("0.1", FpToString(1e-1));
+ EXPECT_EQ("0.01", FpToString(1e-2));
+ EXPECT_EQ("0.001", FpToString(1e-3));
+ EXPECT_EQ("0.0001", FpToString(1e-4));
+ EXPECT_EQ("1e-05", FpToString(1e-5));
+ EXPECT_EQ("1e-06", FpToString(1e-6));
+ EXPECT_EQ("1e-07", FpToString(1e-7));
+ EXPECT_EQ("1e-08", FpToString(1e-8));
+ EXPECT_EQ("1e-09", FpToString(1e-9));
+
+ // changing precision has the same effect as std::stringstream
+ EXPECT_EQ(convert_with_stringstream(123., 1), FpToString(123., 1));
+ EXPECT_EQ(convert_with_stringstream(1234567., 7), FpToString(1234567., 7));
+ EXPECT_EQ(convert_with_stringstream(12345.67, 7), FpToString(12345.67, 7));
+ EXPECT_EQ(convert_with_stringstream(1234567e-9, 7), FpToString(1234567e-9, 7));
+ EXPECT_EQ(convert_with_stringstream(1234567e-9, 1), FpToString(1234567e-9, 1));
+
+ // known example that is difficult to round
+ EXPECT_EQ("1", FpToString(0.9999, 2));
+ EXPECT_EQ("-1", FpToString(-0.9999, 2));
+
+ // some more random tests
+ EXPECT_EQ("1.25", FpToString(1.25));
+ EXPECT_EQ("34.34", FpToString(34.34));
+ EXPECT_EQ("1e+20", FpToString(1e+20));
+ EXPECT_EQ("1.1e+20", FpToString(1.1e+20));
+ EXPECT_EQ("1e-20", FpToString(1e-20));
+ EXPECT_EQ("1.1e-20", FpToString(1.1e-20));
+ EXPECT_EQ("1e-20", FpToString(0.1e-19));
+ EXPECT_EQ("1.1e-20", FpToString(0.11e-19));
+
+ EXPECT_EQ("19", FpToString(18.9, 2));
+ EXPECT_EQ("20", FpToString(19.9, 2));
+ EXPECT_EQ("2e+01", FpToString(19.9, 1));
+ EXPECT_EQ("1.2e-05", FpToString(1.234e-5, 2));
+ EXPECT_EQ("1.3e-05", FpToString(1.299e-5, 2));
+
+ EXPECT_EQ("-1", FpToString(-1.));
+ EXPECT_EQ("-1.25", FpToString(-1.25));
+ EXPECT_EQ("-34.34", FpToString(-34.34));
+ EXPECT_EQ("-1e+20", FpToString(-1e+20));
+ EXPECT_EQ("-1.1e+20", FpToString(-1.1e+20));
+ EXPECT_EQ("-1e-20", FpToString(-1e-20));
+ EXPECT_EQ("-1.1e-20", FpToString(-1.1e-20));
+ EXPECT_EQ("-1e-20", FpToString(-0.1e-19));
+ EXPECT_EQ("-1.1e-20", FpToString(-0.11e-19));
+
+ EXPECT_EQ("-19", FpToString(-18.9, 2));
+ EXPECT_EQ("-20", FpToString(-19.9, 2));
+ EXPECT_EQ("-2e+01", FpToString(-19.9, 1));
+ EXPECT_EQ("-1.2e-05", FpToString(-1.234e-5, 2));
+ EXPECT_EQ("-1.3e-05", FpToString(-1.299e-5, 2));
+}
+
+TEST(FpToStringTest, conversion_float) {
+ // Issue motivating FpToString function,
+ // https://github.com/jbeder/yaml-cpp/issues/1289
+ // Original problem at hand:
+ EXPECT_EQ("34.34", FpToString(34.34f));
+ EXPECT_EQ("56.56", FpToString(56.56f));
+ EXPECT_EQ("12.12", FpToString(12.12f));
+ EXPECT_EQ("78.78", FpToString(78.78f));
+
+ // prints the same way as std::stringstream
+ EXPECT_EQ(convert_with_stringstream(1.f), FpToString(1.f));
+ EXPECT_EQ(convert_with_stringstream(1e0f), FpToString(1e0f));
+ EXPECT_EQ(convert_with_stringstream(1e1f), FpToString(1e1f));
+ EXPECT_EQ(convert_with_stringstream(1e2f), FpToString(1e2f));
+ EXPECT_EQ(convert_with_stringstream(1e3f), FpToString(1e3f));
+ EXPECT_EQ(convert_with_stringstream(1e4f), FpToString(1e4f));
+ EXPECT_EQ(convert_with_stringstream(1e5f), FpToString(1e5f));
+ EXPECT_EQ(convert_with_stringstream(1e6f), FpToString(1e6f));
+ EXPECT_EQ(convert_with_stringstream(1e7f), FpToString(1e7f));
+ EXPECT_EQ(convert_with_stringstream(1e8f), FpToString(1e8f));
+ EXPECT_EQ(convert_with_stringstream(1e9f), FpToString(1e9f));
+
+ // Print by default values below 1e6 without scientific notation
+ EXPECT_EQ("1", FpToString(1.f));
+ EXPECT_EQ("1", FpToString(1e0f));
+ EXPECT_EQ("10", FpToString(1e1f));
+ EXPECT_EQ("100", FpToString(1e2f));
+ EXPECT_EQ("1000", FpToString(1e3f));
+ EXPECT_EQ("10000", FpToString(1e4f));
+ EXPECT_EQ("100000", FpToString(1e5f));
+ EXPECT_EQ("1e+06", FpToString(1e6f));
+ EXPECT_EQ("1e+07", FpToString(1e7f));
+ EXPECT_EQ("1e+08", FpToString(1e8f));
+ EXPECT_EQ("1e+09", FpToString(1e9f));
+
+ // prints the same way as std::stringstream
+ EXPECT_EQ(convert_with_stringstream(1.f), FpToString(1.f));
+ EXPECT_EQ(convert_with_stringstream(1e-0f), FpToString(1e-0f));
+ EXPECT_EQ(convert_with_stringstream(1e-1f), FpToString(1e-1f));
+ EXPECT_EQ(convert_with_stringstream(1e-2f), FpToString(1e-2f));
+ EXPECT_EQ(convert_with_stringstream(1e-3f), FpToString(1e-3f));
+ EXPECT_EQ(convert_with_stringstream(1e-4f), FpToString(1e-4f));
+ EXPECT_EQ(convert_with_stringstream(1e-5f), FpToString(1e-5f));
+ EXPECT_EQ(convert_with_stringstream(1e-6f), FpToString(1e-6f));
+ EXPECT_EQ(convert_with_stringstream(1e-7f), FpToString(1e-7f));
+ EXPECT_EQ(convert_with_stringstream(1e-8f), FpToString(1e-8f));
+ EXPECT_EQ(convert_with_stringstream(1e-9f), FpToString(1e-9f));
+
+ // Print by default values above 1e-5 without scientific notation
+ EXPECT_EQ("1", FpToString(1.f));
+ EXPECT_EQ("1", FpToString(1e-0f));
+ EXPECT_EQ("0.1", FpToString(1e-1f));
+ EXPECT_EQ("0.01", FpToString(1e-2f));
+ EXPECT_EQ("0.001", FpToString(1e-3f));
+ EXPECT_EQ("0.0001", FpToString(1e-4f));
+ EXPECT_EQ("1e-05", FpToString(1e-5f));
+ EXPECT_EQ("1e-06", FpToString(1e-6f));
+ EXPECT_EQ("1e-07", FpToString(1e-7f));
+ EXPECT_EQ("1e-08", FpToString(1e-8f));
+ EXPECT_EQ("1e-09", FpToString(1e-9f));
+
+ // changing precision has the same effect as std::stringstream
+ EXPECT_EQ(convert_with_stringstream(123.f, 1), FpToString(123.f, 1));
+ EXPECT_EQ(convert_with_stringstream(1234567.f, 7), FpToString(1234567.f, 7));
+ EXPECT_EQ(convert_with_stringstream(12345.67f, 7), FpToString(12345.67f, 7));
+ EXPECT_EQ(convert_with_stringstream(1234567e-9f, 7), FpToString(1234567e-9f, 7));
+ EXPECT_EQ(convert_with_stringstream(1234567e-9f, 1), FpToString(1234567e-9f, 1));
+
+ // known example that is difficult to round
+ EXPECT_EQ("1", FpToString(0.9999f, 2));
+ EXPECT_EQ("-1", FpToString(-0.9999f, 2));
+
+ // some more random tests
+ EXPECT_EQ("1.25", FpToString(1.25f));
+ EXPECT_EQ("34.34", FpToString(34.34f));
+ EXPECT_EQ("1e+20", FpToString(1e+20f));
+ EXPECT_EQ("1.1e+20", FpToString(1.1e+20f));
+ EXPECT_EQ("1e-20", FpToString(1e-20f));
+ EXPECT_EQ("1.1e-20", FpToString(1.1e-20f));
+ EXPECT_EQ("1e-20", FpToString(0.1e-19f));
+ EXPECT_EQ("1.1e-20", FpToString(0.11e-19f));
+
+ EXPECT_EQ("19", FpToString(18.9f, 2));
+ EXPECT_EQ("20", FpToString(19.9f, 2));
+ EXPECT_EQ("2e+01", FpToString(19.9f, 1));
+ EXPECT_EQ("1.2e-05", FpToString(1.234e-5f, 2));
+ EXPECT_EQ("1.3e-05", FpToString(1.299e-5f, 2));
+
+ EXPECT_EQ("-1", FpToString(-1.f));
+ EXPECT_EQ("-1.25", FpToString(-1.25f));
+ EXPECT_EQ("-34.34", FpToString(-34.34f));
+ EXPECT_EQ("-1e+20", FpToString(-1e+20f));
+ EXPECT_EQ("-1.1e+20", FpToString(-1.1e+20f));
+ EXPECT_EQ("-1e-20", FpToString(-1e-20f));
+ EXPECT_EQ("-1.1e-20", FpToString(-1.1e-20f));
+ EXPECT_EQ("-1e-20", FpToString(-0.1e-19f));
+ EXPECT_EQ("-1.1e-20", FpToString(-0.11e-19f));
+
+ EXPECT_EQ("-19", FpToString(-18.9f, 2));
+ EXPECT_EQ("-20", FpToString(-19.9f, 2));
+ EXPECT_EQ("-2e+01", FpToString(-19.9f, 1));
+ EXPECT_EQ("-1.2e-05", FpToString(-1.234e-5f, 2));
+ EXPECT_EQ("-1.3e-05", FpToString(-1.299e-5f, 2));
+}
+
+TEST(FpToStringTest, vulnerability_stack_buffer_overflow) {
+ EXPECT_EQ(FpToString(1.0e100, 200), "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
+}
+
+} // namespace
+} // namespace YAML
diff --git a/lib/yamlcpp/test/googletest-1.13.0/.clang-format b/lib/yamlcpp/test/googletest-1.13.0/.clang-format
new file mode 100644
index 0000000000..5b9bfe6d22
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/.clang-format
@@ -0,0 +1,4 @@
+# Run manually to reformat a file:
+# clang-format -i --style=file <file>
+Language: Cpp
+BasedOnStyle: Google
diff --git a/lib/yamlcpp/test/googletest-1.13.0/.github/ISSUE_TEMPLATE/00-bug_report.yml b/lib/yamlcpp/test/googletest-1.13.0/.github/ISSUE_TEMPLATE/00-bug_report.yml
new file mode 100644
index 0000000000..586779ad2d
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/.github/ISSUE_TEMPLATE/00-bug_report.yml
@@ -0,0 +1,53 @@
+name: Bug Report
+description: Let us know that something does not work as expected.
+title: "[Bug]: Please title this bug report"
+body:
+ - type: textarea
+ id: what-happened
+ attributes:
+ label: Describe the issue
+ description: What happened, and what did you expect to happen?
+ validations:
+ required: true
+ - type: textarea
+ id: steps
+ attributes:
+ label: Steps to reproduce the problem
+ description: It is important that we are able to reproduce the problem that you are experiencing. Please provide all code and relevant steps to reproduce the problem, including your `BUILD`/`CMakeLists.txt` file and build commands. Links to a GitHub branch or [godbolt.org](https://godbolt.org/) that demonstrate the problem are also helpful.
+ validations:
+ required: true
+ - type: textarea
+ id: version
+ attributes:
+ label: What version of GoogleTest are you using?
+ description: Please include the output of `git rev-parse HEAD` or the GoogleTest release version number that you are using.
+ validations:
+ required: true
+ - type: textarea
+ id: os
+ attributes:
+ label: What operating system and version are you using?
+ description: If you are using a Linux distribution please include the name and version of the distribution as well.
+ validations:
+ required: true
+ - type: textarea
+ id: compiler
+ attributes:
+ label: What compiler and version are you using?
+ description: Please include the output of `gcc -v` or `clang -v`, or the equivalent for your compiler.
+ validations:
+ required: true
+ - type: textarea
+ id: buildsystem
+ attributes:
+ label: What build system are you using?
+ description: Please include the output of `bazel --version` or `cmake --version`, or the equivalent for your build system.
+ validations:
+ required: true
+ - type: textarea
+ id: additional
+ attributes:
+ label: Additional context
+ description: Add any other context about the problem here.
+ validations:
+ required: false
diff --git a/lib/yamlcpp/test/googletest-1.13.0/.github/ISSUE_TEMPLATE/10-feature_request.yml b/lib/yamlcpp/test/googletest-1.13.0/.github/ISSUE_TEMPLATE/10-feature_request.yml
new file mode 100644
index 0000000000..91ad041770
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/.github/ISSUE_TEMPLATE/10-feature_request.yml
@@ -0,0 +1,33 @@
+name: Feature request
+description: Propose a new feature.
+title: "[FR]: Please title this feature request"
+labels: "enhancement"
+body:
+ - type: textarea
+ id: version
+ attributes:
+ label: Does the feature exist in the most recent commit?
+ description: We recommend using the latest commit from GitHub in your projects.
+ validations:
+ required: true
+ - type: textarea
+ id: why
+ attributes:
+ label: Why do we need this feature?
+ description: Ideally, explain why a combination of existing features cannot be used instead.
+ validations:
+ required: true
+ - type: textarea
+ id: proposal
+ attributes:
+ label: Describe the proposal.
+ description: Include a detailed description of the feature, with usage examples.
+ validations:
+ required: true
+ - type: textarea
+ id: platform
+ attributes:
+ label: Is the feature specific to an operating system, compiler, or build system version?
+ description: If it is, please specify which versions.
+ validations:
+ required: true
diff --git a/lib/yamlcpp/test/googletest-1.13.0/.github/ISSUE_TEMPLATE/config.yml b/lib/yamlcpp/test/googletest-1.13.0/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000..65170d10a7
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Get Help
+ url: https://github.com/google/googletest/discussions
+ about: Please ask and answer questions here.
diff --git a/lib/yamlcpp/test/googletest-1.13.0/.github/workflows/gtest-ci.yml b/lib/yamlcpp/test/googletest-1.13.0/.github/workflows/gtest-ci.yml
new file mode 100644
index 0000000000..03a8cc5e28
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/.github/workflows/gtest-ci.yml
@@ -0,0 +1,43 @@
+name: ci
+
+on:
+ push:
+ pull_request:
+
+env:
+ BAZEL_CXXOPTS: -std=c++14
+
+jobs:
+ Linux:
+ runs-on: ubuntu-latest
+ steps:
+
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: Tests
+ run: bazel test --cxxopt=-std=c++14 --features=external_include_paths --test_output=errors ...
+
+ macOS:
+ runs-on: macos-latest
+ steps:
+
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: Tests
+ run: bazel test --cxxopt=-std=c++14 --features=external_include_paths --test_output=errors ...
+
+
+ Windows:
+ runs-on: windows-latest
+ steps:
+
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: Tests
+ run: bazel test --cxxopt=/std:c++14 --features=external_include_paths --test_output=errors ...
diff --git a/lib/yamlcpp/test/googletest-1.13.0/.gitignore b/lib/yamlcpp/test/googletest-1.13.0/.gitignore
new file mode 100644
index 0000000000..f08cb72a33
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/.gitignore
@@ -0,0 +1,84 @@
+# Ignore CI build directory
+build/
+xcuserdata
+cmake-build-debug/
+.idea/
+bazel-bin
+bazel-genfiles
+bazel-googletest
+bazel-out
+bazel-testlogs
+# python
+*.pyc
+
+# Visual Studio files
+.vs
+*.sdf
+*.opensdf
+*.VC.opendb
+*.suo
+*.user
+_ReSharper.Caches/
+Win32-Debug/
+Win32-Release/
+x64-Debug/
+x64-Release/
+
+# Ignore autoconf / automake files
+Makefile.in
+aclocal.m4
+configure
+build-aux/
+autom4te.cache/
+googletest/m4/libtool.m4
+googletest/m4/ltoptions.m4
+googletest/m4/ltsugar.m4
+googletest/m4/ltversion.m4
+googletest/m4/lt~obsolete.m4
+googlemock/m4
+
+# Ignore generated directories.
+googlemock/fused-src/
+googletest/fused-src/
+
+# macOS files
+.DS_Store
+googletest/.DS_Store
+googletest/xcode/.DS_Store
+
+# Ignore cmake generated directories and files.
+CMakeFiles
+CTestTestfile.cmake
+Makefile
+cmake_install.cmake
+googlemock/CMakeFiles
+googlemock/CTestTestfile.cmake
+googlemock/Makefile
+googlemock/cmake_install.cmake
+googlemock/gtest
+/bin
+/googlemock/gmock.dir
+/googlemock/gmock_main.dir
+/googlemock/RUN_TESTS.vcxproj.filters
+/googlemock/RUN_TESTS.vcxproj
+/googlemock/INSTALL.vcxproj.filters
+/googlemock/INSTALL.vcxproj
+/googlemock/gmock_main.vcxproj.filters
+/googlemock/gmock_main.vcxproj
+/googlemock/gmock.vcxproj.filters
+/googlemock/gmock.vcxproj
+/googlemock/gmock.sln
+/googlemock/ALL_BUILD.vcxproj.filters
+/googlemock/ALL_BUILD.vcxproj
+/lib
+/Win32
+/ZERO_CHECK.vcxproj.filters
+/ZERO_CHECK.vcxproj
+/RUN_TESTS.vcxproj.filters
+/RUN_TESTS.vcxproj
+/INSTALL.vcxproj.filters
+/INSTALL.vcxproj
+/googletest-distribution.sln
+/CMakeCache.txt
+/ALL_BUILD.vcxproj.filters
+/ALL_BUILD.vcxproj
diff --git a/lib/yamlcpp/test/googletest-1.13.0/BUILD.bazel b/lib/yamlcpp/test/googletest-1.13.0/BUILD.bazel
new file mode 100644
index 0000000000..ac62251e10
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/BUILD.bazel
@@ -0,0 +1,218 @@
+# Copyright 2017 Google Inc.
+# All Rights Reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Bazel Build for Google C++ Testing Framework(Google Test)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+exports_files(["LICENSE"])
+
+config_setting(
+ name = "qnx",
+ constraint_values = ["@platforms//os:qnx"],
+)
+
+config_setting(
+ name = "windows",
+ constraint_values = ["@platforms//os:windows"],
+)
+
+config_setting(
+ name = "freebsd",
+ constraint_values = ["@platforms//os:freebsd"],
+)
+
+config_setting(
+ name = "openbsd",
+ constraint_values = ["@platforms//os:openbsd"],
+)
+
+config_setting(
+ name = "msvc_compiler",
+ flag_values = {
+ "@bazel_tools//tools/cpp:compiler": "msvc-cl",
+ },
+ visibility = [":__subpackages__"],
+)
+
+config_setting(
+ name = "has_absl",
+ values = {"define": "absl=1"},
+)
+
+# Library that defines the FRIEND_TEST macro.
+cc_library(
+ name = "gtest_prod",
+ hdrs = ["googletest/include/gtest/gtest_prod.h"],
+ includes = ["googletest/include"],
+)
+
+# Google Test including Google Mock
+cc_library(
+ name = "gtest",
+ srcs = glob(
+ include = [
+ "googletest/src/*.cc",
+ "googletest/src/*.h",
+ "googletest/include/gtest/**/*.h",
+ "googlemock/src/*.cc",
+ "googlemock/include/gmock/**/*.h",
+ ],
+ exclude = [
+ "googletest/src/gtest-all.cc",
+ "googletest/src/gtest_main.cc",
+ "googlemock/src/gmock-all.cc",
+ "googlemock/src/gmock_main.cc",
+ ],
+ ),
+ hdrs = glob([
+ "googletest/include/gtest/*.h",
+ "googlemock/include/gmock/*.h",
+ ]),
+ copts = select({
+ ":qnx": [],
+ ":windows": [],
+ "//conditions:default": ["-pthread"],
+ }),
+ defines = select({
+ ":has_absl": ["GTEST_HAS_ABSL=1"],
+ "//conditions:default": [],
+ }),
+ features = select({
+ ":windows": ["windows_export_all_symbols"],
+ "//conditions:default": [],
+ }),
+ includes = [
+ "googlemock",
+ "googlemock/include",
+ "googletest",
+ "googletest/include",
+ ],
+ linkopts = select({
+ ":qnx": ["-lregex"],
+ ":windows": [],
+ ":freebsd": [
+ "-lm",
+ "-pthread",
+ ],
+ ":openbsd": [
+ "-lm",
+ "-pthread",
+ ],
+ "//conditions:default": ["-pthread"],
+ }),
+ deps = select({
+ ":has_absl": [
+ "@com_google_absl//absl/debugging:failure_signal_handler",
+ "@com_google_absl//absl/debugging:stacktrace",
+ "@com_google_absl//absl/debugging:symbolize",
+ "@com_google_absl//absl/flags:flag",
+ "@com_google_absl//absl/flags:parse",
+ "@com_google_absl//absl/flags:reflection",
+ "@com_google_absl//absl/flags:usage",
+ "@com_google_absl//absl/strings",
+ "@com_google_absl//absl/types:any",
+ "@com_google_absl//absl/types:optional",
+ "@com_google_absl//absl/types:variant",
+ "@com_googlesource_code_re2//:re2",
+ ],
+ "//conditions:default": [],
+ }),
+)
+
+cc_library(
+ name = "gtest_main",
+ srcs = ["googlemock/src/gmock_main.cc"],
+ features = select({
+ ":windows": ["windows_export_all_symbols"],
+ "//conditions:default": [],
+ }),
+ deps = [":gtest"],
+)
+
+# The following rules build samples of how to use gTest.
+cc_library(
+ name = "gtest_sample_lib",
+ srcs = [
+ "googletest/samples/sample1.cc",
+ "googletest/samples/sample2.cc",
+ "googletest/samples/sample4.cc",
+ ],
+ hdrs = [
+ "googletest/samples/prime_tables.h",
+ "googletest/samples/sample1.h",
+ "googletest/samples/sample2.h",
+ "googletest/samples/sample3-inl.h",
+ "googletest/samples/sample4.h",
+ ],
+ features = select({
+ ":windows": ["windows_export_all_symbols"],
+ "//conditions:default": [],
+ }),
+)
+
+cc_test(
+ name = "gtest_samples",
+ size = "small",
+ # All Samples except:
+ # sample9 (main)
+ # sample10 (main and takes a command line option and needs to be separate)
+ srcs = [
+ "googletest/samples/sample1_unittest.cc",
+ "googletest/samples/sample2_unittest.cc",
+ "googletest/samples/sample3_unittest.cc",
+ "googletest/samples/sample4_unittest.cc",
+ "googletest/samples/sample5_unittest.cc",
+ "googletest/samples/sample6_unittest.cc",
+ "googletest/samples/sample7_unittest.cc",
+ "googletest/samples/sample8_unittest.cc",
+ ],
+ linkstatic = 0,
+ deps = [
+ "gtest_sample_lib",
+ ":gtest_main",
+ ],
+)
+
+cc_test(
+ name = "sample9_unittest",
+ size = "small",
+ srcs = ["googletest/samples/sample9_unittest.cc"],
+ deps = [":gtest"],
+)
+
+cc_test(
+ name = "sample10_unittest",
+ size = "small",
+ srcs = ["googletest/samples/sample10_unittest.cc"],
+ deps = [":gtest"],
+)
diff --git a/lib/yamlcpp/test/googletest-1.13.0/CMakeLists.txt b/lib/yamlcpp/test/googletest-1.13.0/CMakeLists.txt
new file mode 100644
index 0000000000..6af414371f
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/CMakeLists.txt
@@ -0,0 +1,39 @@
+# Note: CMake support is community-based. The maintainers do not use CMake
+# internally.
+
+cmake_minimum_required(VERSION 3.5)
+
+if (POLICY CMP0048)
+ cmake_policy(SET CMP0048 NEW)
+endif (POLICY CMP0048)
+
+if (POLICY CMP0069)
+ cmake_policy(SET CMP0069 NEW)
+endif (POLICY CMP0069)
+
+if (POLICY CMP0077)
+ cmake_policy(SET CMP0077 NEW)
+endif (POLICY CMP0077)
+
+project(googletest-distribution)
+set(GOOGLETEST_VERSION 1.13.0)
+
+if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX)
+ set(CMAKE_CXX_EXTENSIONS OFF)
+endif()
+
+enable_testing()
+
+include(CMakeDependentOption)
+include(GNUInstallDirs)
+
+#Note that googlemock target already builds googletest
+option(BUILD_GMOCK "Builds the googlemock subproject" ON)
+option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON)
+option(GTEST_HAS_ABSL "Use Abseil and RE2. Requires Abseil and RE2 to be separately added to the build." OFF)
+
+if(BUILD_GMOCK)
+ add_subdirectory( googlemock )
+else()
+ add_subdirectory( googletest )
+endif()
diff --git a/lib/yamlcpp/test/googletest-1.13.0/CONTRIBUTING.md b/lib/yamlcpp/test/googletest-1.13.0/CONTRIBUTING.md
new file mode 100644
index 0000000000..de14c8159b
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/CONTRIBUTING.md
@@ -0,0 +1,131 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your patches! Before we can take them, we have to jump a
+couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement
+(CLA).
+
+* If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an
+ [individual CLA](https://developers.google.com/open-source/cla/individual).
+* If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a
+ [corporate CLA](https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Are you a Googler?
+
+If you are a Googler, please make an attempt to submit an internal contribution
+rather than a GitHub Pull Request. If you are not able to submit internally, a
+PR is acceptable as an alternative.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the
+ [issue tracker](https://github.com/google/googletest/issues).
+2. Please don't mix more than one logical change per submittal, because it
+ makes the history hard to follow. If you want to make a change that doesn't
+ have a corresponding issue in the issue tracker, please create one.
+3. Also, coordinate with team members that are listed on the issue in question.
+ This ensures that work isn't being duplicated and communicating your plan
+ early also generally leads to better patches.
+4. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement
+ ([see details above](#contributor-license-agreements)).
+5. Fork the desired repo, develop and test your code changes.
+6. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing.
+7. Ensure that your code has an appropriate set of unit tests which all pass.
+8. Submit a pull request.
+
+## The Google Test and Google Mock Communities
+
+The Google Test community exists primarily through the
+[discussion group](http://groups.google.com/group/googletestframework) and the
+GitHub repository. Likewise, the Google Mock community exists primarily through
+their own [discussion group](http://groups.google.com/group/googlemock). You are
+definitely encouraged to contribute to the discussion and you can also help us
+to keep the effectiveness of the group high by following and promoting the
+guidelines listed here.
+
+### Please Be Friendly
+
+Showing courtesy and respect to others is a vital part of the Google culture,
+and we strongly encourage everyone participating in Google Test development to
+join us in accepting nothing less. Of course, being courteous is not the same as
+failing to constructively disagree with each other, but it does mean that we
+should be respectful of each other when enumerating the 42 technical reasons
+that a particular proposal may not be the best choice. There's never a reason to
+be antagonistic or dismissive toward anyone who is sincerely trying to
+contribute to a discussion.
+
+Sure, C++ testing is serious business and all that, but it's also a lot of fun.
+Let's keep it that way. Let's strive to be one of the friendliest communities in
+all of open source.
+
+As always, discuss Google Test in the official GoogleTest discussion group. You
+don't have to actually submit code in order to sign up. Your participation
+itself is a valuable contribution.
+
+## Style
+
+To keep the source consistent, readable, diffable and easy to merge, we use a
+fairly rigid coding style, as defined by the
+[google-styleguide](https://github.com/google/styleguide) project. All patches
+will be expected to conform to the style outlined
+[here](https://google.github.io/styleguide/cppguide.html). Use
+[.clang-format](https://github.com/google/googletest/blob/main/.clang-format) to
+check your formatting.
+
+## Requirements for Contributors
+
+If you plan to contribute a patch, you need to build Google Test, Google Mock,
+and their own tests from a git checkout, which has further requirements:
+
+* [Python](https://www.python.org/) v2.3 or newer (for running some of the
+ tests and re-generating certain source files from templates)
+* [CMake](https://cmake.org/) v2.8.12 or newer
+
+## Developing Google Test and Google Mock
+
+This section discusses how to make your own changes to the Google Test project.
+
+### Testing Google Test and Google Mock Themselves
+
+To make sure your changes work as intended and don't break existing
+functionality, you'll want to compile and run Google Test and GoogleMock's own
+tests. For that you can use CMake:
+
+ mkdir mybuild
+ cd mybuild
+ cmake -Dgtest_build_tests=ON -Dgmock_build_tests=ON ${GTEST_REPO_DIR}
+
+To choose between building only Google Test or Google Mock, you may modify your
+cmake command to be one of each
+
+ cmake -Dgtest_build_tests=ON ${GTEST_DIR} # sets up Google Test tests
+ cmake -Dgmock_build_tests=ON ${GMOCK_DIR} # sets up Google Mock tests
+
+Make sure you have Python installed, as some of Google Test's tests are written
+in Python. If the cmake command complains about not being able to find Python
+(`Could NOT find PythonInterp (missing: PYTHON_EXECUTABLE)`), try telling it
+explicitly where your Python executable can be found:
+
+ cmake -DPYTHON_EXECUTABLE=path/to/python ...
+
+Next, you can build Google Test and / or Google Mock and all desired tests. On
+\*nix, this is usually done by
+
+ make
+
+To run the tests, do
+
+ make test
+
+All tests should pass.
diff --git a/lib/yamlcpp/test/googletest-1.13.0/CONTRIBUTORS b/lib/yamlcpp/test/googletest-1.13.0/CONTRIBUTORS
new file mode 100644
index 0000000000..77397a5b53
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/CONTRIBUTORS
@@ -0,0 +1,65 @@
+# This file contains a list of people who've made non-trivial
+# contribution to the Google C++ Testing Framework project. People
+# who commit code to the project are encouraged to add their names
+# here. Please keep the list sorted by first names.
+
+Ajay Joshi <ja...@google.com>
+Balázs Dán <ba...@gmail.com>
+Benoit Sigoure <ts...@google.com>
+Bharat Mediratta <bh...@menalto.com>
+Bogdan Piloca <bo...@google.com>
+Chandler Carruth <ch...@google.com>
+Chris Prince <cp...@google.com>
+Chris Taylor <ta...@google.com>
+Dan Egnor <eg...@google.com>
+Dave MacLachlan <dm...@gmail.com>
+David Anderson <da...@google.com>
+Dean Sturtevant
+Eric Roman <er...@chromium.org>
+Gene Volovich <gv...@cite.com>
+Hady Zalek <ha...@gmail.com>
+Hal Burch <gm...@hburch.com>
+Jeffrey Yasskin <jy...@google.com>
+Jim Keller <ji...@google.com>
+Joe Walnes <jo...@truemesh.com>
+Jon Wray <jw...@google.com>
+Jói Sigurðsson <jo...@google.com>
+Keir Mierle <mi...@gmail.com>
+Keith Ray <ke...@gmail.com>
+Kenton Varda <ke...@google.com>
+Kostya Serebryany <kc...@google.com>
+Krystian Kuzniarek <kr...@gmail.com>
+Lev Makhlis
+Manuel Klimek <kl...@google.com>
+Mario Tanev <ra...@google.com>
+Mark Paskin
+Markus Heule <ma...@gmail.com>
+Martijn Vels <mv...@google.com>
+Matthew Simmons <si...@acm.org>
+Mika Raento <mi...@iki.fi>
+Mike Bland <mb...@google.com>
+Miklós Fazekas <mf...@szemafor.com>
+Neal Norwitz <nn...@gmail.com>
+Nermin Ozkiranartli <ne...@google.com>
+Owen Carlsen <oc...@google.com>
+Paneendra Ba <pa...@google.com>
+Pasi Valminen <pa...@gmail.com>
+Patrick Hanna <ph...@google.com>
+Patrick Riley <pf...@google.com>
+Paul Menage <me...@google.com>
+Peter Kaminski <pi...@google.com>
+Piotr Kaminski <pi...@google.com>
+Preston Jackson <pr...@gmail.com>
+Rainer Klaffenboeck <ra...@dynatrace.com>
+Russ Cox <rs...@google.com>
+Russ Rufer <ru...@pentad.com>
+Sean Mcafee <ee...@gmail.com>
+Sigurður Ásgeirsson <si...@google.com>
+Sverre Sundsdal <su...@gmail.com>
+Szymon Sobik <so...@gmail.com>
+Takeshi Yoshino <ty...@google.com>
+Tracy Bialik <tr...@pentad.com>
+Vadim Berman <va...@google.com>
+Vlad Losev <vl...@google.com>
+Wolfgang Klier <wk...@google.com>
+Zhanyong Wan <wa...@google.com>
diff --git a/lib/yamlcpp/test/googletest-1.13.0/LICENSE b/lib/yamlcpp/test/googletest-1.13.0/LICENSE
new file mode 100644
index 0000000000..1941a11f8c
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/LICENSE
@@ -0,0 +1,28 @@
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/lib/yamlcpp/test/googletest-1.13.0/README.md b/lib/yamlcpp/test/googletest-1.13.0/README.md
new file mode 100644
index 0000000000..cd89abb2d2
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/README.md
@@ -0,0 +1,117 @@
+# GoogleTest
+
+### Announcements
+
+#### Live at Head
+
+GoogleTest now follows the
+[Abseil Live at Head philosophy](https://abseil.io/about/philosophy#upgrade-support).
+We recommend
+[updating to the latest commit in the `main` branch as often as possible](https://github.com/abseil/abseil-cpp/blob/master/FAQ.md#what-is-live-at-head-and-how-do-i-do-it).
+
+#### Documentation Updates
+
+Our documentation is now live on GitHub Pages at
+https://google.github.io/googletest/. We recommend browsing the documentation on
+GitHub Pages rather than directly in the repository.
+
+#### Release 1.12.1
+
+[Release 1.12.1](https://github.com/google/googletest/releases/tag/release-1.12.1)
+is now available.
+
+The 1.12.x branch will be the last to support C++11. Future releases will
+require at least C++14.
+
+#### Coming Soon
+
+* We are planning to take a dependency on
+ [Abseil](https://github.com/abseil/abseil-cpp).
+* More documentation improvements are planned.
+
+## Welcome to **GoogleTest**, Google's C++ test framework!
+
+This repository is a merger of the formerly separate GoogleTest and GoogleMock
+projects. These were so closely related that it makes sense to maintain and
+release them together.
+
+### Getting Started
+
+See the [GoogleTest User's Guide](https://google.github.io/googletest/) for
+documentation. We recommend starting with the
+[GoogleTest Primer](https://google.github.io/googletest/primer.html).
+
+More information about building GoogleTest can be found at
+[googletest/README.md](googletest/README.md).
+
+## Features
+
+* An [xUnit](https://en.wikipedia.org/wiki/XUnit) test framework.
+* Test discovery.
+* A rich set of assertions.
+* User-defined assertions.
+* Death tests.
+* Fatal and non-fatal failures.
+* Value-parameterized tests.
+* Type-parameterized tests.
+* Various options for running the tests.
+* XML test report generation.
+
+## Supported Platforms
+
+GoogleTest follows Google's
+[Foundational C++ Support Policy](https://opensource.google/documentation/policies/cplusplus-support).
+See
+[this table](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md)
+for a list of currently supported versions compilers, platforms, and build
+tools.
+
+## Who Is Using GoogleTest?
+
+In addition to many internal projects at Google, GoogleTest is also used by the
+following notable projects:
+
+* The [Chromium projects](http://www.chromium.org/) (behind the Chrome browser
+ and Chrome OS).
+* The [LLVM](http://llvm.org/) compiler.
+* [Protocol Buffers](https://github.com/google/protobuf), Google's data
+ interchange format.
+* The [OpenCV](http://opencv.org/) computer vision library.
+
+## Related Open Source Projects
+
+[GTest Runner](https://github.com/nholthaus/gtest-runner) is a Qt5 based
+automated test-runner and Graphical User Interface with powerful features for
+Windows and Linux platforms.
+
+[GoogleTest UI](https://github.com/ospector/gtest-gbar) is a test runner that
+runs your test binary, allows you to track its progress via a progress bar, and
+displays a list of test failures. Clicking on one shows failure text. GoogleTest
+UI is written in C#.
+
+[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event
+listener for GoogleTest that implements the
+[TAP protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol) for test
+result output. If your test runner understands TAP, you may find it useful.
+
+[gtest-parallel](https://github.com/google/gtest-parallel) is a test runner that
+runs tests from your binary in parallel to provide significant speed-up.
+
+[GoogleTest Adapter](https://marketplace.visualstudio.com/items?itemName=DavidSchuldenfrei.gtest-adapter)
+is a VS Code extension allowing to view GoogleTest in a tree view and run/debug
+your tests.
+
+[C++ TestMate](https://github.com/matepek/vscode-catch2-test-adapter) is a VS
+Code extension allowing to view GoogleTest in a tree view and run/debug your
+tests.
+
+[Cornichon](https://pypi.org/project/cornichon/) is a small Gherkin DSL parser
+that generates stub code for GoogleTest.
+
+## Contributing Changes
+
+Please read
+[`CONTRIBUTING.md`](https://github.com/google/googletest/blob/main/CONTRIBUTING.md)
+for details on how to contribute to this project.
+
+Happy testing!
diff --git a/lib/yamlcpp/test/googletest-1.13.0/WORKSPACE b/lib/yamlcpp/test/googletest-1.13.0/WORKSPACE
new file mode 100644
index 0000000000..0f10a6a9a8
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/WORKSPACE
@@ -0,0 +1,40 @@
+workspace(name = "com_google_googletest")
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+ name = "com_google_absl", # 2023-01-10T21:08:25Z
+ sha256 = "f9a4e749f42c386a32a90fddf0e2913ed408d10c42f7f33ccf4c59ac4f0d1d05",
+ strip_prefix = "abseil-cpp-52835439ca90d86b27bf8cd1708296e95604d724",
+ urls = ["https://github.com/abseil/abseil-cpp/archive/52835439ca90d86b27bf8cd1708296e95604d724.zip"],
+)
+
+# Note this must use a commit from the `abseil` branch of the RE2 project.
+# https://github.com/google/re2/tree/abseil
+http_archive(
+ name = "com_googlesource_code_re2", # 2022-12-21T14:29:10Z
+ sha256 = "b9ce3a51beebb38534d11d40f8928d40509b9e18a735f6a4a97ad3d014c87cb5",
+ strip_prefix = "re2-d0b1f8f2ecc2ea74956c7608b6f915175314ff0e",
+ urls = ["https://github.com/google/re2/archive/d0b1f8f2ecc2ea74956c7608b6f915175314ff0e.zip"],
+)
+
+http_archive(
+ name = "rules_python", # 2023-01-10T22:00:51Z
+ sha256 = "5de54486a60ad8948dabe49605bb1c08053e04001a431ab3e96745b4d97a4419",
+ strip_prefix = "rules_python-70cce26432187a60b4e950118791385e6fb3c26f",
+ urls = ["https://github.com/bazelbuild/rules_python/archive/70cce26432187a60b4e950118791385e6fb3c26f.zip"],
+)
+
+http_archive(
+ name = "bazel_skylib", # 2022-11-16T18:29:32Z
+ sha256 = "a22290c26d29d3ecca286466f7f295ac6cbe32c0a9da3a91176a90e0725e3649",
+ strip_prefix = "bazel-skylib-5bfcb1a684550626ce138fe0fe8f5f702b3764c3",
+ urls = ["https://github.com/bazelbuild/bazel-skylib/archive/5bfcb1a684550626ce138fe0fe8f5f702b3764c3.zip"],
+)
+
+http_archive(
+ name = "platforms", # 2022-11-09T19:18:22Z
+ sha256 = "b4a3b45dc4202e2b3e34e3bc49d2b5b37295fc23ea58d88fb9e01f3642ad9b55",
+ strip_prefix = "platforms-3fbc687756043fb58a407c2ea8c944bc2fe1d922",
+ urls = ["https://github.com/bazelbuild/platforms/archive/3fbc687756043fb58a407c2ea8c944bc2fe1d922.zip"],
+)
diff --git a/lib/yamlcpp/test/googletest-1.13.0/ci/linux-presubmit.sh b/lib/yamlcpp/test/googletest-1.13.0/ci/linux-presubmit.sh
new file mode 100644
index 0000000000..4eb5bbe4a1
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/ci/linux-presubmit.sh
@@ -0,0 +1,134 @@
+#!/bin/bash
+#
+# Copyright 2020, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -euox pipefail
+
+readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20220217"
+readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20220621"
+
+if [[ -z ${GTEST_ROOT:-} ]]; then
+ GTEST_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+if [[ -z ${STD:-} ]]; then
+ STD="c++14 c++17 c++20"
+fi
+
+# Test the CMake build
+for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do
+ for cmake_off_on in OFF ON; do
+ time docker run \
+ --volume="${GTEST_ROOT}:/src:ro" \
+ --tmpfs="/build:exec" \
+ --workdir="/build" \
+ --rm \
+ --env="CC=${cc}" \
+ --env="CXX_FLAGS=\"-Werror -Wdeprecated\"" \
+ ${LINUX_LATEST_CONTAINER} \
+ /bin/bash -c "
+ cmake /src \
+ -DCMAKE_CXX_STANDARD=14 \
+ -Dgtest_build_samples=ON \
+ -Dgtest_build_tests=ON \
+ -Dgmock_build_tests=ON \
+ -Dcxx_no_exception=${cmake_off_on} \
+ -Dcxx_no_rtti=${cmake_off_on} && \
+ make -j$(nproc) && \
+ ctest -j$(nproc) --output-on-failure"
+ done
+done
+
+# Do one test with an older version of GCC
+time docker run \
+ --volume="${GTEST_ROOT}:/src:ro" \
+ --workdir="/src" \
+ --rm \
+ --env="CC=/usr/local/bin/gcc" \
+ --env="BAZEL_CXXOPTS=-std=c++14" \
+ ${LINUX_GCC_FLOOR_CONTAINER} \
+ /usr/local/bin/bazel test ... \
+ --copt="-Wall" \
+ --copt="-Werror" \
+ --copt="-Wuninitialized" \
+ --copt="-Wno-error=pragmas" \
+ --distdir="/bazel-distdir" \
+ --features=external_include_paths \
+ --keep_going \
+ --show_timestamps \
+ --test_output=errors
+
+# Test GCC
+for std in ${STD}; do
+ for absl in 0 1; do
+ time docker run \
+ --volume="${GTEST_ROOT}:/src:ro" \
+ --workdir="/src" \
+ --rm \
+ --env="CC=/usr/local/bin/gcc" \
+ --env="BAZEL_CXXOPTS=-std=${std}" \
+ ${LINUX_LATEST_CONTAINER} \
+ /usr/local/bin/bazel test ... \
+ --copt="-Wall" \
+ --copt="-Werror" \
+ --copt="-Wuninitialized" \
+ --define="absl=${absl}" \
+ --distdir="/bazel-distdir" \
+ --features=external_include_paths \
+ --keep_going \
+ --show_timestamps \
+ --test_output=errors
+ done
+done
+
+# Test Clang
+for std in ${STD}; do
+ for absl in 0 1; do
+ time docker run \
+ --volume="${GTEST_ROOT}:/src:ro" \
+ --workdir="/src" \
+ --rm \
+ --env="CC=/opt/llvm/clang/bin/clang" \
+ --env="BAZEL_CXXOPTS=-std=${std}" \
+ ${LINUX_LATEST_CONTAINER} \
+ /usr/local/bin/bazel test ... \
+ --copt="--gcc-toolchain=/usr/local" \
+ --copt="-Wall" \
+ --copt="-Werror" \
+ --copt="-Wuninitialized" \
+ --define="absl=${absl}" \
+ --distdir="/bazel-distdir" \
+ --features=external_include_paths \
+ --keep_going \
+ --linkopt="--gcc-toolchain=/usr/local" \
+ --show_timestamps \
+ --test_output=errors
+ done
+done
diff --git a/lib/yamlcpp/test/googletest-1.13.0/ci/macos-presubmit.sh b/lib/yamlcpp/test/googletest-1.13.0/ci/macos-presubmit.sh
new file mode 100644
index 0000000000..8f35df58d2
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/ci/macos-presubmit.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+#
+# Copyright 2020, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -euox pipefail
+
+if [[ -z ${GTEST_ROOT:-} ]]; then
+ GTEST_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+# Test the CMake build
+for cmake_off_on in OFF ON; do
+ BUILD_DIR=$(mktemp -d build_dir.XXXXXXXX)
+ cd ${BUILD_DIR}
+ time cmake ${GTEST_ROOT} \
+ -DCMAKE_CXX_STANDARD=14 \
+ -Dgtest_build_samples=ON \
+ -Dgtest_build_tests=ON \
+ -Dgmock_build_tests=ON \
+ -Dcxx_no_exception=${cmake_off_on} \
+ -Dcxx_no_rtti=${cmake_off_on}
+ time make
+ time ctest -j$(nproc) --output-on-failure
+done
+
+# Test the Bazel build
+
+# If we are running on Kokoro, check for a versioned Bazel binary.
+KOKORO_GFILE_BAZEL_BIN="bazel-5.1.1-darwin-x86_64"
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
+ BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
+ chmod +x ${BAZEL_BIN}
+else
+ BAZEL_BIN="bazel"
+fi
+
+cd ${GTEST_ROOT}
+for absl in 0 1; do
+ ${BAZEL_BIN} test ... \
+ --copt="-Wall" \
+ --copt="-Werror" \
+ --cxxopt="-std=c++14" \
+ --define="absl=${absl}" \
+ --features=external_include_paths \
+ --keep_going \
+ --show_timestamps \
+ --test_output=errors
+done
diff --git a/lib/yamlcpp/test/googletest-1.13.0/ci/windows-presubmit.bat b/lib/yamlcpp/test/googletest-1.13.0/ci/windows-presubmit.bat
new file mode 100644
index 0000000000..8668ff3594
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/ci/windows-presubmit.bat
@@ -0,0 +1,56 @@
+SETLOCAL ENABLEDELAYEDEXPANSION
+
+SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-5.1.1-windows-x86_64.exe
+
+SET PATH=C:\Python37;%PATH%
+SET BAZEL_PYTHON=C:\python37\python.exe
+SET BAZEL_SH=C:\tools\msys64\usr\bin\bash.exe
+SET CMAKE_BIN="C:\Program Files\CMake\bin\cmake.exe"
+SET CTEST_BIN="C:\Program Files\CMake\bin\ctest.exe"
+SET CTEST_OUTPUT_ON_FAILURE=1
+
+IF EXIST git\googletest (
+ CD git\googletest
+) ELSE IF EXIST github\googletest (
+ CD github\googletest
+)
+
+IF %errorlevel% neq 0 EXIT /B 1
+
+:: ----------------------------------------------------------------------------
+:: CMake Visual Studio 15 2017 Win64
+MKDIR cmake_msvc2017
+CD cmake_msvc2017
+
+%CMAKE_BIN% .. ^
+ -G "Visual Studio 15 2017 Win64" ^
+ -DPYTHON_EXECUTABLE:FILEPATH=c:\python37\python.exe ^
+ -DPYTHON_INCLUDE_DIR:PATH=c:\python37\include ^
+ -DPYTHON_LIBRARY:FILEPATH=c:\python37\lib\site-packages\pip ^
+ -Dgtest_build_samples=ON ^
+ -Dgtest_build_tests=ON ^
+ -Dgmock_build_tests=ON
+IF %errorlevel% neq 0 EXIT /B 1
+
+%CMAKE_BIN% --build . --target ALL_BUILD --config Debug -- -maxcpucount
+IF %errorlevel% neq 0 EXIT /B 1
+
+%CTEST_BIN% -C Debug --timeout 600
+IF %errorlevel% neq 0 EXIT /B 1
+
+CD ..
+RMDIR /S /Q cmake_msvc2017
+
+:: ----------------------------------------------------------------------------
+:: Bazel Visual Studio 15 2017 Win64
+
+SET BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC
+%BAZEL_EXE% test ... ^
+ --compilation_mode=dbg ^
+ --copt=/std:c++14 ^
+ --copt=/WX ^
+ --features=external_include_paths ^
+ --keep_going ^
+ --test_output=errors ^
+ --test_tag_filters=-no_test_msvc2017
+IF %errorlevel% neq 0 EXIT /B 1
diff --git a/lib/yamlcpp/test/googletest-1.13.0/docs/_config.yml b/lib/yamlcpp/test/googletest-1.13.0/docs/_config.yml
new file mode 100644
index 0000000000..d12867eab6
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/docs/_config.yml
@@ -0,0 +1 @@
+title: GoogleTest
diff --git a/lib/yamlcpp/test/googletest-1.13.0/docs/_data/navigation.yml b/lib/yamlcpp/test/googletest-1.13.0/docs/_data/navigation.yml
new file mode 100644
index 0000000000..9f3332708e
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/docs/_data/navigation.yml
@@ -0,0 +1,43 @@
+nav:
+- section: "Get Started"
+ items:
+ - title: "Supported Platforms"
+ url: "/platforms.html"
+ - title: "Quickstart: Bazel"
+ url: "/quickstart-bazel.html"
+ - title: "Quickstart: CMake"
+ url: "/quickstart-cmake.html"
+- section: "Guides"
+ items:
+ - title: "GoogleTest Primer"
+ url: "/primer.html"
+ - title: "Advanced Topics"
+ url: "/advanced.html"
+ - title: "Mocking for Dummies"
+ url: "/gmock_for_dummies.html"
+ - title: "Mocking Cookbook"
+ url: "/gmock_cook_book.html"
+ - title: "Mocking Cheat Sheet"
+ url: "/gmock_cheat_sheet.html"
+- section: "References"
+ items:
+ - title: "Testing Reference"
+ url: "/reference/testing.html"
+ - title: "Mocking Reference"
+ url: "/reference/mocking.html"
+ - title: "Assertions"
+ url: "/reference/assertions.html"
+ - title: "Matchers"
+ url: "/reference/matchers.html"
+ - title: "Actions"
+ url: "/reference/actions.html"
+ - title: "Testing FAQ"
+ url: "/faq.html"
+ - title: "Mocking FAQ"
+ url: "/gmock_faq.html"
+ - title: "Code Samples"
+ url: "/samples.html"
+ - title: "Using pkg-config"
+ url: "/pkgconfig.html"
+ - title: "Community Documentation"
+ url: "/community_created_documentation.html"
diff --git a/lib/yamlcpp/test/googletest-1.13.0/docs/_layouts/default.html b/lib/yamlcpp/test/googletest-1.13.0/docs/_layouts/default.html
new file mode 100644
index 0000000000..c7f331b87d
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/docs/_layouts/default.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html lang="{{ site.lang | default: "en-US" }}">
+ <head>
+ <meta charset="UTF-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+{% seo %}
+ <link rel="stylesheet" href="{{ "/assets/css/style.css?v=" | append: site.github.build_revision | relative_url }}">
+ <script>
+ window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
+ ga('create', 'UA-197576187-1', { 'storage': 'none' });
+ ga('set', 'referrer', document.referrer.split('?')[0]);
+ ga('set', 'location', window.location.href.split('?')[0]);
+ ga('set', 'anonymizeIp', true);
+ ga('send', 'pageview');
+ </script>
+ <script async src='https://www.google-analytics.com/analytics.js'></script>
+ </head>
+ <body>
+ <div class="sidebar">
+ <div class="header">
+ <h1><a href="{{ "/" | relative_url }}">{{ site.title | default: "Documentation" }}</a></h1>
+ </div>
+ <input type="checkbox" id="nav-toggle" class="nav-toggle">
+ <label for="nav-toggle" class="expander">
+ <span class="arrow"></span>
+ </label>
+ <nav>
+ {% for item in site.data.navigation.nav %}
+ <h2>{{ item.section }}</h2>
+ <ul>
+ {% for subitem in item.items %}
+ <a href="{{subitem.url | relative_url }}">
+ <li class="{% if subitem.url == page.url %}active{% endif %}">
+ {{ subitem.title }}
+ </li>
+ </a>
+ {% endfor %}
+ </ul>
+ {% endfor %}
+ </nav>
+ </div>
+ <div class="main markdown-body">
+ <div class="main-inner">
+ {{ content }}
+ </div>
+ <div class="footer">
+ GoogleTest ·
+ <a href="https://github.com/google/googletest">GitHub Repository</a> ·
+ <a href="https://github.com/google/googletest/blob/main/LICENSE">License</a> ·
+ <a href="https://policies.google.com/privacy">Privacy Policy</a>
+ </div>
+ </div>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/anchor-js/4.1.0/anchor.min.js" integrity="sha256-lZaRhKri35AyJSypXXs4o6OPFTbTmUoltBbDCbdzegg=" crossorigin="anonymous"></script>
+ <script>anchors.add('.main h2, .main h3, .main h4, .main h5, .main h6');</script>
+ </body>
+</html>
diff --git a/lib/yamlcpp/test/googletest-1.13.0/docs/_sass/main.scss b/lib/yamlcpp/test/googletest-1.13.0/docs/_sass/main.scss
new file mode 100644
index 0000000000..92edc877a5
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/docs/_sass/main.scss
@@ -0,0 +1,200 @@
+// Styles for GoogleTest docs website on GitHub Pages.
+// Color variables are defined in
+// https://github.com/pages-themes/primer/tree/master/_sass/primer-support/lib/variables
+
+$sidebar-width: 260px;
+
+body {
+ display: flex;
+ margin: 0;
+}
+
+.sidebar {
+ background: $black;
+ color: $text-white;
+ flex-shrink: 0;
+ height: 100vh;
+ overflow: auto;
+ position: sticky;
+ top: 0;
+ width: $sidebar-width;
+}
+
+.sidebar h1 {
+ font-size: 1.5em;
+}
+
+.sidebar h2 {
+ color: $gray-light;
+ font-size: 0.8em;
+ font-weight: normal;
+ margin-bottom: 0.8em;
+ padding-left: 2.5em;
+ text-transform: uppercase;
+}
+
+.sidebar .header {
+ background: $black;
+ padding: 2em;
+ position: sticky;
+ top: 0;
+ width: 100%;
+}
+
+.sidebar .header a {
+ color: $text-white;
+ text-decoration: none;
+}
+
+.sidebar .nav-toggle {
+ display: none;
+}
+
+.sidebar .expander {
+ cursor: pointer;
+ display: none;
+ height: 3em;
+ position: absolute;
+ right: 1em;
+ top: 1.5em;
+ width: 3em;
+}
+
+.sidebar .expander .arrow {
+ border: solid $white;
+ border-width: 0 3px 3px 0;
+ display: block;
+ height: 0.7em;
+ margin: 1em auto;
+ transform: rotate(45deg);
+ transition: transform 0.5s;
+ width: 0.7em;
+}
+
+.sidebar nav {
+ width: 100%;
+}
+
+.sidebar nav ul {
+ list-style-type: none;
+ margin-bottom: 1em;
+ padding: 0;
+
+ &:last-child {
+ margin-bottom: 2em;
+ }
+
+ a {
+ text-decoration: none;
+ }
+
+ li {
+ color: $text-white;
+ padding-left: 2em;
+ text-decoration: none;
+ }
+
+ li.active {
+ background: $border-gray-darker;
+ font-weight: bold;
+ }
+
+ li:hover {
+ background: $border-gray-darker;
+ }
+}
+
+.main {
+ background-color: $bg-gray;
+ width: calc(100% - #{$sidebar-width});
+}
+
+.main .main-inner {
+ background-color: $white;
+ padding: 2em;
+}
+
+.main .footer {
+ margin: 0;
+ padding: 2em;
+}
+
+.main table th {
+ text-align: left;
+}
+
+.main .callout {
+ border-left: 0.25em solid $white;
+ padding: 1em;
+
+ a {
+ text-decoration: underline;
+ }
+
+ &.important {
+ background-color: $bg-yellow-light;
+ border-color: $bg-yellow;
+ color: $black;
+ }
+
+ &.note {
+ background-color: $bg-blue-light;
+ border-color: $text-blue;
+ color: $text-blue;
+ }
+
+ &.tip {
+ background-color: $green-000;
+ border-color: $green-700;
+ color: $green-700;
+ }
+
+ &.warning {
+ background-color: $red-000;
+ border-color: $text-red;
+ color: $text-red;
+ }
+}
+
+.main .good pre {
+ background-color: $bg-green-light;
+}
+
+.main .bad pre {
+ background-color: $red-000;
+}
+
+@media all and (max-width: 768px) {
+ body {
+ flex-direction: column;
+ }
+
+ .sidebar {
+ height: auto;
+ position: relative;
+ width: 100%;
+ }
+
+ .sidebar .expander {
+ display: block;
+ }
+
+ .sidebar nav {
+ height: 0;
+ overflow: hidden;
+ }
+
+ .sidebar .nav-toggle:checked {
+ & ~ nav {
+ height: auto;
+ }
+
+ & + .expander .arrow {
+ transform: rotate(-135deg);
+ }
+ }
+
+ .main {
+ width: 100%;
+ }
+}
diff --git a/lib/yamlcpp/test/googletest-1.13.0/docs/advanced.md b/lib/yamlcpp/test/googletest-1.13.0/docs/advanced.md
new file mode 100644
index 0000000000..f16382fe04
--- /dev/null
+++ b/lib/yamlcpp/test/googletest-1.13.0/docs/advanced.md
@@ -0,0 +1,2407 @@
+# Advanced googletest Topics
+
+## Introduction
+
+Now that you have read the [googletest Primer](primer.md) and learned how to
+write tests using googletest, it's time to learn some new tricks. This document
+will show you more assertions as well as how to construct complex failure
+messages, propagate fatal failures, reuse and speed up your test fixtures, and
+use various flags with your tests.
+
+## More Assertions
+
+This section covers some less frequently used, but still significant,
+assertions.
+
+### Explicit Success and Failure
+
+See [Explicit Success and Failure](reference/assertions.md#success-failure) in
+the Assertions Reference.
+
+### Exception Assertions
+
+See [Exception Assertions](reference/assertions.md#exceptions) in the Assertions
+Reference.
+
+### Predicate Assertions for Better Error Messages
+
+Even though googletest has a rich set of assertions, they can never be complete,
+as it's impossible (nor a good idea) to anticipate all scenarios a user might
+run into. Therefore, sometimes a user has to use `EXPECT_TRUE()` to check a
+complex expression, for lack of a better macro. This has the problem of not
+showing you the values of the parts of the expression, making it hard to
+understand what went wrong. As a workaround, some users choose to construct the
+failure message by themselves, streaming it into `EXPECT_TRUE()`. However, this
+is awkward especially when the expression has side-effects or is expensive to
+evaluate.
+
+googletest gives you three different options to solve this problem:
+
+#### Using an Existing Boolean Function
+
+If you already have a function or functor that returns `bool` (or a type that
+can be implicitly converted to `bool`), you can use it in a *predicate
+assertion* to get the function arguments printed for free. See
+[`EXPECT_PRED*`](reference/assertions.md#EXPECT_PRED) in the Assertions
+Reference for details.
+
+#### Using a Function That Returns an AssertionResult
+
+While `EXPECT_PRED*()` and friends are handy for a quick job, the syntax is not
+satisfactory: you have to use different macros for different arities, and it
+feels more like Lisp than C++. The `::testing::AssertionResult` class solves
+this problem.
+
+An `AssertionResult` object represents the result of an assertion (whether it's
+a success or a failure, and an associated message). You can create an
+`AssertionResult` using one of these factory functions:
+
+```c++
+namespace testing {
+
+// Returns an AssertionResult object to indicate that an assertion has
+// succeeded.
+AssertionResult AssertionSuccess();
+
+// Returns an AssertionResult object to indicate that an assertion has
+// failed.
+AssertionResult AssertionFailure();
+
+}
+```
+
+You can then use the `<<` operator to stream messages to the `AssertionResult`
+object.
+
+To provide more readable messages in Boolean assertions (e.g. `EXPECT_TRUE()`),
+write a predicate function that returns `AssertionResult` instead of `bool`. For
+example, if you define `IsEven()` as:
+
+```c++
+testing::AssertionResult IsEven(int n) {
+ if ((n % 2) == 0)
+ return testing::AssertionSuccess();
+ else
+ return testing::AssertionFailure() << n << " is odd";
+}
+```
+
+instead of:
+
+```c++
+bool IsEven(int n) {
+ return (n % 2) == 0;
+}
+```
+
+the failed assertion `EXPECT_TRUE(IsEven(Fib(4)))` will print:
+
+```none
+Value of: IsEven(Fib(4))
+ Actual: false (3 is odd)
+Expected: true
+```
+
+instead of a more opaque
+
+```none
+Value of: IsEven(Fib(4))
+ Actual: false
+Expected: true
+```
+
+If you want informative messages in `EXPECT_FALSE` and `ASSERT_FALSE` as well
+(one third of Boolean assertions in the Google code base are negative ones), and
+are fine with making the predicate slower in the success case, you can supply a
+success message:
+
+```c++
+testing::AssertionResult IsEven(int n) {
+ if ((n % 2) == 0)
+ return testing::AssertionSuccess() << n << " is even";
+ else
+ return testing::AssertionFailure() << n << " is odd";
+}
+```
+
+Then the statement `EXPECT_FALSE(IsEven(Fib(6)))` will print
+
+```none
+ Value of: IsEven(Fib(6))
+ Actual: true (8 is even)
+ Expected: false
+```
+
+#### Using a Predicate-Formatter
+
+If you find the default message generated by
+[`EXPECT_PRED*`](reference/assertions.md#EXPECT_PRED) and
+[`EXPECT_TRUE`](reference/assertions.md#EXPECT_TRUE) unsatisfactory, or some
+arguments to your predicate do not support streaming to `ostream`, you can
+instead use *predicate-formatter assertions* to *fully* customize how the
+message is formatted. See
+[`EXPECT_PRED_FORMAT*`](reference/assertions.md#EXPECT_PRED_FORMAT) in the
+Assertions Reference for details.
+
+### Floating-Point Comparison
+
+See [Floating-Point Comparison](reference/assertions.md#floating-point) in the
+Assertions Reference.
+
+#### Floating-Point Predicate-Format Functions
+
+Some floating-point operations are useful, but not that often used. In order to
+avoid an explosion of new macros, we provide them as predicate-format functions
+that can be used in the predicate assertion macro
+[`EXPECT_PRED_FORMAT2`](reference/assertions.md#EXPECT_PRED_FORMAT), for
+example:
+
+```c++
+using ::testing::FloatLE;
+using ::testing::DoubleLE;
+...
+EXPECT_PRED_FORMAT2(FloatLE, val1, val2);
+EXPECT_PRED_FORMAT2(DoubleLE, val1, val2);
+```
+
+The above code verifies that `val1` is less than, or approximately equal to,
+`val2`.
+
+### Asserting Using gMock Matchers
+
+See [`EXPECT_THAT`](reference/assertions.md#EXPECT_THAT) in the Assertions
+Reference.
+
+### More String Assertions
+
+(Please read the [previous](#asserting-using-gmock-matchers) section first if
+you haven't.)
+
+You can use the gMock [string matchers](reference/matchers.md#string-matchers)
+with [`EXPECT_THAT`](reference/assertions.md#EXPECT_THAT) to do more string
+comparison tricks (sub-string, prefix, suffix, regular expression, and etc). For
+example,
+
+```c++
+using ::testing::HasSubstr;
+using ::testing::MatchesRegex;
+...
+ ASSERT_THAT(foo_string, HasSubstr("needle"));
+ EXPECT_THAT(bar_string, MatchesRegex("\\w*\\d+"));
+```
+
+### Windows HRESULT assertions
+
+See [Windows HRESULT Assertions](reference/assertions.md#HRESULT) in the
+Assertions Reference.
+
+### Type Assertions
+
+You can call the function
+
+```c++
+::testing::StaticAssertTypeEq<T1, T2>();
+```
+
+to assert that types `T1` and `T2` are the same. The function does nothing if
+the assertion is satisfied. If the types are different, the function call will
+fail to compile, the compiler error message will say that `T1 and T2 are not the
+same type` and most likely (depending on the compiler) show you the actual
+values of `T1` and `T2`. This is mainly useful inside template code.
+
+**Caveat**: When used inside a member function of a class template or a function
+template, `StaticAssertTypeEq<T1, T2>()` is effective only if the function is
+instantiated. For example, given:
+
+```c++
+template <typename T> class Foo {
+ public:
+ void Bar() { testing::StaticAssertTypeEq<int, T>(); }
+};
+```
+
+the code:
+
+```c++
+void Test1() { Foo<bool> foo; }
+```
+
+will not generate a compiler error, as `Foo<bool>::Bar()` is never actually
+instantiated. Instead, you need:
+
+```c++
+void Test2() { Foo<bool> foo; foo.Bar(); }
+```
+
+to cause a compiler error.
+
+### Assertion Placement
+
+You can use assertions in any C++ function. In particular, it doesn't have to be
+a method of the test fixture class. The one constraint is that assertions that
+generate a fatal failure (`FAIL*` and `ASSERT_*`) can only be used in
+void-returning functions. This is a consequence of Google's not using
+exceptions. By placing it in a non-void function you'll get a confusing compile
+error like `"error: void value not ignored as it ought to be"` or `"cannot
+initialize return object of type 'bool' with an rvalue of type 'void'"` or
+`"error: no viable conversion from 'void' to 'string'"`.
+
+If you need to use fatal assertions in a function that returns non-void, one
+option is to make the function return the value in an out parameter instead. For
+example, you can rewrite `T2 Foo(T1 x)` to `void Foo(T1 x, T2* result)`. You
+need to make sure that `*result` contains some sensible value even when the
+function returns prematurely. As the function now returns `void`, you can use
+any assertion inside of it.
+
+If changing the function's type is not an option, you should just use assertions
+that generate non-fatal failures, such as `ADD_FAILURE*` and `EXPECT_*`.
+
+{: .callout .note}
+NOTE: Constructors and destructors are not considered void-returning functions,
+according to the C++ language specification, and so you may not use fatal
+assertions in them; you'll get a compilation error if you try. Instead, either
+call `abort` and crash the entire test executable, or put the fatal assertion in
+a `SetUp`/`TearDown` function; see
+[constructor/destructor vs. `SetUp`/`TearDown`](faq.md#CtorVsSetUp)
+
+{: .callout .warning}
+WARNING: A fatal assertion in a helper function (private void-returning method)
+called from a constructor or destructor does not terminate the current test, as
+your intuition might suggest: it merely returns from the constructor or
+destructor early, possibly leaving your object in a partially-constructed or
+partially-destructed state! You almost certainly want to `abort` or use
+`SetUp`/`TearDown` instead.
+
+## Skipping test execution
+
+Related to the assertions `SUCCEED()` and `FAIL()`, you can prevent further test
+execution at runtime with the `GTEST_SKIP()` macro. This is useful when you need
+to check for preconditions of the system under test during runtime and skip
+tests in a meaningful way.
+
+`GTEST_SKIP()` can be used in individual test cases or in the `SetUp()` methods
+of classes derived from either `::testing::Environment` or `::testing::Test`.
+For example:
+
+```c++
+TEST(SkipTest, DoesSkip) {
+ GTEST_SKIP() << "Skipping single test";
+ EXPECT_EQ(0, 1); // Won't fail; it won't be executed
+}
+
+class SkipFixture : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ GTEST_SKIP() << "Skipping all tests for this fixture";
+ }
+};
+
+// Tests for SkipFixture won't be executed.
+TEST_F(SkipFixture, SkipsOneTest) {
+ EXPECT_EQ(5, 7); // Won't fail
+}
+```
+
+As with assertion macros, you can stream a custom message into `GTEST_SKIP()`.
+
+## Teaching googletest How to Print Your Values
+
+When a test assertion such as `EXPECT_EQ` fails, googletest prints the argument
+values to help you debug. It does this using a user-extensible value printer.
+
+This printer knows how to print built-in C++ types, native arrays, STL
+containers, and any type that supports the `<<` operator. For other types, it
+prints the raw bytes in the value and hopes that you the user can figure it out.
+
+As mentioned earlier, the printer is *extensible*. That means you can teach it
+to do a better job at printing your particular type than to dump the bytes. To
+do that, define `<<` for your type:
+
+```c++
+#include <ostream>
+
+namespace foo {
+
+class Bar { // We want googletest to be able to print instances of this.
+...
+ // Create a free inline friend function.
+ friend std::ostream& operator<<(std::ostream& os, const Bar& bar) {
+ return os << bar.DebugString(); // whatever needed to print bar to os
+ }
+};
+
+// If you can't declare the function in the class it's important that the
+// << operator is defined in the SAME namespace that defines Bar. C++'s look-up
+// rules rely on that.
+std::ostream& operator<<(std::ostream& os, const Bar& bar) {
+ return os << bar.DebugString(); // whatever needed to print bar to os
+}
+
+} // namespace foo
+```
+
+Sometimes, this might not be an option: your team may consider it bad style to
+have a `<<` operator for `Bar`, or `Bar` may already have a `<<` operator that
+doesn't do what you want (and you cannot change it). If so, you can instead
+define a `PrintTo()` function like this:
+
+```c++
+#include <ostream>
+
+namespace foo {
+
+class Bar {
+ ...
+ friend void PrintTo(const Bar& bar, std::ostream* os) {
+ *os << bar.DebugString(); // whatever needed to print bar to os
+ }
+};
+
+// If you can't declare the function in the class it's important that PrintTo()
+// is defined in the SAME namespace that defines Bar. C++'s look-up rules rely
+// on that.
+void PrintTo(const Bar& bar, std::ostream* os) {
+ *os << bar.DebugString(); // whatever needed to print bar to os
+}
+
+} // namespace foo
+```
+
+If you have defined both `<<` and `PrintTo()`, the latter will be used when
+googletest is concerned. This allows you to customize how the value appears in
+googletest's output without affecting code that relies on the behavior of its
+`<<` operator.
+
+If you want to print a value `x` using googletest's value printer yourself, just
+call `::testing::PrintToString(x)`, which returns an `std::string`:
+
+```c++
+vector<pair<Bar, int> > bar_ints = GetBarIntVector();
+
+EXPECT_TRUE(IsCorrectBarIntVector(bar_ints))
+ << "bar_ints = " << testing::PrintToString(bar_ints);
+```
+
+## Death Tests
+
+In many applications, there are assertions that can cause application failure if
+a condition is not met. These consistency checks, which ensure that the program
+is in a known good state, are there to fail at the earliest possible time after
+some program state is corrupted. If the assertion checks the wrong condition,
+then the program may proceed in an erroneous state, which could lead to memory
+corruption, security holes, or worse. Hence it is vitally important to test that
+such assertion statements work as expected.
+
+Since these precondition checks cause the processes to die, we call such tests
+_death tests_. More generally, any test that checks that a program terminates
+(except by throwing an exception) in an expected fashion is also a death test.
+
+Note that if a piece of code throws an exception, we don't consider it "death"
+for the purpose of death tests, as the caller of the code could catch the
+exception and avoid the crash. If you want to verify exceptions thrown by your
+code, see [Exception Assertions](#ExceptionAssertions).
+
+If you want to test `EXPECT_*()/ASSERT_*()` failures in your test code, see
+["Catching" Failures](#catching-failures).
+
+### How to Write a Death Test
+
+GoogleTest provides assertion macros to support death tests. See
+[Death Assertions](reference/assertions.md#death) in the Assertions Reference
+for details.
+
+To write a death test, simply use one of the macros inside your test function.
+For example,
+
+```c++
+TEST(MyDeathTest, Foo) {
+ // This death test uses a compound statement.
+ ASSERT_DEATH({
+ int n = 5;
+ Foo(&n);
+ }, "Error on line .* of Foo()");
+}
+
+TEST(MyDeathTest, NormalExit) {
+ EXPECT_EXIT(NormalExit(), testing::ExitedWithCode(0), "Success");
+}
+
+TEST(MyDeathTest, KillProcess) {
+ EXPECT_EXIT(KillProcess(), testing::KilledBySignal(SIGKILL),
+ "Sending myself unblockable signal");
+}
+```
+
+verifies that:
+
+* calling `Foo(5)` causes the process to die with the given error message,
+* calling `NormalExit()` causes the process to print `"Success"` to stderr and
+ exit with exit code 0, and
+* calling `KillProcess()` kills the process with signal `SIGKILL`.
+
+The test function body may contain other assertions and statements as well, if
+necessary.
+
+Note that a death test only cares about three things:
+
+1. does `statement` abort or exit the process?
+2. (in the case of `ASSERT_EXIT` and `EXPECT_EXIT`) does the exit status
+ satisfy `predicate`? Or (in the case of `ASSERT_DEATH` and `EXPECT_DEATH`)
+ is the exit status non-zero? And
+3. does the stderr output match `matcher`?
+
+In particular, if `statement` generates an `ASSERT_*` or `EXPECT_*` failure, it
+will **not** cause the death test to fail, as googletest assertions don't abort
+the process.
+
+### Death Test Naming
+
+{: .callout .important}
+IMPORTANT: We strongly recommend you to follow the convention of naming your
+**test suite** (not test) `*DeathTest` when it contains a death test, as
+demonstrated in the above example. The
+[Death Tests And Threads](#death-tests-and-threads) section below explains why.
+
+If a test fixture class is shared by normal tests and death tests, you can use
+`using` or `typedef` to introduce an alias for the fixture class and avoid
+duplicating its code:
+
+```c++
+class FooTest : public testing::Test { ... };
+
+using FooDeathTest = FooTest;
+
+TEST_F(FooTest, DoesThis) {
+ // normal test
+}
+
+TEST_F(FooDeathTest, DoesThat) {
+ // death test
+}
+```
+
+### Regular Expression Syntax
+
+When built with Bazel and using Abseil, googletest uses the
+[RE2](https://github.com/google/re2/wiki/Syntax) syntax. Otherwise, for POSIX
+systems (Linux, Cygwin, Mac), googletest uses the
+[POSIX extended regular expression](http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
+syntax. To learn about POSIX syntax, you may want to read this
+[Wikipedia entry](http://en.wikipedia.org/wiki/Regular_expression#POSIX_extended).
+
+On Windows, googletest uses its own simple regular expression implementation. It
+lacks many features. For example, we don't support union (`"x|y"`), grouping
+(`"(xy)"`), brackets (`"[xy]"`), and repetition count (`"x{5,7}"`), among
+others. Below is what we do support (`A` denotes a literal character, period
+(`.`), or a single `\\ ` escape sequence; `x` and `y` denote regular
+expressions.):
+
+Expression | Meaning
+---------- | --------------------------------------------------------------
+`c` | matches any literal character `c`
+`\\d` | matches any decimal digit
+`\\D` | matches any character that's not a decimal digit
+`\\f` | matches `\f`
+`\\n` | matches `\n`
+`\\r` | matches `\r`
+`\\s` | matches any ASCII whitespace, including `\n`
+`\\S` | matches any character that's not a whitespace
+`\\t` | matches `\t`
+`\\v` | matches `\v`
+`\\w` | matches any letter, `_`, or decimal digit
+`\\W` | matches any character that `\\w` doesn't match
+`\\c` | matches any literal character `c`, which must be a punctuation
+`.` | matches any single character except `\n`
+`A?` | matches 0 or 1 occurrences of `A`
+`A*` | matches 0 or many occurrences of `A`
+`A+` | matches 1 or many occurrences of `A`
+`^` | matches the beginning of a string (not that of each line)
+`$` | matches the end of a string (not that of each line)
+`xy` | matches `x` followed by `y`
+
+To help you determine which capability is available on your system, googletest
+defines macros to govern which regular expression it is using. The macros are:
+`GTEST_USES_SIMPLE_RE=1` or `GTEST_USES_POSIX_RE=1`. If you want your death
+tests to work in all cases, you can either `#if` on these macros or use the more
+limited syntax only.
+
+### How It Works
+
+See [Death Assertions](reference/assertions.md#death) in the Assertions
+Reference.
+
+### Death Tests And Threads
+
+The reason for the two death test styles has to do with thread safety. Due to
+well-known problems with forking in the presence of threads, death tests should
+be run in a single-threaded context. Sometimes, however, it isn't feasible to
+arrange that kind of environment. For example, statically-initialized modules
+may start threads before main is ever reached. Once threads have been created,
+it may be difficult or impossible to clean them up.
+
+googletest has three features intended to raise awareness of threading issues.
+
+1. A warning is emitted if multiple threads are running when a death test is
+ encountered.
+2. Test suites with a name ending in "DeathTest" are run before all other
+ tests.
+3. It uses `clone()` instead of `fork()` to spawn the child process on Linux
+ (`clone()` is not available on Cygwin and Mac), as `fork()` is more likely
+ to cause the child to hang when the parent process has multiple threads.
+
+It's perfectly fine to create threads inside a death test statement; they are
+executed in a separate process and cannot affect the parent.
+
+### Death Test Styles
+
+The "threadsafe" death test style was introduced in order to help mitigate the
+risks of testing in a possibly multithreaded environment. It trades increased
+test execution time (potentially dramatically so) for improved thread safety.
+
+The automated testing framework does not set the style flag. You can choose a
+particular style of death tests by setting the flag programmatically:
+
+```c++
+GTEST_FLAG_SET(death_test_style, "threadsafe")
+```
+
+You can do this in `main()` to set the style for all death tests in the binary,
+or in individual tests. Recall that flags are saved before running each test and
+restored afterwards, so you need not do that yourself. For example:
+
+```c++
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+ GTEST_FLAG_SET(death_test_style, "fast");
+ return RUN_ALL_TESTS();
+}
+
+TEST(MyDeathTest, TestOne) {
+ GTEST_FLAG_SET(death_test_style, "threadsafe");
+ // This test is run in the "threadsafe" style:
+ ASSERT_DEATH(ThisShouldDie(), "");
+}
+
+TEST(MyDeathTest, TestTwo) {
+ // This test is run in the "fast" style:
+ ASSERT_DEATH(ThisShouldDie(), "");
+}
+```
+
+### Caveats
+
+The `statement` argument of `ASSERT_EXIT()` can be any valid C++ statement. If
+it leaves the current function via a `return` statement or by throwing an
+exception, the death test is considered to have failed. Some googletest macros
+may return from the current function (e.g. `ASSERT_TRUE()`), so be sure to avoid
+them in `statement`.
+
+Since `statement` runs in the child process, any in-memory side effect (e.g.
+modifying a variable, releasing memory, etc) it causes will *not* be observable
+in the parent process. In particular, if you release memory in a death test,
+your program will fail the heap check as the parent process will never see the
+memory reclaimed. To solve this problem, you can
+
+1. try not to free memory in a death test;
+2. free the memory again in the parent process; or
+3. do not use the heap checker in your program.
+
+Due to an implementation detail, you cannot place multiple death test assertions
+on the same line; otherwise, compilation will fail with an unobvious error
+message.
+
+Despite the improved thread safety afforded by the "threadsafe" style of death
+test, thread problems such as deadlock are still possible in the presence of
+handlers registered with `pthread_atfork(3)`.
+
+## Using Assertions in Sub-routines
+
+{: .callout .note}
+Note: If you want to put a series of test assertions in a subroutine to check
+for a complex condition, consider using
+[a custom GMock matcher](gmock_cook_book.md#NewMatchers) instead. This lets you
+provide a more readable error message in case of failure and avoid all of the
+issues described below.
+
+### Adding Traces to Assertions
+
+If a test sub-routine is called from several places, when an assertion inside it
+fails, it can be hard to tell which invocation of the sub-routine the failure is
+from. You can alleviate this problem using extra logging or custom failure
+messages, but that usually clutters up your tests. A better solution is to use
+the `SCOPED_TRACE` macro or the `ScopedTrace` utility:
+
+```c++
+SCOPED_TRACE(message);
+```
+
+```c++
+ScopedTrace trace("file_path", line_number, message);
+```
+
+where `message` can be anything streamable to `std::ostream`. `SCOPED_TRACE`
+macro will cause the current file name, line number, and the given message to be
+added in every failure message. `ScopedTrace` accepts explicit file name and
+line number in arguments, which is useful for writing test helpers. The effect
+will be undone when the control leaves the current lexical scope.
+
+For example,
+
+```c++
+10: void Sub1(int n) {
+11: EXPECT_EQ(Bar(n), 1);
+12: EXPECT_EQ(Bar(n + 1), 2);
+13: }
+14:
+15: TEST(FooTest, Bar) {
+16: {
+17: SCOPED_TRACE("A"); // This trace point will be included in
+18: // every failure in this scope.
+19: Sub1(1);
+20: }
+21: // Now it won't.
+22: Sub1(9);
+23: }
+```
+
+could result in messages like these:
+
+```none
+path/to/foo_test.cc:11: Failure
+Value of: Bar(n)
+Expected: 1
+ Actual: 2
+Google Test trace:
+path/to/foo_test.cc:17: A
+
+path/to/foo_test.cc:12: Failure
+Value of: Bar(n + 1)
+Expected: 2
+ Actual: 3
+```
+
+Without the trace, it would've been difficult to know which invocation of
+`Sub1()` the two failures come from respectively. (You could add an extra
+message to each assertion in `Sub1()` to indicate the value of `n`, but that's
+tedious.)
+
+Some tips on using `SCOPED_TRACE`:
+
+1. With a suitable message, it's often enough to use `SCOPED_TRACE` at the
+ beginning of a sub-routine, instead of at each call site.
+2. When calling sub-routines inside a loop, make the loop iterator part of the
+ message in `SCOPED_TRACE` such that you can know which iteration the failure
+ is from.
+3. Sometimes the line number of the trace point is enough for identifying the
+ particular invocation of a sub-routine. In this case, you don't have to
+ choose a unique message for `SCOPED_TRACE`. You can simply use `""`.
+4. You can use `SCOPED_TRACE` in an inner scope when there is one in the outer
+ scope. In this case, all active trace points will be included in the failure
+ messages, in reverse order they are encountered.
+5. The trace dump is clickable in Emacs - hit `return` on a line number and
+ you'll be taken to that line in the source file!
+
+### Propagating Fatal Failures
+
+A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that
+when they fail they only abort the _current function_, not the entire test. For
+example, the following test will segfault:
+
+```c++
+void Subroutine() {
+ // Generates a fatal failure and aborts the current function.
+ ASSERT_EQ(1, 2);
+
+ // The following won't be executed.
+ ...
+}
+
+TEST(FooTest, Bar) {
+ Subroutine(); // The intended behavior is for the fatal failure
+ // in Subroutine() to abort the entire test.
+
+ // The actual behavior: the function goes on after Subroutine() returns.
+ int* p = nullptr;
+ *p = 3; // Segfault!
+}
+```
+
+To alleviate this, googletest provides three different solutions. You could use
+either exceptions, the `(ASSERT|EXPECT)_NO_FATAL_FAILURE` assertions or the
+`HasFatalFailure()` function. They are described in the following two
+subsections.
+
+#### Asserting on Subroutines with an exception
+
+The following code can turn ASSERT-failure into an exception:
+
+```c++
+class ThrowListener : public testing::EmptyTestEventListener {
+ void OnTestPartResult(const testing::TestPartResult& result) override {
+ if (result.type() == testing::TestPartResult::kFatalFailure) {
+ throw testing::AssertionException(result);
+ }
+ }
+};
+int main(int argc, char** argv) {
+ ...
+ testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener);
+ return RUN_ALL_TESTS();
+}
+```
+
+This listener should be added after other listeners if you have any, otherwise
+they won't see failed `OnTestPartResult`.
+
+#### Asserting on Subroutines
+
+As shown above, if your test calls a subroutine that has an `ASSERT_*` failure
+in it, the test will continue after the subroutine returns. This may not be what
+you want.
+
+Often people want fatal failures to propagate like exceptions. For that
+googletest offers the following macros:
+
+Fatal assertion | Nonfatal assertion | Verifies
+------------------------------------- | ------------------------------------- | --------
+`ASSERT_NO_FATAL_FAILURE(statement);` | `EXPECT_NO_FATAL_FAILURE(statement);` | `statement` doesn't generate any new fatal failures in the current thread.
+
+Only failures in the thread that executes the assertion are checked to determine
+the result of this type of assertions. If `statement` creates new threads,
+failures in these threads are ignored.
+
+Examples:
+
+```c++
+ASSERT_NO_FATAL_FAILURE(Foo());
+
+int i;
+EXPECT_NO_FATAL_FAILURE({
+ i = Bar();
+});
+```
+
+Assertions from multiple threads are currently not supported on Windows.
+
+#### Checking for Failures in the Current Test
+
+`HasFatalFailure()` in the `::testing::Test` class returns `true` if an
+assertion in the current test has suffered a fatal failure. This allows
+functions to catch fatal failures in a sub-routine and return early.
+
+```c++
+class Test {
+ public:
+ ...
+ static bool HasFatalFailure();
+};
+```
+
+The typical usage, which basically simulates the behavior of a thrown exception,
+is:
+
+```c++
+TEST(FooTest, Bar) {
+ Subroutine();
+ // Aborts if Subroutine() had a fatal failure.
+ if (HasFatalFailure()) return;
+
+ // The following won't be executed.
+ ...
+}
+```
+
+If `HasFatalFailure()` is used outside of `TEST()` , `TEST_F()` , or a test
+fixture, you must add the `::testing::Test::` prefix, as in:
+
+```c++
+if (testing::Test::HasFatalFailure()) return;
+```
+
+Similarly, `HasNonfatalFailure()` returns `true` if the current test has at
+least one non-fatal failure, and `HasFailure()` returns `true` if the current
+test has at least one failure of either kind.
+
+## Logging Additional Information
+
+In your test code, you can call `RecordProperty("key", value)` to log additional
+information, where `value` can be either a string or an `int`. The *last* value
+recorded for a key will be emitted to the
+[XML output](#generating-an-xml-report) if you specify one. For example, the
+test
+
+```c++
+TEST_F(WidgetUsageTest, MinAndMaxWidgets) {
+ RecordProperty("MaximumWidgets", ComputeMaxUsage());
+ RecordProperty("MinimumWidgets", ComputeMinUsage());
+}
+```
+
+will output XML like this:
+
+```xml
+ ...
+ <testcase name="MinAndMaxWidgets" file="test.cpp" line="1" status="run" time="0.006" classname="WidgetUsageTest" MaximumWidgets="12" MinimumWidgets="9" />
+ ...
+```
+
+{: .callout .note}
+> NOTE:
+>
+> * `RecordProperty()` is a static member of the `Test` class. Therefore it
+> needs to be prefixed with `::testing::Test::` if used outside of the
+> `TEST` body and the test fixture class.
+> * *`key`* must be a valid XML attribute name, and cannot conflict with the
+> ones already used by googletest (`name`, `status`, `time`, `classname`,
+> `type_param`, and `value_param`).
+> * Calling `RecordProperty()` outside of the lifespan of a test is allowed.
+> If it's called outside of a test but between a test suite's
+> `SetUpTestSuite()` and `TearDownTestSuite()` methods, it will be
+> attributed to the XML element for the test suite. If it's called outside
+> of all test suites (e.g. in a test environment), it will be attributed to
+> the top-level XML element.
+
+## Sharing Resources Between Tests in the Same Test Suite
+
+googletest creates a new test fixture object for each test in order to make
+tests independent and easier to debug. However, sometimes tests use resources
+that are expensive to set up, making the one-copy-per-test model prohibitively
+expensive.
+
+If the tests don't change the resource, there's no harm in their sharing a
+single resource copy. So, in addition to per-test set-up/tear-down, googletest
+also supports per-test-suite set-up/tear-down. To use it:
+
+1. In your test fixture class (say `FooTest` ), declare as `static` some member
+ variables to hold the shared resources.
+2. Outside your test fixture class (typically just below it), define those
+ member variables, optionally giving them initial values.
+3. In the same test fixture class, define a `static void SetUpTestSuite()`
+ function (remember not to spell it as **`SetupTestSuite`** with a small
+ `u`!) to set up the shared resources and a `static void TearDownTestSuite()`
+ function to tear them down.
+
+That's it! googletest automatically calls `SetUpTestSuite()` before running the
+*first test* in the `FooTest` test suite (i.e. before creating the first
+`FooTest` object), and calls `TearDownTestSuite()` after running the *last test*
+in it (i.e. after deleting the last `FooTest` object). In between, the tests can
+use the shared resources.
+
+Remember that the test order is undefined, so your code can't depend on a test
+preceding or following another. Also, the tests must either not modify the state
+of any shared resource, or, if they do modify the state, they must restore the
+state to its original value before passing control to the next test.
+
+Note that `SetUpTestSuite()` may be called multiple times for a test fixture
+class that has derived classes, so you should not expect code in the function
+body to be run only once. Also, derived classes still have access to shared
+resources defined as static members, so careful consideration is needed when
+managing shared resources to avoid memory leaks.
+
+Here's an example of per-test-suite set-up and tear-down:
+
+```c++
+class FooTest : public testing::Test {
+ protected:
+ // Per-test-suite set-up.
+ // Called before the first test in this test suite.
+ // Can be omitted if not needed.
+ static void SetUpTestSuite() {
+ // Avoid reallocating static objects if called in subclasses of FooTest.
+ if (shared_resource_ == nullptr) {
+ shared_resource_ = new ...;
+ }
+ }
+
+ // Per-test-suite tear-down.
+ // Called after the last test in this test suite.
+ // Can be omitted if not needed.
+ static void TearDownTestSuite() {
+ delete shared_resource_;
+ shared_resource_ = nullptr;
+ }
+
+ // You can define per-test set-up logic as usual.
+ void SetUp() override { ... }
+
+ // You can define per-test tear-down logic as usual.
+ void TearDown() override { ... }
+
+ // Some expensive resource shared by all tests.
+ static T* shared_resource_;
+};
+
+T* FooTest::shared_resource_ = nullptr;
+
+TEST_F(FooTest, Test1) {
+ ... you can refer to shared_resource_ here ...
+}
+
+TEST_F(FooTest, Test2) {
+ ... you can refer to shared_resource_ here ...
+}
+```
+
+{: .callout .note}
+NOTE: Though the above code declares `SetUpTestSuite()` protected, it may
+sometimes be necessary to declare it public, such as when using it with
+`TEST_P`.
+
+## Global Set-Up and Tear-Down
+
+Just as you can do set-up and tear-down at the test level and the test suite
+level, you can also do it at the test program level. Here's how.
+
+First, you subclass the `::testing::Environment` class to define a test
+environment, which knows how to set-up and tear-down:
+
+```c++
+class Environment : public ::testing::Environment {
+ public:
+ ~Environment() override {}
+
+ // Override this to define how to set up the environment.
+ void SetUp() override {}
+
+ // Override this to define how to tear down the environment.
+ void TearDown() override {}
+};
+```
+
+Then, you register an instance of your environment class with googletest by
+calling the `::testing::AddGlobalTestEnvironment()` function:
+
+```c++
+Environment* AddGlobalTestEnvironment(Environment* env);
+```
+
+Now, when `RUN_ALL_TESTS()` is called, it first calls the `SetUp()` method of
+each environment object, then runs the tests if none of the environments
+reported fatal failures and `GTEST_SKIP()` was not called. `RUN_ALL_TESTS()`
+always calls `TearDown()` with each environment object, regardless of whether or
+not the tests were run.
+
+It's OK to register multiple environment objects. In this suite, their `SetUp()`
+will be called in the order they are registered, and their `TearDown()` will be
+called in the reverse order.
+
+Note that googletest takes ownership of the registered environment objects.
+Therefore **do not delete them** by yourself.
+
+You should call `AddGlobalTestEnvironment()` before `RUN_ALL_TESTS()` is called,
+probably in `main()`. If you use `gtest_main`, you need to call this before
+`main()` starts for it to take effect. One way to do this is to define a global
+variable like this:
+
+```c++
+testing::Environment* const foo_env =
+ testing::AddGlobalTestEnvironment(new FooEnvironment);
+```
+
+However, we strongly recommend you to write your own `main()` and call
+`AddGlobalTestEnvironment()` there, as relying on initialization of global
+variables makes the code harder to read and may cause problems when you register
+multiple environments from different translation units and the environments have
+dependencies among them (remember that the compiler doesn't guarantee the order
+in which global variables from different translation units are initialized).
+
+## Value-Parameterized Tests
+
+*Value-parameterized tests* allow you to test your code with different
+parameters without writing multiple copies of the same test. This is useful in a
+number of situations, for example:
+
+* You have a piece of code whose behavior is affected by one or more
+ command-line flags. You want to make sure your code performs correctly for
+ various values of those flags.
+* You want to test different implementations of an OO interface.
+* You want to test your code over various inputs (a.k.a. data-driven testing).
+ This feature is easy to abuse, so please exercise your good sense when doing
+ it!
+
+### How to Write Value-Parameterized Tests
+
+To write value-parameterized tests, first you should define a fixture class. It
+must be derived from both `testing::Test` and `testing::WithParamInterface<T>`
+(the latter is a pure interface), where `T` is the type of your parameter
+values. For convenience, you can just derive the fixture class from
+`testing::TestWithParam<T>`, which itself is derived from both `testing::Test`
+and `testing::WithParamInterface<T>`. `T` can be any copyable type. If it's a
+raw pointer, you are responsible for managing the lifespan of the pointed
+values.
+
+{: .callout .note}
+NOTE: If your test fixture defines `SetUpTestSuite()` or `TearDownTestSuite()`
+they must be declared **public** rather than **protected** in order to use
+`TEST_P`.
+
+```c++
+class FooTest :
+ public testing::TestWithParam<const char*> {
+ // You can implement all the usual fixture class members here.
+ // To access the test parameter, call GetParam() from class
+ // TestWithParam<T>.
+};
+
+// Or, when you want to add parameters to a pre-existing fixture class:
+class BaseTest : public testing::Test {
+ ...
+};
+class BarTest : public BaseTest,
+ public testing::WithParamInterface<const char*> {
+ ...
+};
+```
+
+Then, use the `TEST_P` macro to define as many test patterns using this fixture
+as you want. The `_P` suffix is for "parameterized" or "pattern", whichever you
+prefer to think.
+
+```c++
+TEST_P(FooTest, DoesBlah) {
+ // Inside a test, access the test parameter with the GetParam() method
+ // of the TestWithParam<T> class:
+ EXPECT_TRUE(foo.Blah(GetParam()));
+ ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+ ...
+}
+```
+
+Finally, you can use the `INSTANTIATE_TEST_SUITE_P` macro to instantiate the
+test suite with any set of parameters you want. GoogleTest defines a number of
+functions for generating test parameters—see details at
+[`INSTANTIATE_TEST_SUITE_P`](reference/testing.md#INSTANTIATE_TEST_SUITE_P) in
+the Testing Reference.
+
+For example, the following statement will instantiate tests from the `FooTest`
+test suite each with parameter values `"meeny"`, `"miny"`, and `"moe"` using the
+[`Values`](reference/testing.md#param-generators) parameter generator:
+
+```c++
+INSTANTIATE_TEST_SUITE_P(MeenyMinyMoe,
+ FooTest,
+ testing::Values("meeny", "miny", "moe"));
+```
+
+{: .callout .note}
+NOTE: The code above must be placed at global or namespace scope, not at
+function scope.
+
+The first argument to `INSTANTIATE_TEST_SUITE_P` is a unique name for the
+instantiation of the test suite. The next argument is the name of the test
+pattern, and the last is the
+[parameter generator](reference/testing.md#param-generators).
+
+The parameter generator expression is not evaluated until GoogleTest is
+initialized (via `InitGoogleTest()`). Any prior initialization done in the
+`main` function will be accessible from the parameter generator, for example,
+the results of flag parsing.
+
+You can instantiate a test pattern more than once, so to distinguish different
+instances of the pattern, the instantiation name is added as a prefix to the
+actual test suite name. Remember to pick unique prefixes for different
+instantiations. The tests from the instantiation above will have these names:
+
+* `MeenyMinyMoe/FooTest.DoesBlah/0` for `"meeny"`
+* `MeenyMinyMoe/FooTest.DoesBlah/1` for `"miny"`
+* `MeenyMinyMoe/FooTest.DoesBlah/2` for `"moe"`
+* `MeenyMinyMoe/FooTest.HasBlahBlah/0` for `"meeny"`
+* `MeenyMinyMoe/FooTest.HasBlahBlah/1` for `"miny"`
+* `MeenyMinyMoe/FooTest.HasBlahBlah/2` for `"moe"`
+
+You can use these names in [`--gtest_filter`](#running-a-subset-of-the-tests).
+
+The following statement will instantiate all tests from `FooTest` again, each
+with parameter values `"cat"` and `"dog"` using the
+[`ValuesIn`](reference/testing.md#param-generators) parameter generator:
+
+```c++
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_SUITE_P(Pets, FooTest, testing::ValuesIn(pets));
+```
+
+The tests from the instantiation above will have these names:
+
+* `Pets/FooTest.DoesBlah/0` for `"cat"`
+* `Pets/FooTest.DoesBlah/1` for `"dog"`
+* `Pets/FooTest.HasBlahBlah/0` for `"cat"`
+* `Pets/FooTest.HasBlahBlah/1` for `"dog"`
+
+Please note that `INSTANTIATE_TEST_SUITE_P` will instantiate *all* tests in the
+given test suite, whether their definitions come before or *after* the
+`INSTANTIATE_TEST_SUITE_P` statement.
+
+Additionally, by default, every `TEST_P` without a corresponding
+`INSTANTIATE_TEST_SUITE_P` causes a failing test in test suite
+`GoogleTestVerification`. If you have a test suite where that omission is not an
+error, for example it is in a library that may be linked in for other reasons or
+where the list of test cases is dynamic and may be empty, then this check can be
+suppressed by tagging the test suite:
+
+```c++
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FooTest);
+```
+
+You can see [sample7_unittest.cc] and [sample8_unittest.cc] for more examples.
+
+[sample7_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample7_unittest.cc "Parameterized Test example"
+[sample8_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample8_unittest.cc "Parameterized Test example with multiple parameters"
+
+### Creating Value-Parameterized Abstract Tests
+
+In the above, we define and instantiate `FooTest` in the *same* source file.
+Sometimes you may want to define value-parameterized tests in a library and let
+other people instantiate them later. This pattern is known as *abstract tests*.
+As an example of its application, when you are designing an interface you can
+write a standard suite of abstract tests (perhaps using a factory function as
+the test parameter) that all implementations of the interface are expected to
+pass. When someone implements the interface, they can instantiate your suite to
+get all the interface-conformance tests for free.
+
+To define abstract tests, you should organize your code like this:
+
+1. Put the definition of the parameterized test fixture class (e.g. `FooTest`)
+ in a header file, say `foo_param_test.h`. Think of this as *declaring* your
+ abstract tests.
+2. Put the `TEST_P` definitions in `foo_param_test.cc`, which includes
+ `foo_param_test.h`. Think of this as *implementing* your abstract tests.
+
+Once they are defined, you can instantiate them by including `foo_param_test.h`,
+invoking `INSTANTIATE_TEST_SUITE_P()`, and depending on the library target that
+contains `foo_param_test.cc`. You can instantiate the same abstract test suite
+multiple times, possibly in different source files.
+
+### Specifying Names for Value-Parameterized Test Parameters
+
+The optional last argument to `INSTANTIATE_TEST_SUITE_P()` allows the user to
+specify a function or functor that generates custom test name suffixes based on
+the test parameters. The function should accept one argument of type
+`testing::TestParamInfo<class ParamType>`, and return `std::string`.
+
+`testing::PrintToStringParamName` is a builtin test suffix generator that
+returns the value of `testing::PrintToString(GetParam())`. It does not work for
+`std::string` or C strings.
+
+{: .callout .note}
+NOTE: test names must be non-empty, unique, and may only contain ASCII
+alphanumeric characters. In particular, they
+[should not contain underscores](faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore)
+
+```c++
+class MyTestSuite : public testing::TestWithParam<int> {};
+
+TEST_P(MyTestSuite, MyTest)
+{
+ std::cout << "Example Test Param: " << GetParam() << std::endl;
+}
+
+INSTANTIATE_TEST_SUITE_P(MyGroup, MyTestSuite, testing::Range(0, 10),
+ testing::PrintToStringParamName());
+```
+
+Providing a custom functor allows for more control over test parameter name
+generation, especially for types where the automatic conversion does not
+generate helpful parameter names (e.g. strings as demonstrated above). The
+following example illustrates this for multiple parameters, an enumeration type
+and a string, and also demonstrates how to combine generators. It uses a lambda
+for conciseness:
+
+```c++
+enum class MyType { MY_FOO = 0, MY_BAR = 1 };
+
+class MyTestSuite : public testing::TestWithParam<std::tuple<MyType, std::string>> {
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ MyGroup, MyTestSuite,
+ testing::Combine(
+ testing::Values(MyType::MY_FOO, MyType::MY_BAR),
+ testing::Values("A", "B")),
+ [](const testing::TestParamInfo<MyTestSuite::ParamType>& info) {
+ std::string name = absl::StrCat(
+ std::get<0>(info.param) == MyType::MY_FOO ? "Foo" : "Bar",
+ std::get<1>(info.param));
+ absl::c_replace_if(name, [](char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+```
+
+## Typed Tests
+
+Suppose you have multiple implementations of the same interface and want to make
+sure that all of them satisfy some common requirements. Or, you may have defined
+several types that are supposed to conform to the same "concept" and you want to
+verify it. In both cases, you want the same test logic repeated for different
+types.
+
+While you can write one `TEST` or `TEST_F` for each type you want to test (and
+you may even factor the test logic into a function template that you invoke from
+the `TEST`), it's tedious and doesn't scale: if you want `m` tests over `n`
+types, you'll end up writing `m*n` `TEST`s.
+
+*Typed tests* allow you to repeat the same test logic over a list of types. You
+only need to write the test logic once, although you must know the type list
+when writing typed tests. Here's how you do it:
+
+First, define a fixture class template. It should be parameterized by a type.
+Remember to derive it from `::testing::Test`:
+
+```c++
+template <typename T>
+class FooTest : public testing::Test {
+ public:
+ ...
+ using List = std::list<T>;
+ static T shared_;
+ T value_;
+};
+```
+
+Next, associate a list of types with the test suite, which will be repeated for
+each type in the list:
+
+```c++
+using MyTypes = ::testing::Types<char, int, unsigned int>;
+TYPED_TEST_SUITE(FooTest, MyTypes);
+```
+
+The type alias (`using` or `typedef`) is necessary for the `TYPED_TEST_SUITE`
+macro to parse correctly. Otherwise the compiler will think that each comma in
+the type list introduces a new macro argument.
+
+Then, use `TYPED_TEST()` instead of `TEST_F()` to define a typed test for this
+test suite. You can repeat this as many times as you want:
+
+```c++
+TYPED_TEST(FooTest, DoesBlah) {
+ // Inside a test, refer to the special name TypeParam to get the type
+ // parameter. Since we are inside a derived class template, C++ requires
+ // us to visit the members of FooTest via 'this'.
+ TypeParam n = this->value_;
+
+ // To visit static members of the fixture, add the 'TestFixture::'
+ // prefix.
+ n += TestFixture::shared_;
+
+ // To refer to typedefs in the fixture, add the 'typename TestFixture::'
+ // prefix. The 'typename' is required to satisfy the compiler.
+ typename TestFixture::List values;
+
+ values.push_back(n);
+ ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+```
+
+You can see [sample6_unittest.cc] for a complete example.
+
+[sample6_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample6_unittest.cc "Typed Test example"
+
+## Type-Parameterized Tests
+
+*Type-parameterized tests* are like typed tests, except that they don't require
+you to know the list of types ahead of time. Instead, you can define the test
+logic first and instantiate it with different type lists later. You can even
+instantiate it more than once in the same program.
+
+If you are designing an interface or concept, you can define a suite of
+type-parameterized tests to verify properties that any valid implementation of
+the interface/concept should have. Then, the author of each implementation can
+just instantiate the test suite with their type to verify that it conforms to
+the requirements, without having to write similar tests repeatedly. Here's an
+example:
+
+First, define a fixture class template, as we did with typed tests:
+
+```c++
+template <typename T>
+class FooTest : public testing::Test {
+ void DoSomethingInteresting();
+ ...
+};
+```
+
+Next, declare that you will define a type-parameterized test suite:
+
+```c++
+TYPED_TEST_SUITE_P(FooTest);
+```
+
+Then, use `TYPED_TEST_P()` to define a type-parameterized test. You can repeat
+this as many times as you want:
+
+```c++
+TYPED_TEST_P(FooTest, DoesBlah) {
+ // Inside a test, refer to TypeParam to get the type parameter.
+ TypeParam n = 0;
+
+ // You will need to use `this` explicitly to refer to fixture members.
+ this->DoSomethingInteresting()
+ ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+```
+
+Now the tricky part: you need to register all test patterns using the
+`REGISTER_TYPED_TEST_SUITE_P` macro before you can instantiate them. The first
+argument of the macro is the test suite name; the rest are the names of the
+tests in this test suite:
+
+```c++
+REGISTER_TYPED_TEST_SUITE_P(FooTest,
+ DoesBlah, HasPropertyA);
+```
+
+Finally, you are free to instantiate the pattern with the types you want. If you
+put the above code in a header file, you can `#include` it in multiple C++
+source files and instantiate it multiple times.
+
+```c++
+using MyTypes = ::testing::Types<char, int, unsigned int>;
+INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
+```
+
+To distinguish different instances of the pattern, the first argument to the
+`INSTANTIATE_TYPED_TEST_SUITE_P` macro is a prefix that will be added to the
+actual test suite name. Remember to pick unique prefixes for different
+instances.
+
+In the special case where the type list contains only one type, you can write
+that type directly without `::testing::Types<...>`, like this:
+
+```c++
+INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int);
+```
+
+You can see [sample6_unittest.cc] for a complete example.
+
+## Testing Private Code
+
+If you change your software's internal implementation, your tests should not
+break as long as the change is not observable by users. Therefore, **per the
+black-box testing principle, most of the time you should test your code through
+its public interfaces.**
+
+**If you still find yourself needing to test internal implementation code,
+consider if there's a better design.** The desire to test internal
+implementation is often a sign that the class is doing too much. Consider
+extracting an implementation class, and testing it. Then use that implementation
+class in the original class.
+
+If you absolutely have to test non-public interface code though, you can. There
+are two cases to consider:
+
+* Static functions ( *not* the same as static member functions!) or unnamed
+ namespaces, and
+* Private or protected class members
+
+To test them, we use the following special techniques:
+
+* Both static functions and definitions/declarations in an unnamed namespace
+ are only visible within the same translation unit. To test them, you can
+ `#include` the entire `.cc` file being tested in your `*_test.cc` file.
+ (#including `.cc` files is not a good way to reuse code - you should not do
+ this in production code!)
+
+ However, a better approach is to move the private code into the
+ `foo::internal` namespace, where `foo` is the namespace your project
+ normally uses, and put the private declarations in a `*-internal.h` file.
+ Your production `.cc` files and your tests are allowed to include this
+ internal header, but your clients are not. This way, you can fully test your
+ internal implementation without leaking it to your clients.
+
+* Private class members are only accessible from within the class or by
... 108833 lines suppressed ...
(trafficserver) 09/09: Proxy Verifier v3.1.3 (#13217)
Posted by cm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit e84ab1a96820bf6b872b398d3dbdbe980cb1faa9
Author: Brian Neradt <br...@gmail.com>
AuthorDate: Fri May 29 15:48:38 2026 -0500
Proxy Verifier v3.1.3 (#13217)
This new release contains a Proxy Verifier bug fix for large HTTP/3
bodies.
(cherry picked from commit b4108528ccb286ee1f6ebc7f28eac8117efe4ef2)
---
tests/proxy-verifier-checksum.txt | 2 +-
tests/proxy-verifier-version.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/proxy-verifier-checksum.txt b/tests/proxy-verifier-checksum.txt
index 59315e96fc..9c2ec8528b 100644
--- a/tests/proxy-verifier-checksum.txt
+++ b/tests/proxy-verifier-checksum.txt
@@ -1 +1 @@
-0a60c646cbc9326abb2fbc397cb9efa8c08a807a
+342286244d441329c12de1122520da6c86c581fd
diff --git a/tests/proxy-verifier-version.txt b/tests/proxy-verifier-version.txt
index 9f94b801a3..66cfae52b2 100644
--- a/tests/proxy-verifier-version.txt
+++ b/tests/proxy-verifier-version.txt
@@ -1 +1 @@
-v2.12.0
+v3.1.3
(trafficserver) 01/09: slice: Fix a crash caused by use-after-free (#13113)
Posted by cm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit a50f7e3c063dcd19c3cf4187334ab19676a99bf1
Author: Masakazu Kitajo <ma...@apache.org>
AuthorDate: Wed Apr 22 11:14:30 2026 -0600
slice: Fix a crash caused by use-after-free (#13113)
(cherry picked from commit 0eac5a15f2e9c073c0da34387ce05914a93283c3)
---
plugins/slice/Data.h | 5 +++--
plugins/slice/server.cc | 35 ++++++++++++++++-------------------
plugins/slice/slice.cc | 13 ++++++++++---
3 files changed, 29 insertions(+), 24 deletions(-)
diff --git a/plugins/slice/Data.h b/plugins/slice/Data.h
index 754a2c331e..0628dc936d 100644
--- a/plugins/slice/Data.h
+++ b/plugins/slice/Data.h
@@ -25,6 +25,7 @@
#include "Stage.h"
#include <netinet/in.h>
+#include <string>
#include <unordered_map>
struct Config;
@@ -49,8 +50,8 @@ struct Data {
sockaddr_storage m_client_ip;
- // transaction pointer
- TSHttpTxn m_txnp{nullptr};
+ // cached effective URL for use during async intercept processing
+ std::string m_effective_url;
// for pristine/effective url coming in
TSMBuffer m_urlbuf{nullptr};
diff --git a/plugins/slice/server.cc b/plugins/slice/server.cc
index bad9947994..3158c786ad 100644
--- a/plugins/slice/server.cc
+++ b/plugins/slice/server.cc
@@ -89,27 +89,24 @@ enum HeaderState {
};
static void
-update_object_size(TSHttpTxn txnp, int64_t size, Config &config)
+update_object_size(std::string_view const url, int64_t size, Config &config)
{
- int urllen = 0;
- char *urlstr = TSHttpTxnEffectiveUrlStringGet(txnp, &urllen);
- if (urlstr != nullptr) {
- if (size <= 0) {
- DEBUG_LOG("Ignoring invalid content length for %.*s: %" PRId64, urllen, urlstr, size);
- return;
- }
+ if (url.empty()) {
+ ERROR_LOG("Could not get URL from transaction.");
+ return;
+ }
- if (static_cast<uint64_t>(size) >= config.m_min_size_to_slice) {
- config.sizeCacheAdd({urlstr, static_cast<size_t>(urllen)}, static_cast<uint64_t>(size));
- TSStatIntIncrement(config.stat_TP, 1);
- } else {
- config.sizeCacheRemove({urlstr, static_cast<size_t>(urllen)});
- TSStatIntIncrement(config.stat_FP, 1);
- }
+ if (size <= 0) {
+ DEBUG_LOG("Ignoring invalid content length for %.*s: %" PRId64, static_cast<int>(url.size()), url.data(), size);
+ return;
+ }
- TSfree(urlstr);
+ if (static_cast<uint64_t>(size) >= config.m_min_size_to_slice) {
+ config.sizeCacheAdd(url, static_cast<uint64_t>(size));
+ TSStatIntIncrement(config.stat_TP, 1);
} else {
- ERROR_LOG("Could not get URL from transaction.");
+ config.sizeCacheRemove(url);
+ TSStatIntIncrement(config.stat_FP, 1);
}
}
@@ -147,7 +144,7 @@ handleFirstServerHeader(Data *const data, TSCont const contp)
}
DEBUG_LOG("Passthru bytes: header: %" PRId64 " body: %" PRId64, hlen, clen);
if (clen != INT64_MAX) {
- update_object_size(data->m_txnp, clen, *data->m_config);
+ update_object_size(data->m_effective_url, clen, *data->m_config);
TSVIONBytesSet(output_vio, hlen + clen);
} else {
TSVIONBytesSet(output_vio, clen);
@@ -167,7 +164,7 @@ handleFirstServerHeader(Data *const data, TSCont const contp)
return HeaderState::Fail;
}
- update_object_size(data->m_txnp, blockcr.m_length, *data->m_config);
+ update_object_size(data->m_effective_url, blockcr.m_length, *data->m_config);
// set the resource content length from block response
data->m_contentlen = blockcr.m_length;
diff --git a/plugins/slice/slice.cc b/plugins/slice/slice.cc
index 9be1a8b729..119f28c539 100644
--- a/plugins/slice/slice.cc
+++ b/plugins/slice/slice.cc
@@ -105,7 +105,14 @@ read_request(TSHttpTxn txnp, Config *const config, TSCont read_resp_hdr_contp)
std::unique_ptr<Data> data = std::make_unique<Data>(config);
data->m_method_type = header.method();
- data->m_txnp = txnp;
+
+ // Cache the effective URL now while txnp is still valid
+ int efflen = 0;
+ char *effstr = TSHttpTxnEffectiveUrlStringGet(txnp, &efflen);
+ if (effstr != nullptr) {
+ data->m_effective_url.assign(effstr, efflen);
+ TSfree(effstr);
+ }
// set up feedback connect
if (AF_INET == ip->sa_family) {
@@ -197,8 +204,8 @@ read_request(TSHttpTxn txnp, Config *const config, TSCont read_resp_hdr_contp)
}
}
- data->m_buffer_index = TSPluginVCIOBufferIndexGet(data->m_txnp); // default of m_buffer_index = 32KB
- data->m_buffer_water_mark = TSPluginVCIOBufferWaterMarkGet(data->m_txnp); // default of m_buffer_water_mark = 0
+ data->m_buffer_index = TSPluginVCIOBufferIndexGet(txnp); // default of m_buffer_index = 32KB
+ data->m_buffer_water_mark = TSPluginVCIOBufferWaterMarkGet(txnp); // default of m_buffer_water_mark = 0
if (dbg_ctl.on()) {
int len = 0;
(trafficserver) 05/09: Fix autest compatibility with Fedora 43 / Python 3.14 (#12857)
Posted by cm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 89e24aa431844015aeb10445a49e05ee4758d897
Author: Bryan Call <bc...@apache.org>
AuthorDate: Tue Feb 10 15:09:34 2026 -0800
Fix autest compatibility with Fedora 43 / Python 3.14 (#12857)
Fix autest compatibility with Python 3.14, OpenSSL 3.x, and
Fedora 43 crypto-policies. Updates deprecated Python APIs, adds
socket timeouts, skips legacy TLS tests when TLSv1.0/1.1 are
disabled by system policy, and fixes a timing flake.
(cherry picked from commit e0694752109acfde70eb09c499e3d8db64642ae3)
---
tests/gold_tests/autest-site/conditions.test.ext | 53 ++++++++++++++++++++++
tests/gold_tests/autest-site/microserver.test.ext | 25 ++++++----
tests/gold_tests/autest-site/ports.py | 2 +-
.../polite_hook_wait/polite_hook_wait.cc | 3 +-
tests/gold_tests/tls/tls_client_versions.test.py | 1 +
.../tls/tls_client_versions_minmax.test.py | 1 +
6 files changed, 74 insertions(+), 11 deletions(-)
diff --git a/tests/gold_tests/autest-site/conditions.test.ext b/tests/gold_tests/autest-site/conditions.test.ext
index ed2656a32c..e01fecdb85 100644
--- a/tests/gold_tests/autest-site/conditions.test.ext
+++ b/tests/gold_tests/autest-site/conditions.test.ext
@@ -16,6 +16,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
import subprocess
import json
import re
@@ -51,6 +52,57 @@ def IsOpenSSL(self):
"SSL library is not OpenSSL")
+def HasLegacyTLSSupport(self):
+ """Check if the system supports legacy TLS protocols (TLSv1.0 and TLSv1.1).
+
+ Modern OpenSSL 3.x installations often disable these protocols entirely,
+ even if the openssl binary still accepts the -tls1 flag and lists TLSv1 ciphers.
+
+ On Fedora/RHEL systems, the crypto-policies framework may disable legacy
+ TLS at runtime even when OpenSSL is compiled with support for it. This
+ causes 'openssl ciphers -v -tls1' to still list TLSv1 ciphers, but actual
+ TLS 1.0 connections will fail with "no protocols available".
+
+ We only probe TLSv1.0 (not TLSv1.1 separately) because crypto-policies
+ always disable both legacy versions together. If TLSv1.0 is unavailable,
+ TLSv1.1 will be too.
+
+ The check connects to localhost on a closed port to avoid any external
+ network dependency. A "connection refused" error means the TLS protocol
+ was available but nothing was listening; "no protocols available" means
+ the crypto-policy blocked TLSv1.0 entirely.
+ """
+
+ def check_tls1_support():
+ try:
+ # Connect to localhost on a port nothing is listening on.
+ # This avoids external network dependency while still detecting
+ # whether the crypto-policy allows TLSv1.0.
+ result = subprocess.run(
+ ['openssl', 's_client', '-tls1', '-connect', '127.0.0.1:1'],
+ capture_output=True,
+ text=True,
+ timeout=5,
+ input='' # Don't wait for interactive input
+ )
+ output = result.stdout + result.stderr
+ # "no protocols available" means TLSv1 is disabled by crypto-policy
+ if 'no protocols available' in output:
+ return False
+ # Connection refused or other errors mean TLSv1 was attempted
+ # (the protocol is available, just no server listening)
+ return True
+ except subprocess.TimeoutExpired:
+ # Timeout on localhost shouldn't happen, but if it does,
+ # assume TLSv1 is not available (safer than false positive)
+ return False
+ except Exception:
+ # If we can't determine, assume TLSv1 is not available (safer)
+ return False
+
+ return self.Condition(check_tls1_support, "System does not support legacy TLS protocols (TLSv1.0/TLSv1.1)")
+
+
def HasCurlVersion(self, version):
return self.EnsureVersion(["curl", "--version"], min_version=version)
@@ -118,6 +170,7 @@ ExtendCondition(HasOpenSSLVersion)
ExtendCondition(HasProxyVerifierVersion)
ExtendCondition(IsBoringSSL)
ExtendCondition(IsOpenSSL)
+ExtendCondition(HasLegacyTLSSupport)
ExtendCondition(HasATSFeature)
ExtendCondition(HasCurlVersion)
ExtendCondition(HasCurlFeature)
diff --git a/tests/gold_tests/autest-site/microserver.test.ext b/tests/gold_tests/autest-site/microserver.test.ext
index e15547ff18..70c734f42d 100644
--- a/tests/gold_tests/autest-site/microserver.test.ext
+++ b/tests/gold_tests/autest-site/microserver.test.ext
@@ -17,6 +17,7 @@
# limitations under the License.
import json
+import os
import socket
import ssl
@@ -109,7 +110,7 @@ def addSessionFromFiles(self, session_dir):
# make headers with the key and values provided
def makeHeader(self, requestString, **kwargs):
headerStr = requestString + '\r\n'
- for k, v in kwargs.iteritems():
+ for k, v in kwargs.items():
headerStr += k + ': ' + v + '\r\n'
headerStr = headerStr + '\r\n'
return headerStr
@@ -142,14 +143,20 @@ def uServerUpAndRunning(serverHost, port, isSsl, isIPv6, request, clientcert='',
sock.sendall(request.encode())
decoded_output = ''
- while True:
- host.WriteDebug("??")
- output = sock.recv(4096) # suggested bufsize from docs.python.org
- host.WriteDebug("!!")
- if len(output) <= 0:
- break
- else:
- decoded_output += output.decode()
+ sock.settimeout(10.0) # 10 second timeout for recv
+ try:
+ while True:
+ host.WriteDebug("??")
+ output = sock.recv(4096) # suggested bufsize from docs.python.org
+ host.WriteDebug("!!")
+ if len(output) <= 0:
+ break
+ else:
+ decoded_output += output.decode('utf-8', errors='replace')
+ except socket.timeout:
+ host.WriteDebug(['uServerUpAndRunning', 'when'], "Socket timeout waiting for response")
+ sock.close()
+ return False
sock.close()
sock = None
diff --git a/tests/gold_tests/autest-site/ports.py b/tests/gold_tests/autest-site/ports.py
index fc68367fc1..fb36b4088d 100644
--- a/tests/gold_tests/autest-site/ports.py
+++ b/tests/gold_tests/autest-site/ports.py
@@ -74,7 +74,7 @@ def PortOpen(port: int, address: str = None, listening_ports: Set[int] = None) -
host.WriteDebug(
'PortOpen', f"Connection to port {port} succeeded, the port is open, "
"and a future connection cannot use it")
- except socket.error:
+ except OSError:
host.WriteDebug(
'PortOpen', f"socket error for port {port}, port is closed, "
"and therefore a future connection can use it")
diff --git a/tests/gold_tests/pluginTest/polite_hook_wait/polite_hook_wait.cc b/tests/gold_tests/pluginTest/polite_hook_wait/polite_hook_wait.cc
index 8473ada745..e7a8f83238 100644
--- a/tests/gold_tests/pluginTest/polite_hook_wait/polite_hook_wait.cc
+++ b/tests/gold_tests/pluginTest/polite_hook_wait/polite_hook_wait.cc
@@ -202,8 +202,9 @@ Blocking_action::_thread_func(void *vba)
ba->_cont_mutex_locked.store(true, std::memory_order_release);
// This is a stand-in for some blocking call to validate the HTTP request in some way.
+ // Use a longer delay to account for slower systems and variable scheduling latency.
//
- std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
// Pass "validation" for first transaction, fail it for second.
//
diff --git a/tests/gold_tests/tls/tls_client_versions.test.py b/tests/gold_tests/tls/tls_client_versions.test.py
index fcd53c265e..1f0343d9cd 100644
--- a/tests/gold_tests/tls/tls_client_versions.test.py
+++ b/tests/gold_tests/tls/tls_client_versions.test.py
@@ -24,6 +24,7 @@ Test TLS protocol offering based on SNI
# for special domain foo.com only offer TLSv1 and TLSv1_1
Test.SkipUnless(Condition.HasOpenSSLVersion("1.1.1"))
+Test.SkipUnless(Condition.HasLegacyTLSSupport())
# Define default ATS
ts = Test.MakeATSProcess("ts", enable_tls=True)
diff --git a/tests/gold_tests/tls/tls_client_versions_minmax.test.py b/tests/gold_tests/tls/tls_client_versions_minmax.test.py
index 2ea7853580..9c63d0700d 100644
--- a/tests/gold_tests/tls/tls_client_versions_minmax.test.py
+++ b/tests/gold_tests/tls/tls_client_versions_minmax.test.py
@@ -24,6 +24,7 @@ Test TLS protocol offering based on SNI
# for special domain foo.com only offer TLSv1 and TLSv1_1
Test.SkipUnless(Condition.HasOpenSSLVersion("1.1.1"))
+Test.SkipUnless(Condition.HasLegacyTLSSupport())
# Define default ATS
ts = Test.MakeATSProcess("ts", enable_tls=True)
(trafficserver) 04/09: GCC 16: Regex header integer includes (#13193)
Posted by cm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 3da3a0faf2038b702bc031b3459e64894021faa8
Author: Brian Neradt <br...@gmail.com>
AuthorDate: Fri May 22 13:09:51 2026 -0500
GCC 16: Regex header integer includes (#13193)
GCC 16 no longer exposes fixed-width integer types through the current
transitive include path. Include cstdint directly so Regex.h remains
self-contained.
(cherry picked from commit e989d54caa54f1985e6f07d9d7ae47a0b5635e1d)
---
include/tsutil/Regex.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/tsutil/Regex.h b/include/tsutil/Regex.h
index 7daaf5c453..58ff856337 100644
--- a/include/tsutil/Regex.h
+++ b/include/tsutil/Regex.h
@@ -23,10 +23,11 @@
#pragma once
+#include <cstdint>
+#include <memory>
#include <string_view>
#include <string>
#include <vector>
-#include <memory>
/// @brief Match flags for regular expression evaluation.
///
(trafficserver) 02/09: Correct records.yaml record drift (#13177)
Posted by cm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit b43ff3e1a4bfec243f54259393367d54417d71f3
Author: Brian Neradt <br...@gmail.com>
AuthorDate: Mon Jun 8 12:51:40 2026 -0500
Correct records.yaml record drift (#13177)
Several records.yaml entries had drifted from the names or
reloadability registered in RecordsConfig, which leaves generated
config references pointing at records that do not exist or implying
runtime updates that are not supported.
This corrects the obvious doc-only mismatches: typoed directives,
stale QUIC record names and defaults, an unregistered deprecated
admin record, and reloadable annotations that disagree with the
registered update type.
(cherry picked from commit 60b81a72ece8a1e318673048c71d3497e8cf96a5)
---
doc/admin-guide/files/records.yaml.en.rst | 47 +++++++++++--------------------
1 file changed, 16 insertions(+), 31 deletions(-)
diff --git a/doc/admin-guide/files/records.yaml.en.rst b/doc/admin-guide/files/records.yaml.en.rst
index d6af41667e..d131424a99 100644
--- a/doc/admin-guide/files/records.yaml.en.rst
+++ b/doc/admin-guide/files/records.yaml.en.rst
@@ -437,7 +437,7 @@ Thread Variables
before :program:`traffic_server` drops privilege. If this variable
is set to ``NULL``, no helper will be spawned.
-.. ts::vc:: CONFIG proxy.config.core_limit INT -1
+.. ts:cv:: CONFIG proxy.config.core_limit INT -1
This option specifies the size limit for core files in the event
that :program:`traffic_server` crashes. ``-1`` means there is
@@ -691,11 +691,6 @@ Management
* Set the ``user_id=#-1`` and start trafficserver as root.
-.. ts:cv:: CONFIG proxy.config.admin.api.restricted INT 0
-
- This is now deprecated, please refer to :ref:`admin-jsonrpc-configuration` to find
- out about the new admin API mechanism.
-
HTTP Engine
===========
@@ -2406,7 +2401,6 @@ Cache Control
Setting this to ``0`` disables the feature.
.. ts:cv:: CONFIG proxy.config.http.cache.try_compat_key_read INT 0
- :reloadable:
When enabled (``1``), |TS| will try to lookup the cached object using the
previous cache key generation algorithm, but will always write new objects
@@ -2550,7 +2544,7 @@ Cache Control
a minimum time, and the actual sync may be delayed if the disks are larger than
how fast we allow it to write to disk (see next options).
-.. ts:cv:: CONFIG proxy.config.cache.dir.sync_max_writes INT 2097152
+.. ts:cv:: CONFIG proxy.config.cache.dir.sync_max_write INT 2097152
:units: bytes
How much of a stripes cache directory we will write to disk in each write cycle.
@@ -2725,13 +2719,11 @@ Dynamic Content & Content Negotiation
=====================================
.. ts:cv:: CONFIG proxy.config.http.cache.open_read_retry_time INT 10
- :reloadable:
:overridable:
The number of milliseconds a cacheable request will wait before requesting the object from cache if an equivalent request is in flight.
.. ts:cv:: CONFIG proxy.config.http.cache.max_open_read_retries INT -1
- :reloadable:
:overridable:
The number of times to attempt fetching an object from cache if there was an equivalent request in flight.
@@ -2825,7 +2817,6 @@ Customizable User Response Pages
Maximum size of the error template response page.
.. ts:cv:: CONFIG proxy.config.body_factory.response_suppression_mode INT 0
- :reloadable:
:overridable:
Specifies when |TS| suppresses generated response pages:
@@ -3347,7 +3338,7 @@ Logging Configuration
How often |TS| executes log related periodic tasks, in seconds
-.. ts:cv:: CONFIG proxy.config.log.proxy.config.log.throttling_interval_msec INT 60000
+.. ts:cv:: CONFIG proxy.config.log.throttling_interval_msec INT 60000
:reloadable:
:units: milliseconds
@@ -3525,7 +3516,7 @@ Diagnostic Logging Configuration
For details about how log throttling works, see
:ts:cv:`log.throttling_interval_msec
- <proxy.config.log.proxy.config.log.throttling_interval_msec>`.
+ <proxy.config.log.throttling_interval_msec>`.
.. ts:cv:: CONFIG proxy.config.diags.logfile.filename STRING diags.log
@@ -4820,14 +4811,12 @@ removed in the future without prior notice.
A size of hash table that stores connection information.
-.. ts:cv:: CONFIG proxy.config.quic.proxy.config.quic.num_alt_connection_ids INT 65521
- :reloadable:
+.. ts:cv:: CONFIG proxy.config.quic.num_alt_connection_ids INT 8
A number of alternate Connection IDs that |TS| provides to a peer. It has to
be at least 8.
-.. ts:cv:: CONFIG proxy.config.quic.stateless_retry_enabled INT 0
- :reloadable:
+.. ts:cv:: CONFIG proxy.config.quic.server.stateless_retry_enabled INT 0
Enables Stateless Retry.
@@ -4842,19 +4831,16 @@ removed in the future without prior notice.
Enables connection migration exercise on origin server connections.
.. ts:cv:: CONFIG proxy.config.quic.server.supported_groups STRING "P-256:X25519:P-384:P-521"
- :reloadable:
Configures the list of supported groups provided by OpenSSL which will be
used to determine the set of shared groups on QUIC origin server connections.
.. ts:cv:: CONFIG proxy.config.quic.client.supported_groups STRING "P-256:X25519:P-384:P-521"
- :reloadable:
Configures the list of supported groups provided by OpenSSL which will be
used to determine the set of shared groups on QUIC client connections.
.. ts:cv:: CONFIG proxy.config.quic.client.session_file STRING ""
- :reloadable:
Only available for :program:`traffic_quic`.
If specified, TLS session data will be stored to the file, and will be used
@@ -4904,61 +4890,61 @@ removed in the future without prior notice.
This value will be advertised as ``initial_max_data`` Transport Parameter.
-.. ts:cv:: CONFIG proxy.config.quic.max_stream_data_bidi_local_in INT 0
+.. ts:cv:: CONFIG proxy.config.quic.initial_max_stream_data_bidi_local_in INT 0
:reloadable:
This value will be advertised as ``initial_max_stream_data_bidi_local``
Transport Parameter.
-.. ts:cv:: CONFIG proxy.config.quic.max_stream_data_bidi_local_out INT 4096
+.. ts:cv:: CONFIG proxy.config.quic.initial_max_stream_data_bidi_local_out INT 4096
:reloadable:
This value will be advertised as ``initial_max_stream_data_bidi_local``
Transport Parameter.
-.. ts:cv:: CONFIG proxy.config.quic.max_stream_data_bidi_remote_in INT 4096
+.. ts:cv:: CONFIG proxy.config.quic.initial_max_stream_data_bidi_remote_in INT 4096
:reloadable:
This value will be advertised as ``initial_max_stream_data_bidi_remote``
Transport Parameter.
-.. ts:cv:: CONFIG proxy.config.quic.max_stream_data_bidi_remote_out INT 0
+.. ts:cv:: CONFIG proxy.config.quic.initial_max_stream_data_bidi_remote_out INT 0
:reloadable:
This value will be advertised as ``initial_max_stream_data_bidi_remote``
Transport Parameter.
-.. ts:cv:: CONFIG proxy.config.quic.max_stream_data_uni_in INT 4096
+.. ts:cv:: CONFIG proxy.config.quic.initial_max_stream_data_uni_in INT 4096
:reloadable:
This value will be advertised as ``initial_max_stream_data_uni``
Transport Parameter.
-.. ts:cv:: CONFIG proxy.config.quic.max_stream_data_uni_out INT 0
+.. ts:cv:: CONFIG proxy.config.quic.initial_max_stream_data_uni_out INT 4096
:reloadable:
This value will be advertised as ``initial_max_stream_data_uni``
Transport Parameter.
-.. ts:cv:: CONFIG proxy.config.quic.max_streams_bidi_in INT 100
+.. ts:cv:: CONFIG proxy.config.quic.initial_max_streams_bidi_in INT 100
:reloadable:
This value will be advertised as ``initial_max_streams_bidi``
Transport Parameter.
-.. ts:cv:: CONFIG proxy.config.quic.max_streams_bidi_out INT 100
+.. ts:cv:: CONFIG proxy.config.quic.initial_max_streams_bidi_out INT 100
:reloadable:
This value will be advertised as ``initial_max_streams_bidi``
Transport Parameter.
-.. ts:cv:: CONFIG proxy.config.quic.max_streams_uni_in INT 100
+.. ts:cv:: CONFIG proxy.config.quic.initial_max_streams_uni_in INT 100
:reloadable:
This value will be advertised as ``initial_max_streams_uni``
Transport Parameter.
-.. ts:cv:: CONFIG proxy.config.quic.max_streams_uni_out INT 100
+.. ts:cv:: CONFIG proxy.config.quic.initial_max_streams_uni_out INT 100
:reloadable:
This value will be advertised as ``initial_max_streams_uni``
@@ -5179,7 +5165,6 @@ Sockets
Note: If MPTCP is enabled, TCP_DEFER_ACCEPT is only supported on Linux kernels 5.19+.
.. ts:cv:: CONFIG proxy.config.net.listen_backlog INT -1
- :reloadable:
This directive sets the maximum number of pending connections.
If it is set to -1, |TS| will automatically set this
(trafficserver) 06/09: Check Curl support for TLS 1.0 and 1.1 (#12887)
Posted by cm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit b99e662cc9f1173bbc14540449c1be5925f2e102
Author: Bryan Call <bc...@apache.org>
AuthorDate: Fri Feb 13 15:33:13 2026 -0800
Check Curl support for TLS 1.0 and 1.1 (#12887)
Skip TLSv1/TLSv1.1 subtests when curl cannot negotiate those protocols.
Adds a curl-based capability probe alongside the existing OpenSSL check.
(cherry picked from commit 8def184a6fca011141ee5470e78608ae31e24f9c)
---
tests/gold_tests/autest-site/conditions.test.ext | 62 ++++++++++++++++++++++
tests/gold_tests/tls/tls_client_versions.test.py | 31 ++++++-----
.../tls/tls_client_versions_minmax.test.py | 47 ++++++++--------
3 files changed, 105 insertions(+), 35 deletions(-)
diff --git a/tests/gold_tests/autest-site/conditions.test.ext b/tests/gold_tests/autest-site/conditions.test.ext
index e01fecdb85..e228b19fae 100644
--- a/tests/gold_tests/autest-site/conditions.test.ext
+++ b/tests/gold_tests/autest-site/conditions.test.ext
@@ -146,6 +146,67 @@ def HasCurlOption(self, option):
return self.CheckOutput(['curl', '--help', 'all'], default, "Curl needs to support option: {option}".format(option=option))
+def HasCurlTLSVersionSupport(self, tls_version):
+ """Check whether curl can attempt a given TLS version.
+
+ This probes curl directly because OpenSSL capability checks do not always
+ reflect curl runtime policy behavior on hardened systems.
+ """
+
+ def check_curl_tls_support():
+ # Map semantic versions used by tests to curl flags.
+ version_map = {
+ "1.0": ("--tlsv1", "1.0"),
+ "1.1": ("--tlsv1.1", "1.1"),
+ "1.2": ("--tlsv1.2", "1.2"),
+ "1.3": ("--tlsv1.3", "1.3"),
+ }
+ if tls_version not in version_map:
+ return False
+
+ tls_flag, tls_max = version_map[tls_version]
+ try:
+ # Connect to localhost closed port to avoid network dependencies.
+ # "connection refused" means curl accepted the TLS flags and tried.
+ result = subprocess.run(
+ [
+ "curl",
+ "-svk",
+ "--connect-timeout",
+ "2",
+ "--max-time",
+ "3",
+ tls_flag,
+ "--tls-max",
+ tls_max,
+ "https://127.0.0.1:1",
+ ],
+ capture_output=True,
+ text=True,
+ timeout=5,
+ )
+ output = (result.stdout + result.stderr).lower()
+ unsupported_markers = [
+ "unsupported protocol",
+ "no protocols available",
+ "option --tlsv",
+ "unknown option",
+ "is unknown",
+ ]
+ if any(marker in output for marker in unsupported_markers):
+ return False
+
+ # Any attempt to connect implies curl accepted the TLS setting.
+ return True
+ except subprocess.TimeoutExpired:
+ return False
+ except Exception:
+ return False
+
+ return self.Condition(
+ check_curl_tls_support, "Curl does not support TLSv{version} in this environment".format(version=tls_version))
+
+
def HasATSFeature(self, feature):
val = self.Variables.get(feature, None)
@@ -175,5 +236,6 @@ ExtendCondition(HasATSFeature)
ExtendCondition(HasCurlVersion)
ExtendCondition(HasCurlFeature)
ExtendCondition(HasCurlOption)
+ExtendCondition(HasCurlTLSVersionSupport)
ExtendCondition(PluginExists)
ExtendCondition(CurlUsingUnixDomainSocket)
diff --git a/tests/gold_tests/tls/tls_client_versions.test.py b/tests/gold_tests/tls/tls_client_versions.test.py
index 1f0343d9cd..134124eabf 100644
--- a/tests/gold_tests/tls/tls_client_versions.test.py
+++ b/tests/gold_tests/tls/tls_client_versions.test.py
@@ -25,6 +25,7 @@ Test TLS protocol offering based on SNI
Test.SkipUnless(Condition.HasOpenSSLVersion("1.1.1"))
Test.SkipUnless(Condition.HasLegacyTLSSupport())
+has_curl_tlsv1 = Condition.HasCurlTLSVersionSupport("1.0")
# Define default ATS
ts = Test.MakeATSProcess("ts", enable_tls=True)
@@ -85,22 +86,24 @@ tr.ReturnCode = 35
tr.StillRunningAfter = ts
# Target foo.com for TLSv1. Should succeed
-tr = Test.AddTestRun("foo.com TLSv1")
-tr.MakeCurlCommand(
- "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 'foo.com:{0}:127.0.0.1' -k https://foo.com:{0}".format(
- ts.Variables.ssl_port),
- ts=ts)
-tr.ReturnCode = 0
-tr.StillRunningAfter = ts
+if has_curl_tlsv1:
+ tr = Test.AddTestRun("foo.com TLSv1")
+ tr.MakeCurlCommand(
+ "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 'foo.com:{0}:127.0.0.1' -k https://foo.com:{0}".format(
+ ts.Variables.ssl_port),
+ ts=ts)
+ tr.ReturnCode = 0
+ tr.StillRunningAfter = ts
# Target bar.com for TLSv1. Should fail
-tr = Test.AddTestRun("bar.com TLSv1")
-tr.MakeCurlCommand(
- "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 'bar.com:{0}:127.0.0.1' -k https://bar.com:{0}".format(
- ts.Variables.ssl_port),
- ts=ts)
-tr.ReturnCode = 35
-tr.StillRunningAfter = ts
+if has_curl_tlsv1:
+ tr = Test.AddTestRun("bar.com TLSv1")
+ tr.MakeCurlCommand(
+ "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 'bar.com:{0}:127.0.0.1' -k https://bar.com:{0}".format(
+ ts.Variables.ssl_port),
+ ts=ts)
+ tr.ReturnCode = 35
+ tr.StillRunningAfter = ts
# Target bar.com for TLSv1_2. Should succeed
tr = Test.AddTestRun("bar.com TLSv1_2")
diff --git a/tests/gold_tests/tls/tls_client_versions_minmax.test.py b/tests/gold_tests/tls/tls_client_versions_minmax.test.py
index 9c63d0700d..4c0d1742e8 100644
--- a/tests/gold_tests/tls/tls_client_versions_minmax.test.py
+++ b/tests/gold_tests/tls/tls_client_versions_minmax.test.py
@@ -25,6 +25,8 @@ Test TLS protocol offering based on SNI
Test.SkipUnless(Condition.HasOpenSSLVersion("1.1.1"))
Test.SkipUnless(Condition.HasLegacyTLSSupport())
+has_curl_tlsv1 = Condition.HasCurlTLSVersionSupport("1.0")
+has_curl_tlsv1_1 = Condition.HasCurlTLSVersionSupport("1.1")
# Define default ATS
ts = Test.MakeATSProcess("ts", enable_tls=True)
@@ -90,31 +92,34 @@ tr.ReturnCode = 35
tr.StillRunningAfter = ts
# Target foo.com for TLSv1. Should succeed
-tr = Test.AddTestRun("foo.com TLSv1")
-tr.MakeCurlCommand(
- "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 'foo.com:{0}:127.0.0.1' -k https://foo.com:{0}".format(
- ts.Variables.ssl_port),
- ts=ts)
-tr.ReturnCode = 0
-tr.StillRunningAfter = ts
+if has_curl_tlsv1:
+ tr = Test.AddTestRun("foo.com TLSv1")
+ tr.MakeCurlCommand(
+ "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 'foo.com:{0}:127.0.0.1' -k https://foo.com:{0}".format(
+ ts.Variables.ssl_port),
+ ts=ts)
+ tr.ReturnCode = 0
+ tr.StillRunningAfter = ts
# Target foo.com for TLSv1_1. Should succeed
-tr = Test.AddTestRun("foo.com TLSv1_1")
-tr.MakeCurlCommand(
- "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.1 --tlsv1.1 --resolve 'foo.com:{0}:127.0.0.1' -k https://foo.com:{0}".format(
- ts.Variables.ssl_port),
- ts=ts)
-tr.ReturnCode = 0
-tr.StillRunningAfter = ts
+if has_curl_tlsv1_1:
+ tr = Test.AddTestRun("foo.com TLSv1_1")
+ tr.MakeCurlCommand(
+ "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.1 --tlsv1.1 --resolve 'foo.com:{0}:127.0.0.1' -k https://foo.com:{0}".format(
+ ts.Variables.ssl_port),
+ ts=ts)
+ tr.ReturnCode = 0
+ tr.StillRunningAfter = ts
# Target bar.com for TLSv1. Should fail
-tr = Test.AddTestRun("bar.com TLSv1")
-tr.MakeCurlCommand(
- "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 'bar.com:{0}:127.0.0.1' -k https://bar.com:{0}".format(
- ts.Variables.ssl_port),
- ts=ts)
-tr.ReturnCode = 35
-tr.StillRunningAfter = ts
+if has_curl_tlsv1:
+ tr = Test.AddTestRun("bar.com TLSv1")
+ tr.MakeCurlCommand(
+ "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 'bar.com:{0}:127.0.0.1' -k https://bar.com:{0}".format(
+ ts.Variables.ssl_port),
+ ts=ts)
+ tr.ReturnCode = 35
+ tr.StillRunningAfter = ts
# Target bar.com for TLSv1_2. Should succeed
tr = Test.AddTestRun("bar.com TLSv1_2")
(trafficserver) 08/09: Single source of truth for Proxy Verifier metadata (#13200)
Posted by cm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 8202d03d32226da35c68359c36b0d9b08fc44ca9
Author: Brian Neradt <br...@gmail.com>
AuthorDate: Mon May 25 21:41:21 2026 -0500
Single source of truth for Proxy Verifier metadata (#13200)
references correctly, but missed the CMakeLists checksum. Currently, the
version and checksums for the Proxy Verifier release are referenced in
multiple places, making it easy to miss updating the various required
locations. This is bad.
This patch adds a checksum companion file next to the version file and
teaches all the consumers to read the shared version/checksum sources
when downloading Proxy Verifier.
(cherry picked from commit ac9b5cf8fc5738fd080ee918a740ebf51d39132d)
---
CMakeLists.txt | 7 +++++--
tests/prepare_proxy_verifier.sh | 23 +++++++++++------------
tests/proxy-verifier-checksum.txt | 1 +
3 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d6fbddf3f5..24fe8c0fb6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -638,8 +638,11 @@ if(ENABLE_AUTEST)
# the autest command. The original AUTEST_OPTIONS string is used in the
# autest.sh script.
separate_arguments(AUTEST_OPTIONS_LIST UNIX_COMMAND "${AUTEST_OPTIONS}")
- set(PROXY_VERIFIER_VERSION "v2.12.0")
- set(PROXY_VERIFIER_HASH "SHA1=8e9adc6e0b31251ca8e6fc2064ae54e5d752bb72")
+ file(READ "${CMAKE_SOURCE_DIR}/tests/proxy-verifier-version.txt" PROXY_VERIFIER_VERSION)
+ string(STRIP "${PROXY_VERIFIER_VERSION}" PROXY_VERIFIER_VERSION)
+ file(READ "${CMAKE_SOURCE_DIR}/tests/proxy-verifier-checksum.txt" PROXY_VERIFIER_SHA1)
+ string(STRIP "${PROXY_VERIFIER_SHA1}" PROXY_VERIFIER_SHA1)
+ set(PROXY_VERIFIER_HASH "SHA1=${PROXY_VERIFIER_SHA1}")
include(proxy-verifier)
endif()
diff --git a/tests/prepare_proxy_verifier.sh b/tests/prepare_proxy_verifier.sh
index 729bf82aa9..e280d5182f 100755
--- a/tests/prepare_proxy_verifier.sh
+++ b/tests/prepare_proxy_verifier.sh
@@ -17,8 +17,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-fail()
-{
+fail() {
echo $1
exit 1
}
@@ -30,9 +29,11 @@ ROOT=${ROOT:-${SCRIPT_DIR}}
PV_VERSION_FILE="${ROOT}/tests/proxy-verifier-version.txt"
[ -r "${PV_VERSION_FILE}" ] || fail "\"${PV_VERSION_FILE}\" does not exist."
+PV_SUM_FILE="${ROOT}/tests/proxy-verifier-checksum.txt"
+[ -r "${PV_SUM_FILE}" ] || fail "\"${PV_SUM_FILE}\" does not exist."
pv_name="proxy-verifier"
-pv_version=`cat ${ROOT}/tests/proxy-verifier-version.txt`
+read -r pv_version <"${PV_VERSION_FILE}"
pv_top_dir="${ROOT}/tests/proxy-verifier"
pv_unpack_dir="${pv_top_dir}/unpack/${pv_version}"
bin_dir="${pv_unpack_dir}/bin"
@@ -40,29 +41,26 @@ pv_dir="${pv_name}-${pv_version}"
pv_tar_filename="${pv_dir}.tar.gz"
pv_tar="${pv_top_dir}/${pv_tar_filename}"
pv_tar_url="https://ci.trafficserver.apache.org/bintray/${pv_tar_filename}"
-expected_sha1="8e9adc6e0b31251ca8e6fc2064ae54e5d752bb72"
+read -r expected_sha1 <"${PV_SUM_FILE}"
pv_client="${bin_dir}/verifier-client"
pv_server="${bin_dir}/verifier-server"
TAR=${TAR:-tar}
CURL=${CURL:-curl}
# Check to see whether Proxy Verifier has already been unpacked.
-if ! [ -x ${pv_client} -a -x ${pv_server} ]
-then
+if ! [ -x ${pv_client} -a -x ${pv_server} ]; then
# 1. Get the tar file if it has not been retrieved already.
# Note that the two spaces between the hash and ${ARCHIVE) is needed
- if [ ! -e ${pv_tar} ]
- then
+ if [ ! -e ${pv_tar} ]; then
# default to using native sha1sum command when available
- if [ $(which sha1sum) ]
- then
+ if [ $(which sha1sum) ]; then
SHASUM=${SHASUM:-sha1sum}
else
SHASUM=${SHASUM:-shasum}
fi
mkdir -p ${pv_top_dir}
- ${CURL} -L --progress-bar -o ${pv_tar} ${pv_tar_url} || \
+ ${CURL} -L --progress-bar -o ${pv_tar} ${pv_tar_url} ||
fail "Failed to download ${pv_tar_url}."
- cat > ${pv_top_dir}/sha1 << EOF
+ cat >${pv_top_dir}/sha1 <<EOF
${expected_sha1} ${pv_tar}
EOF
${SHASUM} -c ${pv_top_dir}/sha1 || fail "SHA1 mismatch for downloaded ${pv_tar_filename}."
@@ -104,6 +102,7 @@ EOF
;;
*)
fail "We need to build proxy-verifier for $(uname -s)"
+ ;;
esac
# 4. Link the OS-specific binaries to the bin directory.
diff --git a/tests/proxy-verifier-checksum.txt b/tests/proxy-verifier-checksum.txt
new file mode 100644
index 0000000000..59315e96fc
--- /dev/null
+++ b/tests/proxy-verifier-checksum.txt
@@ -0,0 +1 @@
+0a60c646cbc9326abb2fbc397cb9efa8c08a807a
(trafficserver) 07/09: Fedora 44 test fixes (#13198)
Posted by cm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit b9b38b4f7d1c07aa49137b8a3b0f785acde225ec
Author: Brian Neradt <br...@gmail.com>
AuthorDate: Wed May 27 12:10:19 2026 -0500
Fedora 44 test fixes (#13198)
* Probe legacy TLS handshakes in tests
Fedora 44 crypto policy can accept legacy TLS command-line flags
while rejecting real TLS 1.0 and 1.1 handshakes. Closed-port probes
therefore let legacy TLS AuTests run in environments where the protocol
cannot actually negotiate.
This uses the AuTest port allocator to start a local OpenSSL server and
probe a real handshake before enabling those tests. The same helper also
gates curl TLS-version checks so both probes reflect runtime policy
rather than option parsing.
* Update cert select curl expectation
Newer curl and OpenSSL versions still return 60 for the bad-CA case,
but their verbose output includes the presented certificate and uses
different verification text. The old expectation made the cert-selection
AuTest depend on wording that varies by toolchain.
This keeps the assertion on the stable certificate-verification failure
and checks that the selected certificate is for bar.com, while still
rejecting the foo.com certificate in that failure path.
* Use temp socket path in JSONRPC test
Docker bind mounts can reject Unix-domain socket connects even after the
socket inode is created. The JSONRPC Catch test hit that behavior in the
Fedora 44 container when its socket was under the bind-mounted tree.
This moves the socket and lock into a per-run temporary directory and
defers setup to Catch startup so failures are reported by the test
framework. This also falls back to a short /tmp path when the temp path
would exceed Unix socket limits.
(cherry picked from commit 4f76e2f356e9551d388a5f5a4bd38fc351d63998)
---
src/mgmt/rpc/server/unit_tests/test_rpcserver.cc | 90 ++++++++-
tests/gold_tests/autest-site/conditions.test.ext | 225 +++++++++++++++------
tests/gold_tests/autest-site/ports.py | 65 ++++--
.../tls/tls_check_cert_select_plugin.test.py | 5 +-
4 files changed, 297 insertions(+), 88 deletions(-)
diff --git a/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc b/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc
index d560b80591..e406be2907 100644
--- a/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc
+++ b/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc
@@ -25,11 +25,16 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
+#include <unistd.h>
#include <thread>
#include <future>
#include <chrono>
#include <fstream>
+#include <cerrno>
+#include <cstring>
+#include <cstdlib>
+#include <vector>
#include "swoc/swoc_file.h"
@@ -68,12 +73,75 @@ add_method_handler(const std::string &name, Func &&call)
namespace
{
-const std::string sockPath{"tests/var/jsonrpc20_test.sock"};
-const std::string lockPath{"tests/var/jsonrpc20_test.lock"};
-constexpr int default_backlog{5};
-constexpr int default_maxRetriesOnTransientErrors{64};
-constexpr size_t default_incoming_req_max_size{32000 * 3};
-DbgCtl dbg_ctl{"rpc.test.client"};
+constexpr std::string_view rpc_test_dir_template{"ats_rpc_XXXXXX"};
+constexpr std::string_view rpc_test_socket_name{"s"};
+constexpr std::string_view rpc_test_lock_name{"l"};
+constexpr size_t max_rpc_socket_path_size{sizeof(sockaddr_un::sun_path) - 1};
+
+fs::path rpcTestDir;
+std::string sockPath;
+std::string lockPath;
+constexpr int default_backlog{5};
+constexpr int default_maxRetriesOnTransientErrors{64};
+constexpr size_t default_incoming_req_max_size{32000 * 3};
+DbgCtl dbg_ctl{"rpc.test.client"};
+
+/** Prepare JSONRPC socket paths beneath @a base.
+ *
+ * This owns creation of the per-run test directory and publishes the socket
+ * and lock paths shared by the JSONRPC test server and clients.
+ *
+ * @param[in] base Candidate parent directory for the test directory.
+ * @param[out] error Reason setup failed, if a usable directory was not created.
+ * @return @c true if the socket and lock paths are ready for this test run.
+ */
+bool
+try_setup_rpc_test_paths(fs::path const &base, std::string &error)
+{
+ auto const dir_template = (base / rpc_test_dir_template).string();
+ auto const socket_path = (fs::path{dir_template} / rpc_test_socket_name).string();
+
+ if (socket_path.size() > max_rpc_socket_path_size) {
+ error = "JSONRPC test socket path is too long under " + base.string() + ": " + socket_path;
+ return false;
+ }
+
+ std::vector<char> mutable_template{dir_template.begin(), dir_template.end()};
+ mutable_template.push_back('\0');
+
+ char *created_dir = mkdtemp(mutable_template.data());
+ if (created_dir == nullptr) {
+ error = "Failed to create JSONRPC test directory under " + base.string() + ": " + std::strerror(errno);
+ return false;
+ }
+
+ rpcTestDir = fs::path{created_dir};
+ sockPath = (rpcTestDir / rpc_test_socket_name).string();
+ lockPath = (rpcTestDir / rpc_test_lock_name).string();
+ return true;
+}
+
+/** Prepare JSONRPC socket paths for the test run.
+ *
+ * This prefers the environment temporary directory, then falls back to @c /tmp
+ * when the generated Unix-domain socket path would be too long or setup fails.
+ *
+ * @param[out] error Reason setup failed, if no candidate directory works.
+ * @return @c true if the socket and lock paths are ready for this test run.
+ */
+bool
+setup_rpc_test_paths(std::string &error)
+{
+ if (try_setup_rpc_test_paths(fs::temp_directory_path(), error)) {
+ error.clear();
+ return true;
+ }
+ if (try_setup_rpc_test_paths(fs::path{"/tmp"}, error)) {
+ error.clear();
+ return true;
+ }
+ return false;
+}
} // end anonymous namespace
@@ -85,6 +153,11 @@ struct RPCServerTestListener : Catch::TestEventListenerBase {
void
testRunStarting(Catch::TestRunInfo const & /* testRunInfo ATS_UNUSED */) override
{
+ std::string setup_error;
+ bool const setup_ok = setup_rpc_test_paths(setup_error);
+ INFO(setup_error);
+ REQUIRE(setup_ok);
+
Layout::create();
init_diags("rpc", nullptr);
RecProcessInit();
@@ -120,6 +193,11 @@ struct RPCServerTestListener : Catch::TestEventListenerBase {
if (jsonrpcServer) {
delete jsonrpcServer; // will stop the thread
}
+
+ std::error_code ec;
+ if (!rpcTestDir.empty()) {
+ fs::remove_all(rpcTestDir, ec);
+ }
}
private:
diff --git a/tests/gold_tests/autest-site/conditions.test.ext b/tests/gold_tests/autest-site/conditions.test.ext
index e228b19fae..41c5a6cacd 100644
--- a/tests/gold_tests/autest-site/conditions.test.ext
+++ b/tests/gold_tests/autest-site/conditions.test.ext
@@ -20,6 +20,110 @@ import os
import subprocess
import json
import re
+import tempfile
+import time
+
+from ports import get_port_number
+
+OPENSSL_TLS_FLAGS = {
+ "1.0": "-tls1",
+ "1.1": "-tls1_1",
+ "1.2": "-tls1_2",
+ "1.3": "-tls1_3",
+}
+
+
+def _terminate_process(process):
+ if process.poll() is not None:
+ return
+ try:
+ process.terminate()
+ process.wait(timeout=2)
+ except (OSError, subprocess.TimeoutExpired):
+ try:
+ process.kill()
+ process.wait(timeout=2)
+ except (OSError, subprocess.TimeoutExpired):
+ pass
+
+
+def _probe_openssl_server(tls_version, client_probe):
+ """Run a local OpenSSL server for TLS capability probes.
+
+ This owns the temporary certificate, port allocation, and server process
+ lifecycle so AuTest conditions can perform a real handshake with the client
+ being checked. Local setup failures return ``False`` so callers can skip
+ dependent tests instead of failing the harness.
+
+ :param tls_version: TLS version string to look up in
+ ``OPENSSL_TLS_FLAGS``.
+ :param client_probe: Callable that receives the server port and TLS flag
+ and returns whether the client completed the expected handshake.
+ :returns: ``True`` if the client probe succeeds against the local server,
+ otherwise ``False``.
+ """
+ tls_flag = OPENSSL_TLS_FLAGS.get(tls_version)
+ if tls_flag is None:
+ return False
+
+ try:
+ with tempfile.TemporaryDirectory() as tmpdir:
+ cert_path = os.path.join(tmpdir, "cert.pem")
+ key_path = os.path.join(tmpdir, "key.pem")
+ result = subprocess.run(
+ [
+ "openssl",
+ "req",
+ "-x509",
+ "-newkey",
+ "rsa:2048",
+ "-nodes",
+ "-sha256",
+ "-keyout",
+ key_path,
+ "-out",
+ cert_path,
+ "-subj",
+ "/CN=localhost",
+ "-days",
+ "1",
+ ],
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ timeout=10,
+ )
+ if result.returncode != 0:
+ return False
+
+ with get_port_number() as port:
+ server = subprocess.Popen(
+ [
+ "openssl",
+ "s_server",
+ "-quiet",
+ "-accept",
+ f"127.0.0.1:{port}",
+ "-cert",
+ cert_path,
+ "-key",
+ key_path,
+ tls_flag,
+ "-cipher",
+ "DEFAULT@SECLEVEL=0",
+ "-www",
+ ],
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ )
+ try:
+ time.sleep(0.5)
+ if server.poll() is not None:
+ return False
+ return client_probe(port, tls_flag)
+ finally:
+ _terminate_process(server)
+ except (OSError, subprocess.SubprocessError):
+ return False
def HasOpenSSLVersion(self, version):
@@ -67,38 +171,39 @@ def HasLegacyTLSSupport(self):
always disable both legacy versions together. If TLSv1.0 is unavailable,
TLSv1.1 will be too.
- The check connects to localhost on a closed port to avoid any external
- network dependency. A "connection refused" error means the TLS protocol
- was available but nothing was listening; "no protocols available" means
- the crypto-policy blocked TLSv1.0 entirely.
+ The check starts a local OpenSSL server and uses an OpenSSL client to
+ complete a real TLSv1.0 handshake. This avoids external network dependency
+ while catching environments that accept legacy TLS command-line flags but
+ reject the protocol during an actual handshake.
"""
def check_tls1_support():
- try:
- # Connect to localhost on a port nothing is listening on.
- # This avoids external network dependency while still detecting
- # whether the crypto-policy allows TLSv1.0.
- result = subprocess.run(
- ['openssl', 's_client', '-tls1', '-connect', '127.0.0.1:1'],
- capture_output=True,
- text=True,
- timeout=5,
- input='' # Don't wait for interactive input
- )
- output = result.stdout + result.stderr
- # "no protocols available" means TLSv1 is disabled by crypto-policy
- if 'no protocols available' in output:
+
+ def client_probe(port, tls_flag):
+ try:
+ result = subprocess.run(
+ [
+ 'openssl',
+ 's_client',
+ tls_flag,
+ '-connect',
+ f'127.0.0.1:{port}',
+ '-cipher',
+ 'DEFAULT@SECLEVEL=0',
+ '-brief',
+ ],
+ capture_output=True,
+ text=True,
+ timeout=5,
+ input='Q\n')
+ output = result.stdout + result.stderr
+ return result.returncode == 0 and 'Protocol version: TLSv1' in output
+ except subprocess.TimeoutExpired:
+ return False
+ except Exception:
return False
- # Connection refused or other errors mean TLSv1 was attempted
- # (the protocol is available, just no server listening)
- return True
- except subprocess.TimeoutExpired:
- # Timeout on localhost shouldn't happen, but if it does,
- # assume TLSv1 is not available (safer than false positive)
- return False
- except Exception:
- # If we can't determine, assume TLSv1 is not available (safer)
- return False
+
+ return _probe_openssl_server("1.0", client_probe)
return self.Condition(check_tls1_support, "System does not support legacy TLS protocols (TLSv1.0/TLSv1.1)")
@@ -154,7 +259,6 @@ def HasCurlTLSVersionSupport(self, tls_version):
"""
def check_curl_tls_support():
- # Map semantic versions used by tests to curl flags.
version_map = {
"1.0": ("--tlsv1", "1.0"),
"1.1": ("--tlsv1.1", "1.1"),
@@ -165,43 +269,36 @@ def HasCurlTLSVersionSupport(self, tls_version):
return False
tls_flag, tls_max = version_map[tls_version]
- try:
- # Connect to localhost closed port to avoid network dependencies.
- # "connection refused" means curl accepted the TLS flags and tried.
- result = subprocess.run(
- [
- "curl",
- "-svk",
- "--connect-timeout",
- "2",
- "--max-time",
- "3",
- tls_flag,
- "--tls-max",
- tls_max,
- "https://127.0.0.1:1",
- ],
- capture_output=True,
- text=True,
- timeout=5,
- )
- output = (result.stdout + result.stderr).lower()
- unsupported_markers = [
- "unsupported protocol",
- "no protocols available",
- "option --tlsv",
- "unknown option",
- "is unknown",
- ]
- if any(marker in output for marker in unsupported_markers):
+
+ def client_probe(port, _tls_flag):
+ try:
+ result = subprocess.run(
+ [
+ "curl",
+ "-svk",
+ "--connect-timeout",
+ "2",
+ "--max-time",
+ "5",
+ "--ciphers",
+ "DEFAULT@SECLEVEL=0",
+ tls_flag,
+ "--tls-max",
+ tls_max,
+ f"https://127.0.0.1:{port}/",
+ ],
+ capture_output=True,
+ text=True,
+ timeout=7,
+ )
+ output = (result.stdout + result.stderr).lower()
+ return result.returncode == 0 and f"ssl connection using tlsv{tls_version}" in output
+ except subprocess.TimeoutExpired:
+ return False
+ except Exception:
return False
- # Any attempt to connect implies curl accepted the TLS setting.
- return True
- except subprocess.TimeoutExpired:
- return False
- except Exception:
- return False
+ return _probe_openssl_server(tls_version, client_probe)
return self.Condition(
check_curl_tls_support, "Curl does not support TLSv{version} in this environment".format(version=tls_version))
diff --git a/tests/gold_tests/autest-site/ports.py b/tests/gold_tests/autest-site/ports.py
index fb36b4088d..cfc56f4a30 100644
--- a/tests/gold_tests/autest-site/ports.py
+++ b/tests/gold_tests/autest-site/ports.py
@@ -16,6 +16,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from contextlib import contextmanager
from typing import Set
import socket
import subprocess
@@ -236,6 +237,50 @@ def _get_port_by_bind():
return port
+def _reserve_port():
+ """
+ Get a port from the global port queue.
+
+ Returns:
+ A tuple containing the port value and whether it should be recycled
+ into the queue when the caller is done with it.
+ """
+ _setup_port_queue()
+ if g_ports.qsize() > 0:
+ try:
+ port = _get_available_port(g_ports)
+ host.WriteVerbose("_reserve_port", f"Using port from port queue: {port}")
+ return port, True
+ except PortQueueSelectionError:
+ port = _get_port_by_bind()
+ host.WriteVerbose("_reserve_port", f"Queue was drained. Using port from a bound socket: {port}")
+ return port, False
+
+ # Since the queue could not be populated, use a port via bind.
+ port = _get_port_by_bind()
+ host.WriteVerbose("_reserve_port", f"Queue is empty. Using port from a bound socket: {port}")
+ return port, False
+
+
+@contextmanager
+def get_port_number():
+ """
+ Reserve a port number from the same allocator used by get_port().
+
+ This is useful for helper code that needs a temporary listening port but
+ does not have an AuTest object with Setup hooks for recycling it. Queue
+ ports are recycled when the context exits.
+
+ :returns: A context manager yielding the reserved port value.
+ """
+ port, recycle_port = _reserve_port()
+ try:
+ yield port
+ finally:
+ if recycle_port:
+ g_ports.put(port)
+
+
def get_port(obj, name):
'''
Get a port and set it to the specified variable on the object.
@@ -247,22 +292,10 @@ def get_port(obj, name):
Returns:
The port value.
'''
- _setup_port_queue()
- port = 0
- if g_ports.qsize() > 0:
- try:
- port = _get_available_port(g_ports)
- host.WriteVerbose("get_port", f"Using port from port queue: {port}")
- # setup clean up step to recycle the port
- obj.Setup.Lambda(
- func_cleanup=lambda: g_ports.put(port), description=f"recycling port: {port}, queue size: {g_ports.qsize()}")
- except PortQueueSelectionError:
- port = _get_port_by_bind()
- host.WriteVerbose("get_port", f"Queue was drained. Using port from a bound socket: {port}")
- else:
- # Since the queue could not be populated, use a port via bind.
- port = _get_port_by_bind()
- host.WriteVerbose("get_port", f"Queue is empty. Using port from a bound socket: {port}")
+ port, recycle_port = _reserve_port()
+ if recycle_port:
+ obj.Setup.Lambda(
+ func_cleanup=lambda: g_ports.put(port), description=f"recycling port: {port}, queue size: {g_ports.qsize()}")
# Assign to the named variable.
obj.Variables[name] = port
diff --git a/tests/gold_tests/tls/tls_check_cert_select_plugin.test.py b/tests/gold_tests/tls/tls_check_cert_select_plugin.test.py
index b4b4d8f587..29c7f6aeac 100644
--- a/tests/gold_tests/tls/tls_check_cert_select_plugin.test.py
+++ b/tests/gold_tests/tls/tls_check_cert_select_plugin.test.py
@@ -164,7 +164,8 @@ tr.MakeCurlCommand(
tr.ReturnCode = 60
tr.StillRunningAfter = server
tr.StillRunningAfter = ts
-tr.Processes.Default.Streams.All = Testers.ContainsExpression("unknown CA", "Failed handshake")
-tr.Processes.Default.Streams.All += Testers.ExcludesExpression("CN=bar.com", "Cert should contain bar.com")
+tr.Processes.Default.Streams.All = Testers.ContainsExpression(r"curl: \(60\) SSL certificate", "Failed certificate verification")
+# Older versions of curl do not print certificate subject details when
+# certificate verification fails.
tr.Processes.Default.Streams.All += Testers.ExcludesExpression("CN=foo.com", "Cert should not contain foo.com")
tr.Processes.Default.Streams.All += Testers.ExcludesExpression("404", "Should make an exchange")