From 51badb8cda767be81ee9ad68fb14ff77f5ecbba4 Mon Sep 17 00:00:00 2001 From: Valentin Platzgummer Date: Fri, 3 Jul 2020 11:18:13 +0200 Subject: [PATCH] Working on ros_bridge, code not working in this state. --- qgroundcontrol.pro | 6 +- .../Simple-WebSocket-Server/.clang-format | 9 + .../Simple-WebSocket-Server/.gitignore | 22 + .../Simple-WebSocket-Server/.gitlab-ci.yml | 36 + .../Simple-WebSocket-Server/CMakeLists.txt | 73 + .../Simple-WebSocket-Server/LICENSE | 21 + .../Simple-WebSocket-Server/README.md | 56 + .../asio_compatibility.hpp | 71 + .../Simple-WebSocket-Server/client_ws.hpp | 757 ++++ .../Simple-WebSocket-Server/client_wss.hpp | 143 + .../Simple-WebSocket-Server/crypto.hpp | 227 ++ .../javascript_client_example.html | 22 + .../Simple-WebSocket-Server/mutex.hpp | 106 + .../Simple-WebSocket-Server/server_ws.hpp | 827 ++++ .../Simple-WebSocket-Server/server_wss.hpp | 79 + .../Simple-WebSocket-Server/status_code.hpp | 176 + .../tests/CMakeLists.txt | 18 + .../Simple-WebSocket-Server/tests/assert.hpp | 9 + .../tests/crypto_test.cpp | 73 + .../Simple-WebSocket-Server/tests/io_test.cpp | 289 ++ .../tests/parse_test.cpp | 153 + .../Simple-WebSocket-Server/utility.hpp | 363 ++ .../Simple-WebSocket-Server/ws_examples.cpp | 145 + .../Simple-WebSocket-Server/wss_examples.cpp | 146 + src/comm/ros_bridge/include/jsongenerator.h | 16 + src/comm/ros_bridge/include/messages.h | 155 + src/comm/ros_bridge/rapidjson/.gitattributes | 22 + src/comm/ros_bridge/rapidjson/.gitignore | 28 + src/comm/ros_bridge/rapidjson/.gitmodules | 3 + src/comm/ros_bridge/rapidjson/.travis.yml | 99 + src/comm/ros_bridge/rapidjson/CHANGELOG.md | 158 + src/comm/ros_bridge/rapidjson/CMakeLists.txt | 221 ++ .../rapidjson/CMakeModules/FindGTestSrc.cmake | 30 + src/comm/ros_bridge/rapidjson/RapidJSON.pc.in | 7 + .../rapidjson/RapidJSONConfig.cmake.in | 15 + .../rapidjson/RapidJSONConfigVersion.cmake.in | 10 + src/comm/ros_bridge/rapidjson/appveyor.yml | 54 + .../ros_bridge/rapidjson/bin/data/abcde.txt | 1 + .../rapidjson/bin/data/glossary.json | 22 + .../ros_bridge/rapidjson/bin/data/menu.json | 27 + .../ros_bridge/rapidjson/bin/data/readme.txt | 1 + .../ros_bridge/rapidjson/bin/data/sample.json | 3315 +++++++++++++++++ .../ros_bridge/rapidjson/bin/data/webapp.json | 88 + .../ros_bridge/rapidjson/bin/data/widget.json | 26 + .../rapidjson/bin/encodings/utf16be.json | Bin 0 -> 368 bytes .../rapidjson/bin/encodings/utf16bebom.json | Bin 0 -> 370 bytes .../rapidjson/bin/encodings/utf16le.json | Bin 0 -> 368 bytes .../rapidjson/bin/encodings/utf16lebom.json | Bin 0 -> 370 bytes .../rapidjson/bin/encodings/utf32be.json | Bin 0 -> 736 bytes .../rapidjson/bin/encodings/utf32bebom.json | Bin 0 -> 740 bytes .../rapidjson/bin/encodings/utf32le.json | Bin 0 -> 736 bytes .../rapidjson/bin/encodings/utf32lebom.json | Bin 0 -> 740 bytes .../rapidjson/bin/encodings/utf8.json | 7 + .../rapidjson/bin/encodings/utf8bom.json | 7 + .../rapidjson/bin/jsonchecker/fail1.json | 1 + .../rapidjson/bin/jsonchecker/fail10.json | 1 + .../rapidjson/bin/jsonchecker/fail11.json | 1 + .../rapidjson/bin/jsonchecker/fail12.json | 1 + .../rapidjson/bin/jsonchecker/fail13.json | 1 + .../rapidjson/bin/jsonchecker/fail14.json | 1 + .../rapidjson/bin/jsonchecker/fail15.json | 1 + .../rapidjson/bin/jsonchecker/fail16.json | 1 + .../rapidjson/bin/jsonchecker/fail17.json | 1 + .../rapidjson/bin/jsonchecker/fail18.json | 1 + .../rapidjson/bin/jsonchecker/fail19.json | 1 + .../rapidjson/bin/jsonchecker/fail2.json | 1 + .../rapidjson/bin/jsonchecker/fail20.json | 1 + .../rapidjson/bin/jsonchecker/fail21.json | 1 + .../rapidjson/bin/jsonchecker/fail22.json | 1 + .../rapidjson/bin/jsonchecker/fail23.json | 1 + .../rapidjson/bin/jsonchecker/fail24.json | 1 + .../rapidjson/bin/jsonchecker/fail25.json | 1 + .../rapidjson/bin/jsonchecker/fail26.json | 1 + .../rapidjson/bin/jsonchecker/fail27.json | 2 + .../rapidjson/bin/jsonchecker/fail28.json | 2 + .../rapidjson/bin/jsonchecker/fail29.json | 1 + .../rapidjson/bin/jsonchecker/fail3.json | 1 + .../rapidjson/bin/jsonchecker/fail30.json | 1 + .../rapidjson/bin/jsonchecker/fail31.json | 1 + .../rapidjson/bin/jsonchecker/fail32.json | 1 + .../rapidjson/bin/jsonchecker/fail33.json | 1 + .../rapidjson/bin/jsonchecker/fail4.json | 1 + .../rapidjson/bin/jsonchecker/fail5.json | 1 + .../rapidjson/bin/jsonchecker/fail6.json | 1 + .../rapidjson/bin/jsonchecker/fail7.json | 1 + .../rapidjson/bin/jsonchecker/fail8.json | 1 + .../rapidjson/bin/jsonchecker/fail9.json | 1 + .../rapidjson/bin/jsonchecker/pass1.json | 58 + .../rapidjson/bin/jsonchecker/pass2.json | 1 + .../rapidjson/bin/jsonchecker/pass3.json | 6 + .../rapidjson/bin/jsonchecker/readme.txt | 3 + .../rapidjson/bin/types/booleans.json | 102 + .../rapidjson/bin/types/floats.json | 102 + .../ros_bridge/rapidjson/bin/types/guids.json | 102 + .../rapidjson/bin/types/integers.json | 102 + .../ros_bridge/rapidjson/bin/types/mixed.json | 592 +++ .../ros_bridge/rapidjson/bin/types/nulls.json | 102 + .../rapidjson/bin/types/paragraphs.json | 102 + .../ros_bridge/rapidjson/bin/types/readme.txt | 1 + .../rapidjson/contrib/natvis/LICENSE | 45 + .../rapidjson/contrib/natvis/README.md | 7 + .../rapidjson/contrib/natvis/rapidjson.natvis | 38 + .../ros_bridge/rapidjson/doc/CMakeLists.txt | 27 + src/comm/ros_bridge/rapidjson/doc/Doxyfile.in | 2369 ++++++++++++ .../rapidjson/doc/Doxyfile.zh-cn.in | 2369 ++++++++++++ .../rapidjson/doc/diagram/architecture.dot | 50 + .../rapidjson/doc/diagram/architecture.png | Bin 0 -> 16569 bytes .../rapidjson/doc/diagram/insituparsing.dot | 65 + .../rapidjson/doc/diagram/insituparsing.png | Bin 0 -> 37281 bytes .../iterative-parser-states-diagram.dot | 62 + .../iterative-parser-states-diagram.png | Bin 0 -> 92378 bytes .../ros_bridge/rapidjson/doc/diagram/makefile | 8 + .../rapidjson/doc/diagram/move1.dot | 47 + .../rapidjson/doc/diagram/move1.png | Bin 0 -> 16081 bytes .../rapidjson/doc/diagram/move2.dot | 62 + .../rapidjson/doc/diagram/move2.png | Bin 0 -> 41517 bytes .../rapidjson/doc/diagram/move3.dot | 60 + .../rapidjson/doc/diagram/move3.png | Bin 0 -> 36371 bytes .../rapidjson/doc/diagram/normalparsing.dot | 56 + .../rapidjson/doc/diagram/normalparsing.png | Bin 0 -> 32887 bytes .../rapidjson/doc/diagram/simpledom.dot | 54 + .../rapidjson/doc/diagram/simpledom.png | Bin 0 -> 43670 bytes .../rapidjson/doc/diagram/tutorial.dot | 58 + .../rapidjson/doc/diagram/tutorial.png | Bin 0 -> 44634 bytes .../rapidjson/doc/diagram/utilityclass.dot | 73 + .../rapidjson/doc/diagram/utilityclass.png | Bin 0 -> 99993 bytes src/comm/ros_bridge/rapidjson/doc/dom.md | 280 ++ .../ros_bridge/rapidjson/doc/dom.zh-cn.md | 284 ++ src/comm/ros_bridge/rapidjson/doc/encoding.md | 146 + .../rapidjson/doc/encoding.zh-cn.md | 152 + src/comm/ros_bridge/rapidjson/doc/faq.md | 289 ++ .../ros_bridge/rapidjson/doc/faq.zh-cn.md | 290 ++ src/comm/ros_bridge/rapidjson/doc/features.md | 104 + .../rapidjson/doc/features.zh-cn.md | 103 + .../ros_bridge/rapidjson/doc/internals.md | 368 ++ .../rapidjson/doc/internals.zh-cn.md | 363 ++ .../rapidjson/doc/logo/rapidjson.png | Bin 0 -> 5259 bytes .../rapidjson/doc/logo/rapidjson.svg | 119 + .../rapidjson/doc/misc/DoxygenLayout.xml | 194 + .../rapidjson/doc/misc/doxygenextra.css | 274 ++ .../ros_bridge/rapidjson/doc/misc/footer.html | 11 + .../ros_bridge/rapidjson/doc/misc/header.html | 24 + src/comm/ros_bridge/rapidjson/doc/npm.md | 31 + .../ros_bridge/rapidjson/doc/performance.md | 26 + .../rapidjson/doc/performance.zh-cn.md | 26 + src/comm/ros_bridge/rapidjson/doc/pointer.md | 234 ++ .../ros_bridge/rapidjson/doc/pointer.zh-cn.md | 234 ++ src/comm/ros_bridge/rapidjson/doc/sax.md | 509 +++ .../ros_bridge/rapidjson/doc/sax.zh-cn.md | 487 +++ src/comm/ros_bridge/rapidjson/doc/schema.md | 505 +++ .../ros_bridge/rapidjson/doc/schema.zh-cn.md | 237 ++ src/comm/ros_bridge/rapidjson/doc/stream.md | 429 +++ .../ros_bridge/rapidjson/doc/stream.zh-cn.md | 429 +++ src/comm/ros_bridge/rapidjson/doc/tutorial.md | 536 +++ .../rapidjson/doc/tutorial.zh-cn.md | 535 +++ .../rapidjson/docker/debian/Dockerfile | 8 + .../rapidjson/example/CMakeLists.txt | 46 + .../rapidjson/example/archiver/archiver.cpp | 292 ++ .../rapidjson/example/archiver/archiver.h | 145 + .../example/archiver/archivertest.cpp | 287 ++ .../example/capitalize/capitalize.cpp | 67 + .../rapidjson/example/condense/condense.cpp | 32 + .../rapidjson/example/filterkey/filterkey.cpp | 135 + .../example/filterkeydom/filterkeydom.cpp | 170 + .../rapidjson/example/jsonx/jsonx.cpp | 207 + .../lookaheadparser/lookaheadparser.cpp | 350 ++ .../example/messagereader/messagereader.cpp | 105 + .../example/parsebyparts/parsebyparts.cpp | 176 + .../rapidjson/example/pretty/pretty.cpp | 30 + .../example/prettyauto/prettyauto.cpp | 56 + .../schemavalidator/schemavalidator.cpp | 78 + .../rapidjson/example/serialize/serialize.cpp | 173 + .../rapidjson/example/simpledom/simpledom.cpp | 29 + .../simplepullreader/simplepullreader.cpp | 53 + .../example/simplereader/simplereader.cpp | 42 + .../example/simplewriter/simplewriter.cpp | 36 + .../rapidjson/example/sortkeys/sortkeys.cpp | 62 + .../rapidjson/example/tutorial/tutorial.cpp | 151 + .../rapidjson/include/rapidjson/allocators.h | 284 ++ .../include/rapidjson/cursorstreamwrapper.h | 78 + .../rapidjson/include/rapidjson/document.h | 2652 +++++++++++++ .../include/rapidjson/encodedstream.h | 299 ++ .../rapidjson/include/rapidjson/encodings.h | 716 ++++ .../rapidjson/include/rapidjson/error/en.h | 74 + .../rapidjson/include/rapidjson/error/error.h | 161 + .../include/rapidjson/filereadstream.h | 99 + .../include/rapidjson/filewritestream.h | 104 + .../rapidjson/include/rapidjson/fwd.h | 151 + .../include/rapidjson/internal/biginteger.h | 290 ++ .../include/rapidjson/internal/diyfp.h | 271 ++ .../include/rapidjson/internal/dtoa.h | 245 ++ .../include/rapidjson/internal/ieee754.h | 78 + .../include/rapidjson/internal/itoa.h | 308 ++ .../include/rapidjson/internal/meta.h | 186 + .../include/rapidjson/internal/pow10.h | 55 + .../include/rapidjson/internal/regex.h | 740 ++++ .../include/rapidjson/internal/stack.h | 232 ++ .../include/rapidjson/internal/strfunc.h | 69 + .../include/rapidjson/internal/strtod.h | 290 ++ .../include/rapidjson/internal/swap.h | 46 + .../include/rapidjson/istreamwrapper.h | 128 + .../include/rapidjson/memorybuffer.h | 70 + .../include/rapidjson/memorystream.h | 71 + .../include/rapidjson/msinttypes/inttypes.h | 316 ++ .../include/rapidjson/msinttypes/stdint.h | 300 ++ .../include/rapidjson/ostreamwrapper.h | 81 + .../rapidjson/include/rapidjson/pointer.h | 1414 +++++++ .../include/rapidjson/prettywriter.h | 277 ++ .../rapidjson/include/rapidjson/rapidjson.h | 656 ++++ .../rapidjson/include/rapidjson/reader.h | 2230 +++++++++++ .../rapidjson/include/rapidjson/schema.h | 2497 +++++++++++++ .../rapidjson/include/rapidjson/stream.h | 223 ++ .../include/rapidjson/stringbuffer.h | 121 + .../rapidjson/include/rapidjson/writer.h | 709 ++++ src/comm/ros_bridge/rapidjson/include_dirs.js | 2 + src/comm/ros_bridge/rapidjson/library.json | 15 + src/comm/ros_bridge/rapidjson/license.txt | 57 + src/comm/ros_bridge/rapidjson/package.json | 24 + .../ros_bridge/rapidjson/rapidjson.autopkg | 77 + src/comm/ros_bridge/rapidjson/readme.md | 160 + src/comm/ros_bridge/rapidjson/readme.zh-cn.md | 152 + .../ros_bridge/rapidjson/test/CMakeLists.txt | 20 + .../rapidjson/test/perftest/CMakeLists.txt | 28 + .../rapidjson/test/perftest/misctest.cpp | 974 +++++ .../rapidjson/test/perftest/perftest.cpp | 24 + .../rapidjson/test/perftest/perftest.h | 185 + .../rapidjson/test/perftest/platformtest.cpp | 166 + .../rapidjson/test/perftest/rapidjsontest.cpp | 546 +++ .../rapidjson/test/perftest/schematest.cpp | 223 ++ .../rapidjson/test/unittest/CMakeLists.txt | 92 + .../test/unittest/allocatorstest.cpp | 100 + .../test/unittest/bigintegertest.cpp | 138 + .../test/unittest/cursorstreamwrappertest.cpp | 115 + .../rapidjson/test/unittest/documenttest.cpp | 672 ++++ .../rapidjson/test/unittest/dtoatest.cpp | 98 + .../test/unittest/encodedstreamtest.cpp | 313 ++ .../rapidjson/test/unittest/encodingstest.cpp | 451 +++ .../test/unittest/filestreamtest.cpp | 155 + .../rapidjson/test/unittest/fwdtest.cpp | 230 ++ .../test/unittest/istreamwrappertest.cpp | 181 + .../rapidjson/test/unittest/itoatest.cpp | 160 + .../test/unittest/jsoncheckertest.cpp | 143 + .../rapidjson/test/unittest/namespacetest.cpp | 70 + .../test/unittest/ostreamwrappertest.cpp | 92 + .../rapidjson/test/unittest/pointertest.cpp | 1635 ++++++++ .../test/unittest/prettywritertest.cpp | 373 ++ .../rapidjson/test/unittest/readertest.cpp | 2201 +++++++++++ .../rapidjson/test/unittest/regextest.cpp | 639 ++++ .../rapidjson/test/unittest/schematest.cpp | 2072 +++++++++++ .../rapidjson/test/unittest/simdtest.cpp | 219 ++ .../rapidjson/test/unittest/strfunctest.cpp | 30 + .../test/unittest/stringbuffertest.cpp | 192 + .../rapidjson/test/unittest/strtodtest.cpp | 132 + .../rapidjson/test/unittest/unittest.cpp | 51 + .../rapidjson/test/unittest/unittest.h | 140 + .../rapidjson/test/unittest/valuetest.cpp | 1851 +++++++++ .../rapidjson/test/unittest/writertest.cpp | 598 +++ .../ros_bridge/rapidjson/test/valgrind.supp | 17 + .../ros_bridge/rapidjson/travis-doxygen.sh | 121 + .../src/JsonProcessor/jsonprocessor.cpp | 6 - .../src/JsonProcessor/jsonprocessor.h | 11 - src/comm/ros_bridge/src/messages.cpp | 143 + 262 files changed, 57443 insertions(+), 18 deletions(-) create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/.clang-format create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/.gitignore create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/.gitlab-ci.yml create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/CMakeLists.txt create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/LICENSE create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/README.md create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/asio_compatibility.hpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/client_ws.hpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/client_wss.hpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/crypto.hpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/javascript_client_example.html create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/mutex.hpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/server_ws.hpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/server_wss.hpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/status_code.hpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/tests/CMakeLists.txt create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/tests/assert.hpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/tests/crypto_test.cpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/tests/io_test.cpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/tests/parse_test.cpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/utility.hpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/ws_examples.cpp create mode 100644 src/comm/ros_bridge/Simple-WebSocket-Server/wss_examples.cpp create mode 100644 src/comm/ros_bridge/include/jsongenerator.h create mode 100644 src/comm/ros_bridge/include/messages.h create mode 100644 src/comm/ros_bridge/rapidjson/.gitattributes create mode 100644 src/comm/ros_bridge/rapidjson/.gitignore create mode 100644 src/comm/ros_bridge/rapidjson/.gitmodules create mode 100644 src/comm/ros_bridge/rapidjson/.travis.yml create mode 100644 src/comm/ros_bridge/rapidjson/CHANGELOG.md create mode 100644 src/comm/ros_bridge/rapidjson/CMakeLists.txt create mode 100644 src/comm/ros_bridge/rapidjson/CMakeModules/FindGTestSrc.cmake create mode 100644 src/comm/ros_bridge/rapidjson/RapidJSON.pc.in create mode 100644 src/comm/ros_bridge/rapidjson/RapidJSONConfig.cmake.in create mode 100644 src/comm/ros_bridge/rapidjson/RapidJSONConfigVersion.cmake.in create mode 100644 src/comm/ros_bridge/rapidjson/appveyor.yml create mode 100644 src/comm/ros_bridge/rapidjson/bin/data/abcde.txt create mode 100644 src/comm/ros_bridge/rapidjson/bin/data/glossary.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/data/menu.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/data/readme.txt create mode 100644 src/comm/ros_bridge/rapidjson/bin/data/sample.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/data/webapp.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/data/widget.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/encodings/utf16be.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/encodings/utf16bebom.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/encodings/utf16le.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/encodings/utf16lebom.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/encodings/utf32be.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/encodings/utf32bebom.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/encodings/utf32le.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/encodings/utf32lebom.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/encodings/utf8.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/encodings/utf8bom.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail1.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail10.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail11.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail12.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail13.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail14.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail15.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail16.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail17.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail18.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail19.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail2.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail20.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail21.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail22.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail23.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail24.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail25.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail26.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail27.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail28.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail29.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail3.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail30.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail31.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail32.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail33.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail4.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail5.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail6.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail7.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail8.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail9.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/pass1.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/pass2.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/pass3.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/jsonchecker/readme.txt create mode 100644 src/comm/ros_bridge/rapidjson/bin/types/booleans.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/types/floats.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/types/guids.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/types/integers.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/types/mixed.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/types/nulls.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/types/paragraphs.json create mode 100644 src/comm/ros_bridge/rapidjson/bin/types/readme.txt create mode 100644 src/comm/ros_bridge/rapidjson/contrib/natvis/LICENSE create mode 100644 src/comm/ros_bridge/rapidjson/contrib/natvis/README.md create mode 100644 src/comm/ros_bridge/rapidjson/contrib/natvis/rapidjson.natvis create mode 100644 src/comm/ros_bridge/rapidjson/doc/CMakeLists.txt create mode 100644 src/comm/ros_bridge/rapidjson/doc/Doxyfile.in create mode 100644 src/comm/ros_bridge/rapidjson/doc/Doxyfile.zh-cn.in create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/architecture.dot create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/architecture.png create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/insituparsing.dot create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/insituparsing.png create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/iterative-parser-states-diagram.dot create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/iterative-parser-states-diagram.png create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/makefile create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/move1.dot create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/move1.png create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/move2.dot create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/move2.png create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/move3.dot create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/move3.png create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/normalparsing.dot create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/normalparsing.png create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/simpledom.dot create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/simpledom.png create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/tutorial.dot create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/tutorial.png create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/utilityclass.dot create mode 100644 src/comm/ros_bridge/rapidjson/doc/diagram/utilityclass.png create mode 100644 src/comm/ros_bridge/rapidjson/doc/dom.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/dom.zh-cn.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/encoding.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/encoding.zh-cn.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/faq.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/faq.zh-cn.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/features.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/features.zh-cn.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/internals.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/internals.zh-cn.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/logo/rapidjson.png create mode 100644 src/comm/ros_bridge/rapidjson/doc/logo/rapidjson.svg create mode 100644 src/comm/ros_bridge/rapidjson/doc/misc/DoxygenLayout.xml create mode 100644 src/comm/ros_bridge/rapidjson/doc/misc/doxygenextra.css create mode 100644 src/comm/ros_bridge/rapidjson/doc/misc/footer.html create mode 100644 src/comm/ros_bridge/rapidjson/doc/misc/header.html create mode 100644 src/comm/ros_bridge/rapidjson/doc/npm.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/performance.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/performance.zh-cn.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/pointer.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/pointer.zh-cn.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/sax.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/sax.zh-cn.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/schema.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/schema.zh-cn.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/stream.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/stream.zh-cn.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/tutorial.md create mode 100644 src/comm/ros_bridge/rapidjson/doc/tutorial.zh-cn.md create mode 100644 src/comm/ros_bridge/rapidjson/docker/debian/Dockerfile create mode 100644 src/comm/ros_bridge/rapidjson/example/CMakeLists.txt create mode 100644 src/comm/ros_bridge/rapidjson/example/archiver/archiver.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/archiver/archiver.h create mode 100644 src/comm/ros_bridge/rapidjson/example/archiver/archivertest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/capitalize/capitalize.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/condense/condense.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/filterkey/filterkey.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/filterkeydom/filterkeydom.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/jsonx/jsonx.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/lookaheadparser/lookaheadparser.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/messagereader/messagereader.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/parsebyparts/parsebyparts.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/pretty/pretty.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/prettyauto/prettyauto.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/schemavalidator/schemavalidator.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/serialize/serialize.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/simpledom/simpledom.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/simplepullreader/simplepullreader.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/simplereader/simplereader.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/simplewriter/simplewriter.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/sortkeys/sortkeys.cpp create mode 100644 src/comm/ros_bridge/rapidjson/example/tutorial/tutorial.cpp create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/allocators.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/cursorstreamwrapper.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/document.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/encodedstream.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/encodings.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/error/en.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/error/error.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/filereadstream.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/filewritestream.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/fwd.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/internal/biginteger.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/internal/diyfp.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/internal/dtoa.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/internal/ieee754.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/internal/itoa.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/internal/meta.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/internal/pow10.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/internal/regex.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/internal/stack.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/internal/strfunc.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/internal/strtod.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/internal/swap.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/istreamwrapper.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/memorybuffer.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/memorystream.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/msinttypes/inttypes.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/msinttypes/stdint.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/ostreamwrapper.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/pointer.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/prettywriter.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/rapidjson.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/reader.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/schema.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/stream.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/stringbuffer.h create mode 100644 src/comm/ros_bridge/rapidjson/include/rapidjson/writer.h create mode 100644 src/comm/ros_bridge/rapidjson/include_dirs.js create mode 100644 src/comm/ros_bridge/rapidjson/library.json create mode 100644 src/comm/ros_bridge/rapidjson/license.txt create mode 100644 src/comm/ros_bridge/rapidjson/package.json create mode 100644 src/comm/ros_bridge/rapidjson/rapidjson.autopkg create mode 100644 src/comm/ros_bridge/rapidjson/readme.md create mode 100644 src/comm/ros_bridge/rapidjson/readme.zh-cn.md create mode 100644 src/comm/ros_bridge/rapidjson/test/CMakeLists.txt create mode 100644 src/comm/ros_bridge/rapidjson/test/perftest/CMakeLists.txt create mode 100644 src/comm/ros_bridge/rapidjson/test/perftest/misctest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/perftest/perftest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/perftest/perftest.h create mode 100644 src/comm/ros_bridge/rapidjson/test/perftest/platformtest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/perftest/rapidjsontest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/perftest/schematest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/CMakeLists.txt create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/allocatorstest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/bigintegertest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/cursorstreamwrappertest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/documenttest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/dtoatest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/encodedstreamtest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/encodingstest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/filestreamtest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/fwdtest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/istreamwrappertest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/itoatest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/jsoncheckertest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/namespacetest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/ostreamwrappertest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/pointertest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/prettywritertest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/readertest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/regextest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/schematest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/simdtest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/strfunctest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/stringbuffertest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/strtodtest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/unittest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/unittest.h create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/valuetest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/unittest/writertest.cpp create mode 100644 src/comm/ros_bridge/rapidjson/test/valgrind.supp create mode 100755 src/comm/ros_bridge/rapidjson/travis-doxygen.sh delete mode 100644 src/comm/ros_bridge/src/JsonProcessor/jsonprocessor.cpp delete mode 100644 src/comm/ros_bridge/src/JsonProcessor/jsonprocessor.h create mode 100644 src/comm/ros_bridge/src/messages.cpp diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 5088e2384..c2976b64f 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -367,6 +367,7 @@ INCLUDEPATH += \ src/ViewWidgets \ src/Audio \ src/comm \ + src/comm/ros_bridge \ src/input \ src/lib/qmapcontrol \ src/uas \ @@ -463,6 +464,8 @@ HEADERS += \ src/Wima/testplanimetrycalculus.h \ src/Settings/WimaSettings.h \ src/QmlControls/QmlObjectVectorModel.h \ + src/comm/ros_bridge/include/jsongenerator.h \ + src/comm/ros_bridge/include/messages.h \ src/comm/utilities.h SOURCES += \ src/Snake/clipper/clipper.cpp \ @@ -500,7 +503,8 @@ SOURCES += \ src/Wima/TestPolygonCalculus.cpp \ src/Wima/testplanimetrycalculus.cpp \ src/Settings/WimaSettings.cc \ - src/QmlControls/QmlObjectVectorModel.cc + src/QmlControls/QmlObjectVectorModel.cc \ + src/comm/ros_bridge/src/messages.cpp # # Unit Test specific configuration goes here (requires full debug build with all plugins) diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/.clang-format b/src/comm/ros_bridge/Simple-WebSocket-Server/.clang-format new file mode 100644 index 000000000..50f942330 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/.clang-format @@ -0,0 +1,9 @@ +IndentWidth: 2 +AccessModifierOffset: -2 +UseTab: Never +ColumnLimit: 0 +MaxEmptyLinesToKeep: 2 +SpaceBeforeParens: Never +BreakBeforeBraces: Custom +BraceWrapping: {BeforeElse: true, BeforeCatch: true} +NamespaceIndentation: All diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/.gitignore b/src/comm/ros_bridge/Simple-WebSocket-Server/.gitignore new file mode 100644 index 000000000..75fe02790 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/.gitignore @@ -0,0 +1,22 @@ +# https://github.com/github/gitignore/blob/master/CMake.gitignore +CMakeCache.txt +CMakeFiles +CMakeScripts +Makefile +cmake_install.cmake +install_manifest.txt +*.cmake +#Additions to https://github.com/github/gitignore/blob/master/CMake.gitignore +Testing +compile_commands.json +.usages_clang + +*.crt +*.key + +# executables +ws_examples +wss_examples +crypto_test +io_test +parse_test diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/.gitlab-ci.yml b/src/comm/ros_bridge/Simple-WebSocket-Server/.gitlab-ci.yml new file mode 100644 index 000000000..e9e8b82bd --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/.gitlab-ci.yml @@ -0,0 +1,36 @@ +before_script: + - mkdir build && cd build + - export CXXFLAGS=-Werror + - export CTEST_OUTPUT_ON_FAILURE=1 + +.script: &compile_and_test + script: + - cmake -DCMAKE_BUILD_TYPE=Release .. && make && make test + - rm -r * + - cmake -DCMAKE_BUILD_TYPE=Release -DUSE_STANDALONE_ASIO=ON .. && make && make test + +arch: + image: "registry.gitlab.com/eidheim/docker-images:arch" + <<: *compile_and_test + +buster: + image: "registry.gitlab.com/eidheim/docker-images:buster" + <<: *compile_and_test + +jessie: + image: "registry.gitlab.com/eidheim/docker-images:jessie" + <<: *compile_and_test + +stretch: + image: "registry.gitlab.com/eidheim/docker-images:stretch" + <<: *compile_and_test + +thread-safety-analysis: + image: "registry.gitlab.com/eidheim/docker-images:arch" + script: + - CXX=clang++ cmake .. && make + +static-analysis: + image: "registry.gitlab.com/eidheim/docker-images:arch" + script: + - scan-build cmake .. && scan-build --status-bugs make diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/CMakeLists.txt b/src/comm/ros_bridge/Simple-WebSocket-Server/CMakeLists.txt new file mode 100644 index 000000000..b87af3db2 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/CMakeLists.txt @@ -0,0 +1,73 @@ +cmake_minimum_required (VERSION 3.0) + +project (Simple-WebSocket-Server) + +option(USE_STANDALONE_ASIO "set ON to use standalone Asio instead of Boost.Asio" OFF) +option(BUILD_TESTING "set ON to build library tests" OFF) + +if(NOT MSVC) + add_compile_options(-std=c++11 -Wall -Wextra -Wsign-conversion) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wthread-safety) + endif() +else() + add_compile_options(/W1) +endif() + +add_library(simple-websocket-server INTERFACE) + +target_include_directories(simple-websocket-server INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) + +find_package(Threads REQUIRED) +target_link_libraries(simple-websocket-server INTERFACE ${CMAKE_THREAD_LIBS_INIT}) + +# TODO 2020 when Debian Jessie LTS ends: +# Remove Boost system, thread, regex components; use Boost:: aliases; remove Boost target_include_directories +if(USE_STANDALONE_ASIO) + target_compile_definitions(simple-websocket-server INTERFACE USE_STANDALONE_ASIO) + find_path(ASIO_PATH asio.hpp) + if(NOT ASIO_PATH) + message(FATAL_ERROR "Standalone Asio not found") + else() + target_include_directories(simple-websocket-server INTERFACE ${ASIO_PATH}) + endif() +else() + find_package(Boost 1.54.0 COMPONENTS system thread coroutine context REQUIRED) + target_link_libraries(simple-websocket-server INTERFACE ${Boost_LIBRARIES}) + target_include_directories(simple-websocket-server INTERFACE ${Boost_INCLUDE_DIR}) + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) + target_compile_definitions(simple-websocket-server INTERFACE USE_BOOST_REGEX) + find_package(Boost 1.54.0 COMPONENTS regex REQUIRED) + target_link_libraries(simple-websocket-server INTERFACE ${Boost_LIBRARIES}) + target_include_directories(simple-websocket-server INTERFACE ${Boost_INCLUDE_DIR}) + endif() +endif() +if(WIN32) + target_link_libraries(simple-websocket-server INTERFACE ws2_32 wsock32) +endif() + +if(APPLE) + set(OPENSSL_ROOT_DIR "/usr/local/opt/openssl") +endif() +find_package(OpenSSL REQUIRED) +target_link_libraries(simple-websocket-server INTERFACE ${OPENSSL_LIBRARIES}) +target_include_directories(simple-websocket-server INTERFACE ${OPENSSL_INCLUDE_DIR}) + +# If Simple-WebSocket-Server is not a sub-project: +if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") + add_executable(ws_examples ws_examples.cpp) + target_link_libraries(ws_examples simple-websocket-server) + if(OPENSSL_FOUND) + add_executable(wss_examples wss_examples.cpp) + target_link_libraries(wss_examples simple-websocket-server) + endif() + + set(BUILD_TESTING ON) + + install(FILES asio_compatibility.hpp server_ws.hpp client_ws.hpp server_wss.hpp client_wss.hpp crypto.hpp utility.hpp status_code.hpp mutex.hpp DESTINATION include/simple-websocket-server) +endif() + +if(BUILD_TESTING) + enable_testing() + add_subdirectory(tests) +endif() diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/LICENSE b/src/comm/ros_bridge/Simple-WebSocket-Server/LICENSE new file mode 100644 index 000000000..3a9d48db7 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2019 Ole Christian Eidheim + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/README.md b/src/comm/ros_bridge/Simple-WebSocket-Server/README.md new file mode 100644 index 000000000..729156391 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/README.md @@ -0,0 +1,56 @@ +Simple-WebSocket-Server +================= + +A very simple, fast, multithreaded, platform independent WebSocket (WS) and WebSocket Secure (WSS) server and client library implemented using C++11, Asio (both Boost.Asio and standalone Asio can be used) and OpenSSL. Created to be an easy way to make WebSocket endpoints in C++. + +See https://gitlab.com/eidheim/Simple-Web-Server for an easy way to make REST resources available from C++ applications. Also, feel free to check out the new C++ IDE supporting C++11/14/17: https://gitlab.com/cppit/jucipp. + +### Features + +* RFC 6455 mostly supported: text/binary frames, fragmented messages, ping-pong, connection close with status and reason. +* Asynchronous message handling +* Thread pool if needed +* Platform independent +* WebSocket Secure support +* Timeouts, if any of SocketServer::timeout_request and SocketServer::timeout_idle are >0 (default: SocketServer::timeout_request=5 seconds, and SocketServer::timeout_idle=0 seconds; no timeout on idle connections) +* Simple way to add WebSocket endpoints using regex for path, and anonymous functions +* An easy to use WebSocket and WebSocket Secure client library +* C++ bindings to the following OpenSSL methods: Base64, MD5, SHA1, SHA256 and SHA512 (found in crypto.hpp) + +### Usage + +See [ws_examples.cpp](ws_examples.cpp) or [wss_examples.cpp](wss_examples.cpp) for example usage. + +### Dependencies + +* Boost.Asio or standalone Asio +* OpenSSL libraries + +### Compile + +Compile with a C++11 supported compiler: + +```sh +mkdir build +cd build +cmake .. +make +cd .. +``` + +#### Run server and client examples + +### WS + +```sh +./build/ws_examples +``` + +### WSS + +Before running the WSS-examples, an RSA private key (server.key) and an SSL certificate (server.crt) must be created. + +Then: +``` +./build/wss_examples +``` diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/asio_compatibility.hpp b/src/comm/ros_bridge/Simple-WebSocket-Server/asio_compatibility.hpp new file mode 100644 index 000000000..2a29e5cef --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/asio_compatibility.hpp @@ -0,0 +1,71 @@ +#ifndef SIMPLE_WEB_ASIO_COMPATIBILITY_HPP +#define SIMPLE_WEB_ASIO_COMPATIBILITY_HPP + +#include + +#ifdef USE_STANDALONE_ASIO +#include +#include +namespace SimpleWeb { + namespace error = asio::error; + using error_code = std::error_code; + using errc = std::errc; + using system_error = std::system_error; + namespace make_error_code = std; +} // namespace SimpleWeb +#else +#include +#include +namespace SimpleWeb { + namespace asio = boost::asio; + namespace error = asio::error; + using error_code = boost::system::error_code; + namespace errc = boost::system::errc; + using system_error = boost::system::system_error; + namespace make_error_code = boost::system::errc; +} // namespace SimpleWeb +#endif + +namespace SimpleWeb { +#if(USE_STANDALONE_ASIO && ASIO_VERSION >= 101300) || BOOST_ASIO_VERSION >= 101300 + using io_context = asio::io_context; + using resolver_results = asio::ip::tcp::resolver::results_type; + using async_connect_endpoint = asio::ip::tcp::endpoint; + + inline void restart(io_context &context) noexcept { + context.restart(); + } + inline asio::ip::address make_address(const std::string &str) noexcept { + return asio::ip::make_address(str); + } + template + asio::executor get_socket_executor(socket_type &socket) { + return socket.get_executor(); + } + template + void async_resolve(asio::ip::tcp::resolver &resolver, const std::pair &host_port, handler_type &&handler) { + resolver.async_resolve(host_port.first, host_port.second, std::forward(handler)); + } +#else + using io_context = asio::io_service; + using resolver_results = asio::ip::tcp::resolver::iterator; + using async_connect_endpoint = asio::ip::tcp::resolver::iterator; + + inline void restart(io_context &context) noexcept { + context.reset(); + } + inline asio::ip::address make_address(const std::string &str) noexcept { + return asio::ip::address::from_string(str); + } + template + io_context &get_socket_executor(socket_type &socket) { + return socket.get_io_service(); + } + template + void async_resolve(asio::ip::tcp::resolver &resolver, const std::pair &host_port, handler_type &&handler) { + resolver.async_resolve(asio::ip::tcp::resolver::query(host_port.first, host_port.second), std::forward(handler)); + } +#endif +} // namespace SimpleWeb + +#endif /* SIMPLE_WEB_ASIO_COMPATIBILITY_HPP */ diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/client_ws.hpp b/src/comm/ros_bridge/Simple-WebSocket-Server/client_ws.hpp new file mode 100644 index 000000000..6457a8734 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/client_ws.hpp @@ -0,0 +1,757 @@ +#ifndef SIMPLE_WEB_CLIENT_WS_HPP +#define SIMPLE_WEB_CLIENT_WS_HPP + +#include "asio_compatibility.hpp" +#include "crypto.hpp" +#include "mutex.hpp" +#include "utility.hpp" +#include +#include +#include +#include +#include +#include + +namespace SimpleWeb { + template + class SocketClient; + + template + class SocketClientBase { + public: + class InMessage : public std::istream { + friend class SocketClientBase; + friend class SocketClient; + friend class Connection; + + public: + unsigned char fin_rsv_opcode; + std::size_t size() noexcept { + return length; + } + + /// Convenience function to return std::string. The stream buffer is consumed. + std::string string() noexcept { + try { + std::string str; + auto size = streambuf.size(); + str.resize(size); + read(&str[0], static_cast(size)); + return str; + } + catch(...) { + return std::string(); + } + } + + private: + InMessage() noexcept : std::istream(&streambuf), length(0) {} + InMessage(unsigned char fin_rsv_opcode, std::size_t length) noexcept : std::istream(&streambuf), fin_rsv_opcode(fin_rsv_opcode), length(length) {} + std::size_t length; + asio::streambuf streambuf; + }; + + /// The buffer is consumed during send operations. + class OutMessage : public std::iostream { + friend class SocketClientBase; + + asio::streambuf streambuf; + + public: + OutMessage() noexcept : std::iostream(&streambuf) {} + OutMessage(std::size_t capacity) noexcept : std::iostream(&streambuf) { + streambuf.prepare(capacity); + } + + /// Returns the size of the buffer + std::size_t size() const noexcept { + return streambuf.size(); + } + }; + + class Connection : public std::enable_shared_from_this { + friend class SocketClientBase; + friend class SocketClient; + + public: + std::string http_version, status_code; + CaseInsensitiveMultimap header; + + asio::ip::tcp::endpoint remote_endpoint; + + std::string remote_endpoint_address() noexcept { + try { + return remote_endpoint.address().to_string(); + } + catch(...) { + return std::string(); + } + } + + unsigned short remote_endpoint_port() noexcept { + return remote_endpoint.port(); + } + + private: + template + Connection(std::shared_ptr handler_runner_, long timeout_idle, Args &&... args) noexcept + : handler_runner(std::move(handler_runner_)), socket(new socket_type(std::forward(args)...)), timeout_idle(timeout_idle), closed(false) {} + + std::shared_ptr handler_runner; + + std::unique_ptr socket; // Socket must be unique_ptr since asio::ssl::stream is not movable + + std::shared_ptr in_message; + std::shared_ptr fragmented_in_message; + + long timeout_idle; + Mutex timer_mutex; + std::unique_ptr timer GUARDED_BY(timer_mutex); + + void close() noexcept { + error_code ec; + socket->lowest_layer().shutdown(asio::ip::tcp::socket::shutdown_both, ec); + socket->lowest_layer().cancel(ec); + } + + void set_timeout(long seconds = -1) noexcept { + bool use_timeout_idle = false; + if(seconds == -1) { + use_timeout_idle = true; + seconds = timeout_idle; + } + + LockGuard lock(timer_mutex); + + if(seconds == 0) { + timer = nullptr; + return; + } + + timer = std::unique_ptr(new asio::steady_timer(get_socket_executor(*socket), std::chrono::seconds(seconds))); + std::weak_ptr connection_weak(this->shared_from_this()); // To avoid keeping Connection instance alive longer than needed + timer->async_wait([connection_weak, use_timeout_idle](const error_code &ec) { + if(!ec) { + if(auto connection = connection_weak.lock()) { + if(use_timeout_idle) + connection->send_close(1000, "idle timeout"); // 1000=normal closure + else + connection->close(); + } + } + }); + } + + void cancel_timeout() noexcept { + LockGuard lock(timer_mutex); + if(timer) { + try { + timer->cancel(); + } + catch(...) { + } + } + } + + class OutData { + public: + OutData(std::shared_ptr out_message_, std::function &&callback_) noexcept + : out_message(std::move(out_message_)), callback(std::move(callback_)) {} + std::shared_ptr out_message; + std::function callback; + }; + + Mutex send_queue_mutex; + std::list send_queue GUARDED_BY(send_queue_mutex); + + void send_from_queue() REQUIRES(send_queue_mutex) { + auto self = this->shared_from_this(); + asio::async_write(*self->socket, send_queue.begin()->out_message->streambuf, [self](const error_code &ec, std::size_t /*bytes_transferred*/) { + auto lock = self->handler_runner->continue_lock(); + if(!lock) + return; + { + LockGuard lock(self->send_queue_mutex); + if(!ec) { + auto it = self->send_queue.begin(); + auto callback = std::move(it->callback); + self->send_queue.erase(it); + if(self->send_queue.size() > 0) + self->send_from_queue(); + + lock.unlock(); + if(callback) + callback(ec); + } + else { + // All handlers in the queue is called with ec: + std::vector> callbacks; + for(auto &out_data : self->send_queue) { + if(out_data.callback) + callbacks.emplace_back(std::move(out_data.callback)); + } + self->send_queue.clear(); + + lock.unlock(); + for(auto &callback : callbacks) + callback(ec); + } + } + }); + } + + std::atomic closed; + + void read_remote_endpoint() noexcept { + try { + remote_endpoint = socket->lowest_layer().remote_endpoint(); + } + catch(const std::exception &e) { + std::cerr << e.what() << std::endl; + } + } + + public: + /// fin_rsv_opcode: 129=one fragment, text, 130=one fragment, binary, 136=close connection. + /// See http://tools.ietf.org/html/rfc6455#section-5.2 for more information. + void send(const std::shared_ptr &out_message, const std::function &callback = nullptr, unsigned char fin_rsv_opcode = 129) { + cancel_timeout(); + set_timeout(); + + // Create mask + std::array mask; + std::uniform_int_distribution dist(0, 255); + std::random_device rd; + for(std::size_t c = 0; c < 4; c++) + mask[c] = static_cast(dist(rd)); + + std::size_t length = out_message->size(); + + std::size_t max_additional_bytes = 14; // ws protocol adds at most 14 bytes + auto out_header_and_message = std::make_shared(length + max_additional_bytes); + + out_header_and_message->put(static_cast(fin_rsv_opcode)); + // Masked (first length byte>=128) + if(length >= 126) { + std::size_t num_bytes; + if(length > 0xffff) { + num_bytes = 8; + out_header_and_message->put(static_cast(127 + 128)); + } + else { + num_bytes = 2; + out_header_and_message->put(static_cast(126 + 128)); + } + + for(std::size_t c = num_bytes - 1; c != static_cast(-1); c--) + out_header_and_message->put((static_cast(length) >> (8 * c)) % 256); + } + else + out_header_and_message->put(static_cast(length + 128)); + + for(std::size_t c = 0; c < 4; c++) + out_header_and_message->put(static_cast(mask[c])); + + for(std::size_t c = 0; c < length; c++) + out_header_and_message->put(out_message->get() ^ mask[c % 4]); + + LockGuard lock(send_queue_mutex); + send_queue.emplace_back(out_header_and_message, callback); + if(send_queue.size() == 1) + send_from_queue(); + } + + /// Convenience function for sending a string. + /// fin_rsv_opcode: 129=one fragment, text, 130=one fragment, binary, 136=close connection. + /// See http://tools.ietf.org/html/rfc6455#section-5.2 for more information. + void send(string_view out_message_str, const std::function &callback = nullptr, unsigned char fin_rsv_opcode = 129) { + auto out_message = std::make_shared(); + out_message->write(out_message_str.data(), static_cast(out_message_str.size())); + send(out_message, callback, fin_rsv_opcode); + } + + void send_close(int status, const std::string &reason = "", const std::function &callback = nullptr) { + // Send close only once (in case close is initiated by client) + if(closed) + return; + closed = true; + + auto out_message = std::make_shared(); + + out_message->put(status >> 8); + out_message->put(status % 256); + + *out_message << reason; + + // fin_rsv_opcode=136: message close + send(out_message, callback, 136); + } + }; + + class Config { + friend class SocketClientBase; + + private: + Config() noexcept {} + + public: + /// Timeout on request handling. Defaults to no timeout. + long timeout_request = 0; + /// Idle timeout. Defaults to no timeout. + long timeout_idle = 0; + /// Maximum size of incoming messages. Defaults to architecture maximum. + /// Exceeding this limit will result in a message_size error code and the connection will be closed. + std::size_t max_message_size = std::numeric_limits::max(); + /// Additional header fields to send when performing WebSocket upgrade. + /// Use this variable to for instance set Sec-WebSocket-Protocol. + CaseInsensitiveMultimap header; + /// Set proxy server (server:port) + std::string proxy_server; + }; + /// Set before calling start(). + Config config; + + std::function)> on_open; + std::function, std::shared_ptr)> on_message; + std::function, int, const std::string &)> on_close; + std::function, const error_code &)> on_error; + std::function)> on_ping; + std::function)> on_pong; + + void start() { + if(!io_service) { + io_service = std::make_shared(); + internal_io_service = true; + } + + if(io_service->stopped()) + restart(*io_service); + + connect(); + + if(internal_io_service) + io_service->run(); + } + + void stop() noexcept { + { + LockGuard lock(connection_mutex); + if(connection) + connection->close(); + } + + if(internal_io_service) + io_service->stop(); + } + + virtual ~SocketClientBase() noexcept { + handler_runner->stop(); + stop(); + } + + /// If you have your own io_context, store its pointer here before running start(). + std::shared_ptr io_service; + + protected: + bool internal_io_service = false; + + std::string host; + unsigned short port; + unsigned short default_port; + std::string path; + + Mutex connection_mutex; + std::shared_ptr connection GUARDED_BY(connection_mutex); + + std::shared_ptr handler_runner; + + SocketClientBase(const std::string &host_port_path, unsigned short default_port) noexcept : default_port(default_port), handler_runner(new ScopeRunner()) { + auto host_port_end = host_port_path.find('/'); + auto host_port = parse_host_port(host_port_path.substr(0, host_port_end), default_port); + host = std::move(host_port.first); + port = host_port.second; + + if(host_port_end != std::string::npos) + path = host_port_path.substr(host_port_end); + else + path = "/"; + } + + std::pair parse_host_port(const std::string &host_port, unsigned short default_port) const noexcept { + std::pair parsed_host_port; + std::size_t host_end = host_port.find(':'); + if(host_end == std::string::npos) { + parsed_host_port.first = host_port; + parsed_host_port.second = default_port; + } + else { + parsed_host_port.first = host_port.substr(0, host_end); + parsed_host_port.second = static_cast(stoul(host_port.substr(host_end + 1))); + } + return parsed_host_port; + } + + virtual void connect() = 0; + + void upgrade(const std::shared_ptr &connection) { + connection->read_remote_endpoint(); + + auto corrected_path = path; + if(!config.proxy_server.empty() && std::is_same::value) + corrected_path = "http://" + host + ':' + std::to_string(port) + corrected_path; + + auto write_buffer = std::make_shared(); + std::ostream ostream(write_buffer.get()); + ostream << "GET " << corrected_path << " HTTP/1.1\r\n"; + ostream << "Host: " << host; + if(port != default_port) + ostream << ':' << std::to_string(port); + ostream << "\r\n"; + ostream << "Upgrade: websocket\r\n"; + ostream << "Connection: Upgrade\r\n"; + + // Make random 16-byte nonce + std::string nonce; + nonce.reserve(16); + std::uniform_int_distribution dist(0, 255); + std::random_device rd; + for(std::size_t c = 0; c < 16; c++) + nonce += static_cast(dist(rd)); + + auto nonce_base64 = std::make_shared(Crypto::Base64::encode(nonce)); + ostream << "Sec-WebSocket-Key: " << *nonce_base64 << "\r\n"; + ostream << "Sec-WebSocket-Version: 13\r\n"; + for(auto &header_field : config.header) + ostream << header_field.first << ": " << header_field.second << "\r\n"; + ostream << "\r\n"; + + connection->in_message = std::shared_ptr(new InMessage()); + + connection->set_timeout(config.timeout_request); + asio::async_write(*connection->socket, *write_buffer, [this, connection, write_buffer, nonce_base64](const error_code &ec, std::size_t /*bytes_transferred*/) { + connection->cancel_timeout(); + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + connection->set_timeout(this->config.timeout_request); + asio::async_read_until(*connection->socket, connection->in_message->streambuf, "\r\n\r\n", [this, connection, nonce_base64](const error_code &ec, std::size_t bytes_transferred) { + connection->cancel_timeout(); + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + // connection->in_message->streambuf.size() is not necessarily the same as bytes_transferred, from Boost-docs: + // "After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter" + // The chosen solution is to extract lines from the stream directly when parsing the header. What is left of the + // streambuf (maybe some bytes of a message) is appended to in the next async_read-function + std::size_t num_additional_bytes = connection->in_message->streambuf.size() - bytes_transferred; + + if(!ResponseMessage::parse(*connection->in_message, connection->http_version, connection->status_code, connection->header)) { + this->connection_error(connection, make_error_code::make_error_code(errc::protocol_error)); + return; + } + if(connection->status_code.compare(0, 4, "101 ") != 0) { + this->connection_error(connection, make_error_code::make_error_code(errc::permission_denied)); + return; + } + auto header_it = connection->header.find("Sec-WebSocket-Accept"); + static auto ws_magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + if(header_it != connection->header.end() && + Crypto::Base64::decode(header_it->second) == Crypto::sha1(*nonce_base64 + ws_magic_string)) { + this->connection_open(connection); + read_message(connection, num_additional_bytes); + } + else + this->connection_error(connection, make_error_code::make_error_code(errc::protocol_error)); + } + else + this->connection_error(connection, ec); + }); + } + else + this->connection_error(connection, ec); + }); + } + + void read_message(const std::shared_ptr &connection, std::size_t num_additional_bytes) { + asio::async_read(*connection->socket, connection->in_message->streambuf, asio::transfer_exactly(num_additional_bytes > 2 ? 0 : 2 - num_additional_bytes), [this, connection](const error_code &ec, std::size_t bytes_transferred) { + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + if(bytes_transferred == 0 && connection->in_message->streambuf.size() == 0) { // TODO: This might happen on server at least, might also happen here + this->read_message(connection, 0); + return; + } + std::size_t num_additional_bytes = connection->in_message->streambuf.size() - bytes_transferred; + + std::array first_bytes; + connection->in_message->read(reinterpret_cast(&first_bytes[0]), 2); + + connection->in_message->fin_rsv_opcode = first_bytes[0]; + + // Close connection if masked message from server (protocol error) + if(first_bytes[1] >= 128) { + const std::string reason("message from server masked"); + connection->send_close(1002, reason); + this->connection_close(connection, 1002, reason); + return; + } + + std::size_t length = (first_bytes[1] & 127); + + if(length == 126) { + // 2 next bytes is the size of content + asio::async_read(*connection->socket, connection->in_message->streambuf, asio::transfer_exactly(num_additional_bytes > 2 ? 0 : 2 - num_additional_bytes), [this, connection](const error_code &ec, std::size_t bytes_transferred) { + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + std::size_t num_additional_bytes = connection->in_message->streambuf.size() - bytes_transferred; + + std::array length_bytes; + connection->in_message->read(reinterpret_cast(&length_bytes[0]), 2); + + std::size_t length = 0; + std::size_t num_bytes = 2; + for(std::size_t c = 0; c < num_bytes; c++) + length += static_cast(length_bytes[c]) << (8 * (num_bytes - 1 - c)); + + connection->in_message->length = length; + this->read_message_content(connection, num_additional_bytes); + } + else + this->connection_error(connection, ec); + }); + } + else if(length == 127) { + // 8 next bytes is the size of content + asio::async_read(*connection->socket, connection->in_message->streambuf, asio::transfer_exactly(num_additional_bytes > 8 ? 0 : 8 - num_additional_bytes), [this, connection](const error_code &ec, std::size_t bytes_transferred) { + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + std::size_t num_additional_bytes = connection->in_message->streambuf.size() - bytes_transferred; + + std::array length_bytes; + connection->in_message->read(reinterpret_cast(&length_bytes[0]), 8); + + std::size_t length = 0; + std::size_t num_bytes = 8; + for(std::size_t c = 0; c < num_bytes; c++) + length += static_cast(length_bytes[c]) << (8 * (num_bytes - 1 - c)); + + connection->in_message->length = length; + this->read_message_content(connection, num_additional_bytes); + } + else + this->connection_error(connection, ec); + }); + } + else { + connection->in_message->length = length; + this->read_message_content(connection, num_additional_bytes); + } + } + else + this->connection_error(connection, ec); + }); + } + + void read_message_content(const std::shared_ptr &connection, std::size_t num_additional_bytes) { + if(connection->in_message->length + (connection->fragmented_in_message ? connection->fragmented_in_message->length : 0) > config.max_message_size) { + connection_error(connection, make_error_code::make_error_code(errc::message_size)); + const int status = 1009; + const std::string reason = "message too big"; + connection->send_close(status, reason); + connection_close(connection, status, reason); + return; + } + asio::async_read(*connection->socket, connection->in_message->streambuf, asio::transfer_exactly(num_additional_bytes > connection->in_message->length ? 0 : connection->in_message->length - num_additional_bytes), [this, connection](const error_code &ec, std::size_t bytes_transferred) { + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + std::size_t num_additional_bytes = connection->in_message->streambuf.size() - bytes_transferred; + std::shared_ptr next_in_message; + if(num_additional_bytes > 0) { // Extract bytes that are not extra bytes in buffer (only happen when several messages are sent in upgrade response) + next_in_message = connection->in_message; + connection->in_message = std::shared_ptr(new InMessage(next_in_message->fin_rsv_opcode, next_in_message->length)); + std::ostream ostream(&connection->in_message->streambuf); + for(std::size_t c = 0; c < next_in_message->length; ++c) + ostream.put(next_in_message->get()); + } + else + next_in_message = std::shared_ptr(new InMessage()); + + // If connection close + if((connection->in_message->fin_rsv_opcode & 0x0f) == 8) { + connection->cancel_timeout(); + connection->set_timeout(); + + int status = 0; + if(connection->in_message->length >= 2) { + unsigned char byte1 = connection->in_message->get(); + unsigned char byte2 = connection->in_message->get(); + status = (static_cast(byte1) << 8) + byte2; + } + + auto reason = connection->in_message->string(); + connection->send_close(status, reason); + this->connection_close(connection, status, reason); + } + // If ping + else if((connection->in_message->fin_rsv_opcode & 0x0f) == 9) { + connection->cancel_timeout(); + connection->set_timeout(); + + // Send pong + auto out_message = std::make_shared(); + *out_message << connection->in_message->string(); + connection->send(out_message, nullptr, connection->in_message->fin_rsv_opcode + 1); + + if(this->on_ping) + this->on_ping(connection); + + // Next message + connection->in_message = next_in_message; + this->read_message(connection, num_additional_bytes); + } + // If pong + else if((connection->in_message->fin_rsv_opcode & 0x0f) == 10) { + connection->cancel_timeout(); + connection->set_timeout(); + + if(this->on_pong) + this->on_pong(connection); + + // Next message + connection->in_message = next_in_message; + this->read_message(connection, num_additional_bytes); + } + // If fragmented message and not final fragment + else if((connection->in_message->fin_rsv_opcode & 0x80) == 0) { + if(!connection->fragmented_in_message) { + connection->fragmented_in_message = connection->in_message; + connection->fragmented_in_message->fin_rsv_opcode |= 0x80; + } + else { + connection->fragmented_in_message->length += connection->in_message->length; + std::ostream ostream(&connection->fragmented_in_message->streambuf); + ostream << connection->in_message->rdbuf(); + } + + // Next message + connection->in_message = next_in_message; + this->read_message(connection, num_additional_bytes); + } + else { + connection->cancel_timeout(); + connection->set_timeout(); + + if(this->on_message) { + if(connection->fragmented_in_message) { + connection->fragmented_in_message->length += connection->in_message->length; + std::ostream ostream(&connection->fragmented_in_message->streambuf); + ostream << connection->in_message->rdbuf(); + + this->on_message(connection, connection->fragmented_in_message); + } + else + this->on_message(connection, connection->in_message); + } + + // Next message + connection->in_message = next_in_message; + // Only reset fragmented_message for non-control frames (control frames can be in between a fragmented message) + connection->fragmented_in_message = nullptr; + this->read_message(connection, num_additional_bytes); + } + } + else + this->connection_error(connection, ec); + }); + } + + void connection_open(const std::shared_ptr &connection) const { + connection->cancel_timeout(); + connection->set_timeout(); + + if(on_open) + on_open(connection); + } + + void connection_close(const std::shared_ptr &connection, int status, const std::string &reason) const { + connection->cancel_timeout(); + connection->set_timeout(); + + if(on_close) + on_close(connection, status, reason); + } + + void connection_error(const std::shared_ptr &connection, const error_code &ec) const { + connection->cancel_timeout(); + connection->set_timeout(); + + if(on_error) + on_error(connection, ec); + } + }; + + template + class SocketClient : public SocketClientBase {}; + + using WS = asio::ip::tcp::socket; + + template <> + class SocketClient : public SocketClientBase { + public: + SocketClient(const std::string &server_port_path) noexcept : SocketClientBase::SocketClientBase(server_port_path, 80){}; + + protected: + void connect() override { + LockGuard lock(connection_mutex); + auto connection = this->connection = std::shared_ptr(new Connection(handler_runner, config.timeout_idle, *io_service)); + lock.unlock(); + + std::pair host_port; + if(config.proxy_server.empty()) + host_port = {host, std::to_string(port)}; + else { + auto proxy_host_port = parse_host_port(config.proxy_server, 8080); + host_port = {proxy_host_port.first, std::to_string(proxy_host_port.second)}; + } + + auto resolver = std::make_shared(*io_service); + connection->set_timeout(config.timeout_request); + async_resolve(*resolver, host_port, [this, connection, resolver](const error_code &ec, resolver_results results) { + connection->cancel_timeout(); + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + connection->set_timeout(this->config.timeout_request); + asio::async_connect(*connection->socket, results, [this, connection, resolver](const error_code &ec, async_connect_endpoint /*endpoint*/) { + connection->cancel_timeout(); + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + asio::ip::tcp::no_delay option(true); + connection->socket->set_option(option); + + this->upgrade(connection); + } + else + this->connection_error(connection, ec); + }); + } + else + this->connection_error(connection, ec); + }); + } + }; +} // namespace SimpleWeb + +#endif /* SIMPLE_WEB_CLIENT_WS_HPP */ diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/client_wss.hpp b/src/comm/ros_bridge/Simple-WebSocket-Server/client_wss.hpp new file mode 100644 index 000000000..914afb8d7 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/client_wss.hpp @@ -0,0 +1,143 @@ +#ifndef SIMPLE_WEB_CLIENT_WSS_HPP +#define SIMPLE_WEB_CLIENT_WSS_HPP + +#include "client_ws.hpp" + +#ifdef USE_STANDALONE_ASIO +#include +#else +#include +#endif + +namespace SimpleWeb { + using WSS = asio::ssl::stream; + + template <> + class SocketClient : public SocketClientBase { + public: + SocketClient(const std::string &server_port_path, bool verify_certificate = true, + const std::string &cert_file = std::string(), const std::string &private_key_file = std::string(), + const std::string &verify_file = std::string()) + : SocketClientBase::SocketClientBase(server_port_path, 443), context(asio::ssl::context::tlsv12) { + if(cert_file.size() > 0 && private_key_file.size() > 0) { + context.use_certificate_chain_file(cert_file); + context.use_private_key_file(private_key_file, asio::ssl::context::pem); + } + + if(verify_certificate) + context.set_verify_callback(asio::ssl::rfc2818_verification(host)); + + if(verify_file.size() > 0) + context.load_verify_file(verify_file); + else + context.set_default_verify_paths(); + + if(verify_file.size() > 0 || verify_certificate) + context.set_verify_mode(asio::ssl::verify_peer); + else + context.set_verify_mode(asio::ssl::verify_none); + }; + + protected: + asio::ssl::context context; + + void connect() override { + LockGuard connection_lock(connection_mutex); + auto connection = this->connection = std::shared_ptr(new Connection(handler_runner, config.timeout_idle, *io_service, context)); + connection_lock.unlock(); + + std::pair host_port; + if(config.proxy_server.empty()) + host_port = {host, std::to_string(port)}; + else { + auto proxy_host_port = parse_host_port(config.proxy_server, 8080); + host_port = {proxy_host_port.first, std::to_string(proxy_host_port.second)}; + } + + auto resolver = std::make_shared(*io_service); + connection->set_timeout(config.timeout_request); + async_resolve(*resolver, host_port, [this, connection, resolver](const error_code &ec, resolver_results results) { + connection->cancel_timeout(); + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + connection->set_timeout(this->config.timeout_request); + asio::async_connect(connection->socket->lowest_layer(), results, [this, connection, resolver](const error_code &ec, async_connect_endpoint /*endpoint*/) { + connection->cancel_timeout(); + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + asio::ip::tcp::no_delay option(true); + error_code ec; + connection->socket->lowest_layer().set_option(option, ec); + + if(!this->config.proxy_server.empty()) { + auto write_buffer = std::make_shared(); + std::ostream write_stream(write_buffer.get()); + auto host_port = this->host + ':' + std::to_string(this->port); + write_stream << "CONNECT " + host_port + " HTTP/1.1\r\n" + << "Host: " << host_port << "\r\n\r\n"; + connection->set_timeout(this->config.timeout_request); + asio::async_write(connection->socket->next_layer(), *write_buffer, [this, connection, write_buffer](const error_code &ec, std::size_t /*bytes_transferred*/) { + connection->cancel_timeout(); + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + connection->set_timeout(this->config.timeout_request); + asio::async_read_until(connection->socket->next_layer(), connection->in_message->streambuf, "\r\n\r\n", [this, connection](const error_code &ec, std::size_t /*bytes_transferred*/) { + connection->cancel_timeout(); + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + if(!ResponseMessage::parse(*connection->in_message, connection->http_version, connection->status_code, connection->header)) + this->connection_error(connection, make_error_code::make_error_code(errc::protocol_error)); + else { + if(connection->status_code.compare(0, 3, "200") != 0) + this->connection_error(connection, make_error_code::make_error_code(errc::permission_denied)); + else + this->handshake(connection); + } + } + else + this->connection_error(connection, ec); + }); + } + else + this->connection_error(connection, ec); + }); + } + else + this->handshake(connection); + } + else + this->connection_error(connection, ec); + }); + } + else + this->connection_error(connection, ec); + }); + } + + void handshake(const std::shared_ptr &connection) { + SSL_set_tlsext_host_name(connection->socket->native_handle(), this->host.c_str()); + + connection->set_timeout(this->config.timeout_request); + connection->socket->async_handshake(asio::ssl::stream_base::client, [this, connection](const error_code &ec) { + connection->cancel_timeout(); + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) + upgrade(connection); + else + this->connection_error(connection, ec); + }); + } + }; +} // namespace SimpleWeb + +#endif /* SIMPLE_WEB_CLIENT_WSS_HPP */ diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/crypto.hpp b/src/comm/ros_bridge/Simple-WebSocket-Server/crypto.hpp new file mode 100644 index 000000000..981f21423 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/crypto.hpp @@ -0,0 +1,227 @@ +#ifndef SIMPLE_WEB_CRYPTO_HPP +#define SIMPLE_WEB_CRYPTO_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace SimpleWeb { +// TODO 2017: remove workaround for MSVS 2012 +#if _MSC_VER == 1700 // MSVS 2012 has no definition for round() + inline double round(double x) noexcept { // Custom definition of round() for positive numbers + return floor(x + 0.5); + } +#endif + + class Crypto { + const static std::size_t buffer_size = 131072; + + public: + class Base64 { + public: + static std::string encode(const std::string &ascii) noexcept { + std::string base64; + + BIO *bio, *b64; + BUF_MEM *bptr = BUF_MEM_new(); + + b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + bio = BIO_new(BIO_s_mem()); + BIO_push(b64, bio); + BIO_set_mem_buf(b64, bptr, BIO_CLOSE); + + // Write directly to base64-buffer to avoid copy + auto base64_length = static_cast(round(4 * ceil(static_cast(ascii.size()) / 3.0))); + base64.resize(base64_length); + bptr->length = 0; + bptr->max = base64_length + 1; + bptr->data = &base64[0]; + + if(BIO_write(b64, &ascii[0], static_cast(ascii.size())) <= 0 || BIO_flush(b64) <= 0) + base64.clear(); + + // To keep &base64[0] through BIO_free_all(b64) + bptr->length = 0; + bptr->max = 0; + bptr->data = nullptr; + + BIO_free_all(b64); + + return base64; + } + + static std::string decode(const std::string &base64) noexcept { + std::string ascii; + + // Resize ascii, however, the size is a up to two bytes too large. + ascii.resize((6 * base64.size()) / 8); + BIO *b64, *bio; + + b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); +// TODO: Remove in 2020 +#if(defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER <= 0x1000115fL) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2080000fL) + bio = BIO_new_mem_buf((char *)&base64[0], static_cast(base64.size())); +#else + bio = BIO_new_mem_buf(&base64[0], static_cast(base64.size())); +#endif + bio = BIO_push(b64, bio); + + auto decoded_length = BIO_read(bio, &ascii[0], static_cast(ascii.size())); + if(decoded_length > 0) + ascii.resize(static_cast(decoded_length)); + else + ascii.clear(); + + BIO_free_all(b64); + + return ascii; + } + }; + + /// Return hex string from bytes in input string. + static std::string to_hex_string(const std::string &input) noexcept { + std::stringstream hex_stream; + hex_stream << std::hex << std::internal << std::setfill('0'); + for(auto &byte : input) + hex_stream << std::setw(2) << static_cast(static_cast(byte)); + return hex_stream.str(); + } + + static std::string md5(const std::string &input, std::size_t iterations = 1) noexcept { + std::string hash; + + hash.resize(128 / 8); + MD5(reinterpret_cast(&input[0]), input.size(), reinterpret_cast(&hash[0])); + + for(std::size_t c = 1; c < iterations; ++c) + MD5(reinterpret_cast(&hash[0]), hash.size(), reinterpret_cast(&hash[0])); + + return hash; + } + + static std::string md5(std::istream &stream, std::size_t iterations = 1) noexcept { + MD5_CTX context; + MD5_Init(&context); + std::streamsize read_length; + std::vector buffer(buffer_size); + while((read_length = stream.read(&buffer[0], buffer_size).gcount()) > 0) + MD5_Update(&context, buffer.data(), static_cast(read_length)); + std::string hash; + hash.resize(128 / 8); + MD5_Final(reinterpret_cast(&hash[0]), &context); + + for(std::size_t c = 1; c < iterations; ++c) + MD5(reinterpret_cast(&hash[0]), hash.size(), reinterpret_cast(&hash[0])); + + return hash; + } + + static std::string sha1(const std::string &input, std::size_t iterations = 1) noexcept { + std::string hash; + + hash.resize(160 / 8); + SHA1(reinterpret_cast(&input[0]), input.size(), reinterpret_cast(&hash[0])); + + for(std::size_t c = 1; c < iterations; ++c) + SHA1(reinterpret_cast(&hash[0]), hash.size(), reinterpret_cast(&hash[0])); + + return hash; + } + + static std::string sha1(std::istream &stream, std::size_t iterations = 1) noexcept { + SHA_CTX context; + SHA1_Init(&context); + std::streamsize read_length; + std::vector buffer(buffer_size); + while((read_length = stream.read(&buffer[0], buffer_size).gcount()) > 0) + SHA1_Update(&context, buffer.data(), static_cast(read_length)); + std::string hash; + hash.resize(160 / 8); + SHA1_Final(reinterpret_cast(&hash[0]), &context); + + for(std::size_t c = 1; c < iterations; ++c) + SHA1(reinterpret_cast(&hash[0]), hash.size(), reinterpret_cast(&hash[0])); + + return hash; + } + + static std::string sha256(const std::string &input, std::size_t iterations = 1) noexcept { + std::string hash; + + hash.resize(256 / 8); + SHA256(reinterpret_cast(&input[0]), input.size(), reinterpret_cast(&hash[0])); + + for(std::size_t c = 1; c < iterations; ++c) + SHA256(reinterpret_cast(&hash[0]), hash.size(), reinterpret_cast(&hash[0])); + + return hash; + } + + static std::string sha256(std::istream &stream, std::size_t iterations = 1) noexcept { + SHA256_CTX context; + SHA256_Init(&context); + std::streamsize read_length; + std::vector buffer(buffer_size); + while((read_length = stream.read(&buffer[0], buffer_size).gcount()) > 0) + SHA256_Update(&context, buffer.data(), static_cast(read_length)); + std::string hash; + hash.resize(256 / 8); + SHA256_Final(reinterpret_cast(&hash[0]), &context); + + for(std::size_t c = 1; c < iterations; ++c) + SHA256(reinterpret_cast(&hash[0]), hash.size(), reinterpret_cast(&hash[0])); + + return hash; + } + + static std::string sha512(const std::string &input, std::size_t iterations = 1) noexcept { + std::string hash; + + hash.resize(512 / 8); + SHA512(reinterpret_cast(&input[0]), input.size(), reinterpret_cast(&hash[0])); + + for(std::size_t c = 1; c < iterations; ++c) + SHA512(reinterpret_cast(&hash[0]), hash.size(), reinterpret_cast(&hash[0])); + + return hash; + } + + static std::string sha512(std::istream &stream, std::size_t iterations = 1) noexcept { + SHA512_CTX context; + SHA512_Init(&context); + std::streamsize read_length; + std::vector buffer(buffer_size); + while((read_length = stream.read(&buffer[0], buffer_size).gcount()) > 0) + SHA512_Update(&context, buffer.data(), static_cast(read_length)); + std::string hash; + hash.resize(512 / 8); + SHA512_Final(reinterpret_cast(&hash[0]), &context); + + for(std::size_t c = 1; c < iterations; ++c) + SHA512(reinterpret_cast(&hash[0]), hash.size(), reinterpret_cast(&hash[0])); + + return hash; + } + + /// key_size is number of bytes of the returned key. + static std::string pbkdf2(const std::string &password, const std::string &salt, int iterations, int key_size) noexcept { + std::string key; + key.resize(static_cast(key_size)); + PKCS5_PBKDF2_HMAC_SHA1(password.c_str(), password.size(), + reinterpret_cast(salt.c_str()), salt.size(), iterations, + key_size, reinterpret_cast(&key[0])); + return key; + } + }; +} // namespace SimpleWeb +#endif /* SIMPLE_WEB_CRYPTO_HPP */ diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/javascript_client_example.html b/src/comm/ros_bridge/Simple-WebSocket-Server/javascript_client_example.html new file mode 100644 index 000000000..ac644c1c1 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/javascript_client_example.html @@ -0,0 +1,22 @@ + + + + +WebSocket Test + + + + + diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/mutex.hpp b/src/comm/ros_bridge/Simple-WebSocket-Server/mutex.hpp new file mode 100644 index 000000000..755c20cc6 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/mutex.hpp @@ -0,0 +1,106 @@ +// Based on https://clang.llvm.org/docs/ThreadSafetyAnalysis.html +#ifndef SIMPLE_WEB_MUTEX_HPP +#define SIMPLE_WEB_MUTEX_HPP + +#include + +// Enable thread safety attributes only with clang. +#if defined(__clang__) && (!defined(SWIG)) +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#define CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) + +#define SCOPED_CAPABILITY \ + THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +#define GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#define PT_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) + +#define ACQUIRED_BEFORE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + +#define ACQUIRED_AFTER(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + +#define REQUIRES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define REQUIRES_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + +#define ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + +#define ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + +#define RELEASE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + +#define RELEASE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + +#define EXCLUDES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) + +#define ASSERT_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) + +#define ASSERT_SHARED_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + +#define RETURN_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +#define NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + +namespace SimpleWeb { + /// Defines an annotated interface for mutexes. + class CAPABILITY("mutex") Mutex { + std::mutex mutex; + + public: + void lock() ACQUIRE() { + mutex.lock(); + } + + void unlock() RELEASE() { + mutex.unlock(); + } + }; + + class SCOPED_CAPABILITY LockGuard { + Mutex &mutex; + bool locked = true; + + public: + LockGuard(Mutex &mutex_) ACQUIRE(mutex_) : mutex(mutex_) { + mutex.lock(); + } + void unlock() RELEASE() { + mutex.unlock(); + locked = false; + } + ~LockGuard() RELEASE() { + if(locked) + mutex.unlock(); + } + }; + +} // namespace SimpleWeb + +#endif // SIMPLE_WEB_MUTEX_HPP diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/server_ws.hpp b/src/comm/ros_bridge/Simple-WebSocket-Server/server_ws.hpp new file mode 100644 index 000000000..1216933ae --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/server_ws.hpp @@ -0,0 +1,827 @@ +#ifndef SIMPLE_WEB_SERVER_WS_HPP +#define SIMPLE_WEB_SERVER_WS_HPP + +#include "asio_compatibility.hpp" +#include "crypto.hpp" +#include "mutex.hpp" +#include "utility.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +// Late 2017 TODO: remove the following checks and always use std::regex +#ifdef USE_BOOST_REGEX +#include +namespace SimpleWeb { + namespace regex = boost; +} +#else +#include +namespace SimpleWeb { + namespace regex = std; +} +#endif + +namespace SimpleWeb { + template + class SocketServer; + + template + class SocketServerBase { + public: + class InMessage : public std::istream { + friend class SocketServerBase; + + public: + unsigned char fin_rsv_opcode; + std::size_t size() noexcept { + return length; + } + + /// Convenience function to return std::string. The stream buffer is consumed. + std::string string() noexcept { + try { + std::string str; + auto size = streambuf.size(); + str.resize(size); + read(&str[0], static_cast(size)); + return str; + } + catch(...) { + return std::string(); + } + } + + private: + InMessage() noexcept : std::istream(&streambuf), length(0) {} + InMessage(unsigned char fin_rsv_opcode, std::size_t length) noexcept : std::istream(&streambuf), fin_rsv_opcode(fin_rsv_opcode), length(length) {} + std::size_t length; + asio::streambuf streambuf; + }; + + /// The buffer is not consumed during send operations. + /// Do not alter while sending. + class OutMessage : public std::ostream { + friend class SocketServerBase; + + asio::streambuf streambuf; + + public: + OutMessage() noexcept : std::ostream(&streambuf) {} + OutMessage(std::size_t capacity) noexcept : std::ostream(&streambuf) { + streambuf.prepare(capacity); + } + + /// Returns the size of the buffer + std::size_t size() const noexcept { + return streambuf.size(); + } + }; + + class Connection : public std::enable_shared_from_this { + friend class SocketServerBase; + friend class SocketServer; + + public: + Connection(std::unique_ptr &&socket_) noexcept : socket(std::move(socket_)), timeout_idle(0), closed(false) {} + + std::string method, path, query_string, http_version; + + CaseInsensitiveMultimap header; + + regex::smatch path_match; + + std::string remote_endpoint_address() noexcept { + try { + return socket->lowest_layer().remote_endpoint().address().to_string(); + } + catch(...) { + } + return std::string(); + } + + unsigned short remote_endpoint_port() noexcept { + try { + return socket->lowest_layer().remote_endpoint().port(); + } + catch(...) { + } + return 0; + } + + private: + template + Connection(std::shared_ptr handler_runner_, long timeout_idle, Args &&... args) noexcept + : handler_runner(std::move(handler_runner_)), socket(new socket_type(std::forward(args)...)), timeout_idle(timeout_idle), closed(false) {} + + std::shared_ptr handler_runner; + + std::unique_ptr socket; // Socket must be unique_ptr since asio::ssl::stream is not movable + + asio::streambuf read_buffer; + std::shared_ptr fragmented_in_message; + + long timeout_idle; + + Mutex timer_mutex; + std::unique_ptr timer GUARDED_BY(timer_mutex); + + void close() noexcept { + error_code ec; + socket->lowest_layer().shutdown(asio::ip::tcp::socket::shutdown_both, ec); + socket->lowest_layer().cancel(ec); + } + + void set_timeout(long seconds = -1) noexcept { + bool use_timeout_idle = false; + if(seconds == -1) { + use_timeout_idle = true; + seconds = timeout_idle; + } + + LockGuard lock(timer_mutex); + + if(seconds == 0) { + timer = nullptr; + return; + } + + timer = std::unique_ptr(new asio::steady_timer(get_socket_executor(*socket), std::chrono::seconds(seconds))); + std::weak_ptr connection_weak(this->shared_from_this()); // To avoid keeping Connection instance alive longer than needed + timer->async_wait([connection_weak, use_timeout_idle](const error_code &ec) { + if(!ec) { + if(auto connection = connection_weak.lock()) { + if(use_timeout_idle) + connection->send_close(1000, "idle timeout"); // 1000=normal closure + else + connection->close(); + } + } + }); + } + + void cancel_timeout() noexcept { + LockGuard lock(timer_mutex); + if(timer) { + try { + timer->cancel(); + } + catch(...) { + } + } + } + + class OutData { + public: + OutData(std::shared_ptr out_header_, std::shared_ptr out_message_, + std::function &&callback_) noexcept + : out_header(std::move(out_header_)), out_message(std::move(out_message_)), callback(std::move(callback_)) {} + std::shared_ptr out_header; + std::shared_ptr out_message; + std::function callback; + }; + + Mutex send_queue_mutex; + std::list send_queue GUARDED_BY(send_queue_mutex); + + /// send_queue_mutex must be locked here + void send_from_queue() REQUIRES(send_queue_mutex) { + std::array buffers{send_queue.begin()->out_header->streambuf.data(), send_queue.begin()->out_message->streambuf.data()}; + auto self = this->shared_from_this(); + asio::async_write(*socket, buffers, [self](const error_code &ec, std::size_t /*bytes_transferred*/) { + auto lock = self->handler_runner->continue_lock(); + if(!lock) + return; + { + LockGuard lock(self->send_queue_mutex); + if(!ec) { + auto it = self->send_queue.begin(); + auto callback = std::move(it->callback); + self->send_queue.erase(it); + if(self->send_queue.size() > 0) + self->send_from_queue(); + + lock.unlock(); + if(callback) + callback(ec); + } + else { + // All handlers in the queue is called with ec: + std::vector> callbacks; + for(auto &out_data : self->send_queue) { + if(out_data.callback) + callbacks.emplace_back(std::move(out_data.callback)); + } + self->send_queue.clear(); + + lock.unlock(); + for(auto &callback : callbacks) + callback(ec); + } + } + }); + } + + std::atomic closed; + + public: + /// fin_rsv_opcode: 129=one fragment, text, 130=one fragment, binary, 136=close connection. + /// See http://tools.ietf.org/html/rfc6455#section-5.2 for more information. + void send(const std::shared_ptr &out_message, const std::function &callback = nullptr, unsigned char fin_rsv_opcode = 129) { + cancel_timeout(); + set_timeout(); + + std::size_t length = out_message->size(); + + auto out_header = std::make_shared(10); // Header is at most 10 bytes + + out_header->put(static_cast(fin_rsv_opcode)); + // Unmasked (first length byte<128) + if(length >= 126) { + std::size_t num_bytes; + if(length > 0xffff) { + num_bytes = 8; + out_header->put(127); + } + else { + num_bytes = 2; + out_header->put(126); + } + + for(std::size_t c = num_bytes - 1; c != static_cast(-1); c--) + out_header->put((static_cast(length) >> (8 * c)) % 256); + } + else + out_header->put(static_cast(length)); + + LockGuard lock(send_queue_mutex); + send_queue.emplace_back(out_header, out_message, callback); + if(send_queue.size() == 1) + send_from_queue(); + } + + /// Convenience function for sending a string. + /// fin_rsv_opcode: 129=one fragment, text, 130=one fragment, binary, 136=close connection. + /// See http://tools.ietf.org/html/rfc6455#section-5.2 for more information. + void send(string_view out_message_str, const std::function &callback = nullptr, unsigned char fin_rsv_opcode = 129) { + auto out_message = std::make_shared(); + out_message->write(out_message_str.data(), static_cast(out_message_str.size())); + send(out_message, callback, fin_rsv_opcode); + } + + void send_close(int status, const std::string &reason = "", const std::function &callback = nullptr) { + // Send close only once (in case close is initiated by server) + if(closed) + return; + closed = true; + + auto send_stream = std::make_shared(); + + send_stream->put(status >> 8); + send_stream->put(status % 256); + + *send_stream << reason; + + // fin_rsv_opcode=136: message close + send(send_stream, callback, 136); + } + }; + + class Endpoint { + friend class SocketServerBase; + + private: + Mutex connections_mutex; + std::unordered_set> connections GUARDED_BY(connections_mutex); + + public: + std::function, CaseInsensitiveMultimap &)> on_handshake; + std::function)> on_open; + std::function, std::shared_ptr)> on_message; + std::function, int, const std::string &)> on_close; + std::function, const error_code &)> on_error; + std::function)> on_ping; + std::function)> on_pong; + + std::unordered_set> get_connections() noexcept { + LockGuard lock(connections_mutex); + auto copy = connections; + return copy; + } + }; + + class Config { + friend class SocketServerBase; + + private: + Config(unsigned short port) noexcept : port(port) {} + + public: + /// Port number to use. Defaults to 80 for HTTP and 443 for HTTPS. Set to 0 get an assigned port. + unsigned short port; + /// If io_service is not set, number of threads that the server will use when start() is called. + /// Defaults to 1 thread. + std::size_t thread_pool_size = 1; + /// Timeout on request handling. Defaults to 5 seconds. + long timeout_request = 5; + /// Idle timeout. Defaults to no timeout. + long timeout_idle = 0; + /// Maximum size of incoming messages. Defaults to architecture maximum. + /// Exceeding this limit will result in a message_size error code and the connection will be closed. + std::size_t max_message_size = std::numeric_limits::max(); + /// Additional header fields to send when performing WebSocket handshake. + CaseInsensitiveMultimap header; + /// IPv4 address in dotted decimal form or IPv6 address in hexadecimal notation. + /// If empty, the address will be any address. + std::string address; + /// Set to false to avoid binding the socket to an address that is already in use. Defaults to true. + bool reuse_address = true; + }; + /// Set before calling start(). + Config config; + + private: + class regex_orderable : public regex::regex { + public: + std::string str; + + regex_orderable(const char *regex_cstr) : regex::regex(regex_cstr), str(regex_cstr) {} + regex_orderable(const std::string ®ex_str) : regex::regex(regex_str), str(regex_str) {} + bool operator<(const regex_orderable &rhs) const noexcept { + return str < rhs.str; + } + }; + + public: + /// Warning: do not add or remove endpoints after start() is called + std::map endpoint; + + /// If you know the server port in advance, use start() instead. + /// Returns assigned port. If io_service is not set, an internal io_service is created instead. + /// Call before accept_and_run(). + unsigned short bind() { + asio::ip::tcp::endpoint endpoint; + if(config.address.size() > 0) + endpoint = asio::ip::tcp::endpoint(make_address(config.address), config.port); + else + endpoint = asio::ip::tcp::endpoint(asio::ip::tcp::v6(), config.port); + + if(!io_service) { + io_service = std::make_shared(); + internal_io_service = true; + } + + if(!acceptor) + acceptor = std::unique_ptr(new asio::ip::tcp::acceptor(*io_service)); + acceptor->open(endpoint.protocol()); + acceptor->set_option(asio::socket_base::reuse_address(config.reuse_address)); + acceptor->bind(endpoint); + + after_bind(); + + return acceptor->local_endpoint().port(); + } + + /// If you know the server port in advance, use start() instead. + /// Accept requests, and if io_service was not set before calling bind(), run the internal io_service instead. + /// Call after bind(). + void accept_and_run() { + acceptor->listen(); + accept(); + + if(internal_io_service) { + if(io_service->stopped()) + restart(*io_service); + + // If thread_pool_size>1, start m_io_service.run() in (thread_pool_size-1) threads for thread-pooling + threads.clear(); + for(std::size_t c = 1; c < config.thread_pool_size; c++) { + threads.emplace_back([this]() { + this->io_service->run(); + }); + } + + // Main thread + if(config.thread_pool_size > 0) + io_service->run(); + + // Wait for the rest of the threads, if any, to finish as well + for(auto &t : threads) + t.join(); + } + } + + /// Start the server by calling bind() and accept_and_run() + void start() { + bind(); + accept_and_run(); + } + + /// Stop accepting new connections, and close current connections + void stop() noexcept { + if(acceptor) { + error_code ec; + acceptor->close(ec); + + for(auto &pair : endpoint) { + LockGuard lock(pair.second.connections_mutex); + for(auto &connection : pair.second.connections) + connection->close(); + pair.second.connections.clear(); + } + + if(internal_io_service) + io_service->stop(); + } + } + + /// Stop accepting new connections + void stop_accept() noexcept { + if(acceptor) { + error_code ec; + acceptor->close(ec); + } + } + + virtual ~SocketServerBase() noexcept {} + + std::unordered_set> get_connections() noexcept { + std::unordered_set> all_connections; + for(auto &e : endpoint) { + LockGuard lock(e.second.connections_mutex); + all_connections.insert(e.second.connections.begin(), e.second.connections.end()); + } + return all_connections; + } + + /** + * Upgrades a request, from for instance Simple-Web-Server, to a WebSocket connection. + * The parameters are moved to the Connection object. + * See also Server::on_upgrade in the Simple-Web-Server project. + * The socket's io_service is used, thus running start() is not needed. + * + * Example use: + * server.on_upgrade=[&socket_server] (auto socket, auto request) { + * auto connection=std::make_shared::Connection>(std::move(socket)); + * connection->method=std::move(request->method); + * connection->path=std::move(request->path); + * connection->query_string=std::move(request->query_string); + * connection->http_version=std::move(request->http_version); + * connection->header=std::move(request->header); + * socket_server.upgrade(connection); + * } + */ + void upgrade(const std::shared_ptr &connection) { + connection->handler_runner = handler_runner; + connection->timeout_idle = config.timeout_idle; + write_handshake(connection); + } + + /// If you have your own io_context, store its pointer here before running start(). + std::shared_ptr io_service; + + protected: + bool internal_io_service = false; + + std::unique_ptr acceptor; + std::vector threads; + + std::shared_ptr handler_runner; + + SocketServerBase(unsigned short port) noexcept : config(port), handler_runner(new ScopeRunner()) {} + + virtual void after_bind() {} + virtual void accept() = 0; + + void read_handshake(const std::shared_ptr &connection) { + connection->set_timeout(config.timeout_request); + asio::async_read_until(*connection->socket, connection->read_buffer, "\r\n\r\n", [this, connection](const error_code &ec, std::size_t /*bytes_transferred*/) { + connection->cancel_timeout(); + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + std::istream stream(&connection->read_buffer); + if(RequestMessage::parse(stream, connection->method, connection->path, connection->query_string, connection->http_version, connection->header)) + write_handshake(connection); + } + }); + } + + void write_handshake(const std::shared_ptr &connection) { + for(auto ®ex_endpoint : endpoint) { + regex::smatch path_match; + if(regex::regex_match(connection->path, path_match, regex_endpoint.first)) { + auto write_buffer = std::make_shared(); + std::ostream handshake(write_buffer.get()); + + StatusCode status_code = StatusCode::information_switching_protocols; + auto key_it = connection->header.find("Sec-WebSocket-Key"); + if(key_it == connection->header.end()) + status_code = StatusCode::client_error_upgrade_required; + else { + CaseInsensitiveMultimap response_header = config.header; + response_header.emplace("Upgrade", "websocket"); + response_header.emplace("Connection", "Upgrade"); + static auto ws_magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + auto sha1 = Crypto::sha1(key_it->second + ws_magic_string); + response_header.emplace("Sec-WebSocket-Accept", Crypto::Base64::encode(sha1)); + + if(regex_endpoint.second.on_handshake) + status_code = regex_endpoint.second.on_handshake(connection, response_header); + + if(status_code == StatusCode::information_switching_protocols) { + handshake << "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"; + for(auto &header_field : response_header) + handshake << header_field.first << ": " << header_field.second << "\r\n"; + handshake << "\r\n"; + } + } + if(status_code != StatusCode::information_switching_protocols) + handshake << "HTTP/1.1 " + SimpleWeb::status_code(status_code) + "\r\n\r\n"; + + connection->path_match = std::move(path_match); + connection->set_timeout(config.timeout_request); + asio::async_write(*connection->socket, *write_buffer, [this, connection, write_buffer, ®ex_endpoint, status_code](const error_code &ec, std::size_t /*bytes_transferred*/) { + connection->cancel_timeout(); + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(status_code != StatusCode::information_switching_protocols) + return; + if(!ec) { + connection_open(connection, regex_endpoint.second); + read_message(connection, regex_endpoint.second); + } + else + connection_error(connection, regex_endpoint.second, ec); + }); + return; + } + } + } + + void read_message(const std::shared_ptr &connection, Endpoint &endpoint) const { + asio::async_read(*connection->socket, connection->read_buffer, asio::transfer_exactly(2), [this, connection, &endpoint](const error_code &ec, std::size_t bytes_transferred) { + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + if(bytes_transferred == 0) { // TODO: why does this happen sometimes? + read_message(connection, endpoint); + return; + } + std::istream stream(&connection->read_buffer); + + std::array first_bytes; + stream.read((char *)&first_bytes[0], 2); + + unsigned char fin_rsv_opcode = first_bytes[0]; + + // Close connection if unmasked message from client (protocol error) + if(first_bytes[1] < 128) { + const std::string reason("message from client not masked"); + connection->send_close(1002, reason); + connection_close(connection, endpoint, 1002, reason); + return; + } + + std::size_t length = (first_bytes[1] & 127); + + if(length == 126) { + // 2 next bytes is the size of content + asio::async_read(*connection->socket, connection->read_buffer, asio::transfer_exactly(2), [this, connection, &endpoint, fin_rsv_opcode](const error_code &ec, std::size_t /*bytes_transferred*/) { + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + std::istream stream(&connection->read_buffer); + + std::array length_bytes; + stream.read((char *)&length_bytes[0], 2); + + std::size_t length = 0; + std::size_t num_bytes = 2; + for(std::size_t c = 0; c < num_bytes; c++) + length += static_cast(length_bytes[c]) << (8 * (num_bytes - 1 - c)); + + read_message_content(connection, length, endpoint, fin_rsv_opcode); + } + else + connection_error(connection, endpoint, ec); + }); + } + else if(length == 127) { + // 8 next bytes is the size of content + asio::async_read(*connection->socket, connection->read_buffer, asio::transfer_exactly(8), [this, connection, &endpoint, fin_rsv_opcode](const error_code &ec, std::size_t /*bytes_transferred*/) { + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + std::istream stream(&connection->read_buffer); + + std::array length_bytes; + stream.read((char *)&length_bytes[0], 8); + + std::size_t length = 0; + std::size_t num_bytes = 8; + for(std::size_t c = 0; c < num_bytes; c++) + length += static_cast(length_bytes[c]) << (8 * (num_bytes - 1 - c)); + + read_message_content(connection, length, endpoint, fin_rsv_opcode); + } + else + connection_error(connection, endpoint, ec); + }); + } + else + read_message_content(connection, length, endpoint, fin_rsv_opcode); + } + else + connection_error(connection, endpoint, ec); + }); + } + + void read_message_content(const std::shared_ptr &connection, std::size_t length, Endpoint &endpoint, unsigned char fin_rsv_opcode) const { + if(length + (connection->fragmented_in_message ? connection->fragmented_in_message->length : 0) > config.max_message_size) { + connection_error(connection, endpoint, make_error_code::make_error_code(errc::message_size)); + const int status = 1009; + const std::string reason = "message too big"; + connection->send_close(status, reason); + connection_close(connection, endpoint, status, reason); + return; + } + asio::async_read(*connection->socket, connection->read_buffer, asio::transfer_exactly(4 + length), [this, connection, length, &endpoint, fin_rsv_opcode](const error_code &ec, std::size_t /*bytes_transferred*/) { + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + if(!ec) { + std::istream istream(&connection->read_buffer); + + // Read mask + std::array mask; + istream.read((char *)&mask[0], 4); + + std::shared_ptr in_message; + + // If fragmented message + if((fin_rsv_opcode & 0x80) == 0 || (fin_rsv_opcode & 0x0f) == 0) { + if(!connection->fragmented_in_message) { + connection->fragmented_in_message = std::shared_ptr(new InMessage(fin_rsv_opcode, length)); + connection->fragmented_in_message->fin_rsv_opcode |= 0x80; + } + else + connection->fragmented_in_message->length += length; + in_message = connection->fragmented_in_message; + } + else + in_message = std::shared_ptr(new InMessage(fin_rsv_opcode, length)); + std::ostream ostream(&in_message->streambuf); + for(std::size_t c = 0; c < length; c++) + ostream.put(istream.get() ^ mask[c % 4]); + + // If connection close + if((fin_rsv_opcode & 0x0f) == 8) { + connection->cancel_timeout(); + connection->set_timeout(); + + int status = 0; + if(length >= 2) { + unsigned char byte1 = in_message->get(); + unsigned char byte2 = in_message->get(); + status = (static_cast(byte1) << 8) + byte2; + } + + auto reason = in_message->string(); + connection->send_close(status, reason); + this->connection_close(connection, endpoint, status, reason); + } + // If ping + else if((fin_rsv_opcode & 0x0f) == 9) { + connection->cancel_timeout(); + connection->set_timeout(); + + // Send pong + auto out_message = std::make_shared(); + *out_message << in_message->string(); + connection->send(out_message, nullptr, fin_rsv_opcode + 1); + + if(endpoint.on_ping) + endpoint.on_ping(connection); + + // Next message + this->read_message(connection, endpoint); + } + // If pong + else if((fin_rsv_opcode & 0x0f) == 10) { + connection->cancel_timeout(); + connection->set_timeout(); + + if(endpoint.on_pong) + endpoint.on_pong(connection); + + // Next message + this->read_message(connection, endpoint); + } + // If fragmented message and not final fragment + else if((fin_rsv_opcode & 0x80) == 0) { + // Next message + this->read_message(connection, endpoint); + } + else { + connection->cancel_timeout(); + connection->set_timeout(); + + if(endpoint.on_message) + endpoint.on_message(connection, in_message); + + // Next message + // Only reset fragmented_in_message for non-control frames (control frames can be in between a fragmented message) + connection->fragmented_in_message = nullptr; + this->read_message(connection, endpoint); + } + } + else + this->connection_error(connection, endpoint, ec); + }); + } + + void connection_open(const std::shared_ptr &connection, Endpoint &endpoint) const { + connection->cancel_timeout(); + connection->set_timeout(); + + { + LockGuard lock(endpoint.connections_mutex); + endpoint.connections.insert(connection); + } + + if(endpoint.on_open) + endpoint.on_open(connection); + } + + void connection_close(const std::shared_ptr &connection, Endpoint &endpoint, int status, const std::string &reason) const { + connection->cancel_timeout(); + connection->set_timeout(); + + { + LockGuard lock(endpoint.connections_mutex); + endpoint.connections.erase(connection); + } + + if(endpoint.on_close) + endpoint.on_close(connection, status, reason); + } + + void connection_error(const std::shared_ptr &connection, Endpoint &endpoint, const error_code &ec) const { + connection->cancel_timeout(); + connection->set_timeout(); + + { + LockGuard lock(endpoint.connections_mutex); + endpoint.connections.erase(connection); + } + + if(endpoint.on_error) + endpoint.on_error(connection, ec); + } + }; + + template + class SocketServer : public SocketServerBase {}; + + using WS = asio::ip::tcp::socket; + + template <> + class SocketServer : public SocketServerBase { + public: + SocketServer() noexcept : SocketServerBase(80) {} + + protected: + void accept() override { + std::shared_ptr connection(new Connection(handler_runner, config.timeout_idle, *io_service)); + + acceptor->async_accept(*connection->socket, [this, connection](const error_code &ec) { + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + // Immediately start accepting a new connection (if io_service hasn't been stopped) + if(ec != error::operation_aborted) + accept(); + + if(!ec) { + asio::ip::tcp::no_delay option(true); + connection->socket->set_option(option); + + read_handshake(connection); + } + }); + } + }; +} // namespace SimpleWeb + +#endif /* SIMPLE_WEB_SERVER_WS_HPP */ diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/server_wss.hpp b/src/comm/ros_bridge/Simple-WebSocket-Server/server_wss.hpp new file mode 100644 index 000000000..534e845f5 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/server_wss.hpp @@ -0,0 +1,79 @@ +#ifndef SIMPLE_WEB_SERVER_WSS_HPP +#define SIMPLE_WEB_SERVER_WSS_HPP + +#include "server_ws.hpp" +#include +#include + +#ifdef USE_STANDALONE_ASIO +#include +#else +#include +#endif + + +namespace SimpleWeb { + using WSS = asio::ssl::stream; + + template <> + class SocketServer : public SocketServerBase { + bool set_session_id_context = false; + + public: + SocketServer(const std::string &cert_file, const std::string &private_key_file, const std::string &verify_file = std::string()) + : SocketServerBase(443), context(asio::ssl::context::tlsv12) { + context.use_certificate_chain_file(cert_file); + context.use_private_key_file(private_key_file, asio::ssl::context::pem); + + if(verify_file.size() > 0) { + context.load_verify_file(verify_file); + context.set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert | + asio::ssl::verify_client_once); + set_session_id_context = true; + } + } + + protected: + asio::ssl::context context; + + void after_bind() override { + if(set_session_id_context) { + // Creating session_id_context from address:port but reversed due to small SSL_MAX_SSL_SESSION_ID_LENGTH + auto session_id_context = std::to_string(acceptor->local_endpoint().port()) + ':'; + session_id_context.append(config.address.rbegin(), config.address.rend()); + SSL_CTX_set_session_id_context(context.native_handle(), reinterpret_cast(session_id_context.data()), + std::min(session_id_context.size(), SSL_MAX_SSL_SESSION_ID_LENGTH)); + } + } + + void accept() override { + std::shared_ptr connection(new Connection(handler_runner, config.timeout_idle, *io_service, context)); + + acceptor->async_accept(connection->socket->lowest_layer(), [this, connection](const error_code &ec) { + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + // Immediately start accepting a new connection (if io_service hasn't been stopped) + if(ec != error::operation_aborted) + accept(); + + if(!ec) { + asio::ip::tcp::no_delay option(true); + connection->socket->lowest_layer().set_option(option); + + connection->set_timeout(config.timeout_request); + connection->socket->async_handshake(asio::ssl::stream_base::server, [this, connection](const error_code &ec) { + auto lock = connection->handler_runner->continue_lock(); + if(!lock) + return; + connection->cancel_timeout(); + if(!ec) + read_handshake(connection); + }); + } + }); + } + }; +} // namespace SimpleWeb + +#endif /* SIMPLE_WEB_SERVER_WSS_HPP */ diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/status_code.hpp b/src/comm/ros_bridge/Simple-WebSocket-Server/status_code.hpp new file mode 100644 index 000000000..9f9ecc561 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/status_code.hpp @@ -0,0 +1,176 @@ +#ifndef SIMPLE_WEB_STATUS_CODE_HPP +#define SIMPLE_WEB_STATUS_CODE_HPP + +#include +#include +#include +#include +#include + +namespace SimpleWeb { + enum class StatusCode { + unknown = 0, + information_continue = 100, + information_switching_protocols, + information_processing, + success_ok = 200, + success_created, + success_accepted, + success_non_authoritative_information, + success_no_content, + success_reset_content, + success_partial_content, + success_multi_status, + success_already_reported, + success_im_used = 226, + redirection_multiple_choices = 300, + redirection_moved_permanently, + redirection_found, + redirection_see_other, + redirection_not_modified, + redirection_use_proxy, + redirection_switch_proxy, + redirection_temporary_redirect, + redirection_permanent_redirect, + client_error_bad_request = 400, + client_error_unauthorized, + client_error_payment_required, + client_error_forbidden, + client_error_not_found, + client_error_method_not_allowed, + client_error_not_acceptable, + client_error_proxy_authentication_required, + client_error_request_timeout, + client_error_conflict, + client_error_gone, + client_error_length_required, + client_error_precondition_failed, + client_error_payload_too_large, + client_error_uri_too_long, + client_error_unsupported_media_type, + client_error_range_not_satisfiable, + client_error_expectation_failed, + client_error_im_a_teapot, + client_error_misdirection_required = 421, + client_error_unprocessable_entity, + client_error_locked, + client_error_failed_dependency, + client_error_upgrade_required = 426, + client_error_precondition_required = 428, + client_error_too_many_requests, + client_error_request_header_fields_too_large = 431, + client_error_unavailable_for_legal_reasons = 451, + server_error_internal_server_error = 500, + server_error_not_implemented, + server_error_bad_gateway, + server_error_service_unavailable, + server_error_gateway_timeout, + server_error_http_version_not_supported, + server_error_variant_also_negotiates, + server_error_insufficient_storage, + server_error_loop_detected, + server_error_not_extended = 510, + server_error_network_authentication_required + }; + + inline const std::map &status_code_strings() { + static const std::map status_code_strings = { + {StatusCode::unknown, ""}, + {StatusCode::information_continue, "100 Continue"}, + {StatusCode::information_switching_protocols, "101 Switching Protocols"}, + {StatusCode::information_processing, "102 Processing"}, + {StatusCode::success_ok, "200 OK"}, + {StatusCode::success_created, "201 Created"}, + {StatusCode::success_accepted, "202 Accepted"}, + {StatusCode::success_non_authoritative_information, "203 Non-Authoritative Information"}, + {StatusCode::success_no_content, "204 No Content"}, + {StatusCode::success_reset_content, "205 Reset Content"}, + {StatusCode::success_partial_content, "206 Partial Content"}, + {StatusCode::success_multi_status, "207 Multi-Status"}, + {StatusCode::success_already_reported, "208 Already Reported"}, + {StatusCode::success_im_used, "226 IM Used"}, + {StatusCode::redirection_multiple_choices, "300 Multiple Choices"}, + {StatusCode::redirection_moved_permanently, "301 Moved Permanently"}, + {StatusCode::redirection_found, "302 Found"}, + {StatusCode::redirection_see_other, "303 See Other"}, + {StatusCode::redirection_not_modified, "304 Not Modified"}, + {StatusCode::redirection_use_proxy, "305 Use Proxy"}, + {StatusCode::redirection_switch_proxy, "306 Switch Proxy"}, + {StatusCode::redirection_temporary_redirect, "307 Temporary Redirect"}, + {StatusCode::redirection_permanent_redirect, "308 Permanent Redirect"}, + {StatusCode::client_error_bad_request, "400 Bad Request"}, + {StatusCode::client_error_unauthorized, "401 Unauthorized"}, + {StatusCode::client_error_payment_required, "402 Payment Required"}, + {StatusCode::client_error_forbidden, "403 Forbidden"}, + {StatusCode::client_error_not_found, "404 Not Found"}, + {StatusCode::client_error_method_not_allowed, "405 Method Not Allowed"}, + {StatusCode::client_error_not_acceptable, "406 Not Acceptable"}, + {StatusCode::client_error_proxy_authentication_required, "407 Proxy Authentication Required"}, + {StatusCode::client_error_request_timeout, "408 Request Timeout"}, + {StatusCode::client_error_conflict, "409 Conflict"}, + {StatusCode::client_error_gone, "410 Gone"}, + {StatusCode::client_error_length_required, "411 Length Required"}, + {StatusCode::client_error_precondition_failed, "412 Precondition Failed"}, + {StatusCode::client_error_payload_too_large, "413 Payload Too Large"}, + {StatusCode::client_error_uri_too_long, "414 URI Too Long"}, + {StatusCode::client_error_unsupported_media_type, "415 Unsupported Media Type"}, + {StatusCode::client_error_range_not_satisfiable, "416 Range Not Satisfiable"}, + {StatusCode::client_error_expectation_failed, "417 Expectation Failed"}, + {StatusCode::client_error_im_a_teapot, "418 I'm a teapot"}, + {StatusCode::client_error_misdirection_required, "421 Misdirected Request"}, + {StatusCode::client_error_unprocessable_entity, "422 Unprocessable Entity"}, + {StatusCode::client_error_locked, "423 Locked"}, + {StatusCode::client_error_failed_dependency, "424 Failed Dependency"}, + {StatusCode::client_error_upgrade_required, "426 Upgrade Required"}, + {StatusCode::client_error_precondition_required, "428 Precondition Required"}, + {StatusCode::client_error_too_many_requests, "429 Too Many Requests"}, + {StatusCode::client_error_request_header_fields_too_large, "431 Request Header Fields Too Large"}, + {StatusCode::client_error_unavailable_for_legal_reasons, "451 Unavailable For Legal Reasons"}, + {StatusCode::server_error_internal_server_error, "500 Internal Server Error"}, + {StatusCode::server_error_not_implemented, "501 Not Implemented"}, + {StatusCode::server_error_bad_gateway, "502 Bad Gateway"}, + {StatusCode::server_error_service_unavailable, "503 Service Unavailable"}, + {StatusCode::server_error_gateway_timeout, "504 Gateway Timeout"}, + {StatusCode::server_error_http_version_not_supported, "505 HTTP Version Not Supported"}, + {StatusCode::server_error_variant_also_negotiates, "506 Variant Also Negotiates"}, + {StatusCode::server_error_insufficient_storage, "507 Insufficient Storage"}, + {StatusCode::server_error_loop_detected, "508 Loop Detected"}, + {StatusCode::server_error_not_extended, "510 Not Extended"}, + {StatusCode::server_error_network_authentication_required, "511 Network Authentication Required"}}; + return status_code_strings; + } + + inline StatusCode status_code(const std::string &status_code_string) noexcept { + if(status_code_string.size() < 3) + return StatusCode::unknown; + + auto number = status_code_string.substr(0, 3); + if(number[0] < '0' || number[0] > '9' || number[1] < '0' || number[1] > '9' || number[2] < '0' || number[2] > '9') + return StatusCode::unknown; + + class StringToStatusCode : public std::unordered_map { + public: + StringToStatusCode() { + for(auto &status_code : status_code_strings()) + emplace(status_code.second.substr(0, 3), status_code.first); + } + }; + static StringToStatusCode string_to_status_code; + + auto pos = string_to_status_code.find(number); + if(pos == string_to_status_code.end()) + return static_cast(atoi(number.c_str())); + return pos->second; + } + + inline const std::string &status_code(StatusCode status_code_enum) noexcept { + auto pos = status_code_strings().find(status_code_enum); + if(pos == status_code_strings().end()) { + static std::string empty_string; + return empty_string; + } + return pos->second; + } +} // namespace SimpleWeb + +#endif // SIMPLE_WEB_STATUS_CODE_HPP diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/tests/CMakeLists.txt b/src/comm/ros_bridge/Simple-WebSocket-Server/tests/CMakeLists.txt new file mode 100644 index 000000000..f5b152639 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/tests/CMakeLists.txt @@ -0,0 +1,18 @@ +if(NOT MSVC) + add_compile_options(-fno-access-control) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wno-thread-safety) + endif() + + add_executable(parse_test parse_test.cpp) + target_link_libraries(parse_test simple-websocket-server) + add_test(parse_test parse_test) +endif() + +add_executable(crypto_test crypto_test.cpp) +target_link_libraries(crypto_test simple-websocket-server) +add_test(crypto_test crypto_test) + +add_executable(io_test io_test.cpp) +target_link_libraries(io_test simple-websocket-server) +add_test(io_test io_test) diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/tests/assert.hpp b/src/comm/ros_bridge/Simple-WebSocket-Server/tests/assert.hpp new file mode 100644 index 000000000..7d55ec7b5 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/tests/assert.hpp @@ -0,0 +1,9 @@ +#ifndef SIMPLE_WEB_ASSERT_HPP +#define SIMPLE_WEB_ASSERT_HPP + +#include +#include + +#define ASSERT(e) ((void)((e) ? ((void)0) : ((void)(std::cerr << "Assertion failed: (" << #e << "), function " << __func__ << ", file " << __FILE__ << ", line " << __LINE__ << ".\n"), std::abort()))) + +#endif /* SIMPLE_WEB_ASSERT_HPP */ diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/tests/crypto_test.cpp b/src/comm/ros_bridge/Simple-WebSocket-Server/tests/crypto_test.cpp new file mode 100644 index 000000000..9775a68cd --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/tests/crypto_test.cpp @@ -0,0 +1,73 @@ +#include "assert.hpp" +#include "crypto.hpp" +#include + +using namespace std; +using namespace SimpleWeb; + +const vector> base64_string_tests = { + {"", ""}, + {"f", "Zg=="}, + {"fo", "Zm8="}, + {"foo", "Zm9v"}, + {"foob", "Zm9vYg=="}, + {"fooba", "Zm9vYmE="}, + {"foobar", "Zm9vYmFy"}, + {"The itsy bitsy spider climbed up the waterspout.\r\nDown came the rain\r\nand washed the spider out.\r\nOut came the sun\r\nand dried up all the rain\r\nand the itsy bitsy spider climbed up the spout again.", + "VGhlIGl0c3kgYml0c3kgc3BpZGVyIGNsaW1iZWQgdXAgdGhlIHdhdGVyc3BvdXQuDQpEb3duIGNhbWUgdGhlIHJhaW4NCmFuZCB3YXNoZWQgdGhlIHNwaWRlciBvdXQuDQpPdXQgY2FtZSB0aGUgc3VuDQphbmQgZHJpZWQgdXAgYWxsIHRoZSByYWluDQphbmQgdGhlIGl0c3kgYml0c3kgc3BpZGVyIGNsaW1iZWQgdXAgdGhlIHNwb3V0IGFnYWluLg=="}}; + +const vector> md5_string_tests = { + {"", "d41d8cd98f00b204e9800998ecf8427e"}, + {"The quick brown fox jumps over the lazy dog", "9e107d9d372bb6826bd81d3542a419d6"}}; + +const vector> sha1_string_tests = { + {"", "da39a3ee5e6b4b0d3255bfef95601890afd80709"}, + {"The quick brown fox jumps over the lazy dog", "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"}}; + +const vector> sha256_string_tests = { + {"", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, + {"The quick brown fox jumps over the lazy dog", "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"}}; + +const vector> sha512_string_tests = { + {"", "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"}, + {"The quick brown fox jumps over the lazy dog", "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6"}}; + +int main() { + for(auto &string_test : base64_string_tests) { + ASSERT(Crypto::Base64::encode(string_test.first) == string_test.second); + ASSERT(Crypto::Base64::decode(string_test.second) == string_test.first); + } + + for(auto &string_test : md5_string_tests) { + ASSERT(Crypto::to_hex_string(Crypto::md5(string_test.first)) == string_test.second); + stringstream ss(string_test.first); + ASSERT(Crypto::to_hex_string(Crypto::md5(ss)) == string_test.second); + } + + for(auto &string_test : sha1_string_tests) { + ASSERT(Crypto::to_hex_string(Crypto::sha1(string_test.first)) == string_test.second); + stringstream ss(string_test.first); + ASSERT(Crypto::to_hex_string(Crypto::sha1(ss)) == string_test.second); + } + + for(auto &string_test : sha256_string_tests) { + ASSERT(Crypto::to_hex_string(Crypto::sha256(string_test.first)) == string_test.second); + stringstream ss(string_test.first); + ASSERT(Crypto::to_hex_string(Crypto::sha256(ss)) == string_test.second); + } + + for(auto &string_test : sha512_string_tests) { + ASSERT(Crypto::to_hex_string(Crypto::sha512(string_test.first)) == string_test.second); + stringstream ss(string_test.first); + ASSERT(Crypto::to_hex_string(Crypto::sha512(ss)) == string_test.second); + } + + //Testing iterations + ASSERT(Crypto::to_hex_string(Crypto::sha1("Test", 1)) == "640ab2bae07bedc4c163f679a746f7ab7fb5d1fa"); + ASSERT(Crypto::to_hex_string(Crypto::sha1("Test", 2)) == "af31c6cbdecd88726d0a9b3798c71ef41f1624d5"); + stringstream ss("Test"); + ASSERT(Crypto::to_hex_string(Crypto::sha1(ss, 2)) == "af31c6cbdecd88726d0a9b3798c71ef41f1624d5"); + + ASSERT(Crypto::to_hex_string(Crypto::pbkdf2("Password", "Salt", 4096, 128 / 8)) == "f66df50f8aaa11e4d9721e1312ff2e66"); + ASSERT(Crypto::to_hex_string(Crypto::pbkdf2("Password", "Salt", 8192, 512 / 8)) == "a941ccbc34d1ee8ebbd1d34824a419c3dc4eac9cbc7c36ae6c7ca8725e2b618a6ad22241e787af937b0960cf85aa8ea3a258f243e05d3cc9b08af5dd93be046c"); +} diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/tests/io_test.cpp b/src/comm/ros_bridge/Simple-WebSocket-Server/tests/io_test.cpp new file mode 100644 index 000000000..2b00b902c --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/tests/io_test.cpp @@ -0,0 +1,289 @@ +#include "assert.hpp" +#include "client_ws.hpp" +#include "server_ws.hpp" + +using namespace std; + +typedef SimpleWeb::SocketServer WsServer; +typedef SimpleWeb::SocketClient WsClient; + +int main() { + WsServer server; + server.config.port = 8080; + server.config.thread_pool_size = 4; + + auto &echo = server.endpoint["^/echo/?$"]; + + atomic server_callback_count(0); + + echo.on_message = [&server_callback_count](shared_ptr connection, shared_ptr in_message) { + auto in_message_str = in_message->string(); + ASSERT(in_message_str == "Hello"); + + ++server_callback_count; + connection->send(in_message_str, [](const SimpleWeb::error_code &ec) { + if(ec) { + cerr << ec.message() << endl; + ASSERT(false); + } + }); + }; + + echo.on_open = [&server_callback_count](shared_ptr connection) { + ++server_callback_count; + ASSERT(!connection->remote_endpoint_address().empty()); + ASSERT(connection->remote_endpoint_port() > 0); + }; + + echo.on_close = [&server_callback_count](shared_ptr /*connection*/, int /*status*/, const string & /*reason*/) { + ++server_callback_count; + }; + + echo.on_error = [](shared_ptr /*connection*/, const SimpleWeb::error_code &ec) { + cerr << ec.message() << endl; + ASSERT(false); + }; + + auto &echo_thrice = server.endpoint["^/echo_thrice/?$"]; + echo_thrice.on_message = [](shared_ptr connection, shared_ptr in_message) { + auto out_message = make_shared(); + *out_message << in_message->string(); + + connection->send(out_message, [connection, out_message](const SimpleWeb::error_code &ec) { + if(!ec) + connection->send(out_message); + }); + connection->send(out_message); + }; + + auto &fragmented_message = server.endpoint["^/fragmented_message/?$"]; + fragmented_message.on_message = [&server_callback_count](shared_ptr connection, shared_ptr in_message) { + ++server_callback_count; + ASSERT(in_message->string() == "fragmented message"); + + connection->send("fragmented", nullptr, 1); + connection->send(" ", nullptr, 0); + connection->send("message", nullptr, 128); + }; + + thread server_thread([&server]() { + server.start(); + }); + + this_thread::sleep_for(chrono::seconds(1)); + + // test stop + server.stop(); + server_thread.join(); + + server_thread = thread([&server]() { + server.start(); + }); + + this_thread::sleep_for(chrono::seconds(1)); + + for(size_t i = 0; i < 400; ++i) { + WsClient client("localhost:8080/echo"); + + atomic client_callback_count(0); + atomic closed(false); + + client.on_message = [&](shared_ptr connection, shared_ptr in_message) { + ASSERT(in_message->string() == "Hello"); + + ++client_callback_count; + + ASSERT(!closed); + + connection->send_close(1000); + }; + + client.on_open = [&](shared_ptr connection) { + ++client_callback_count; + + ASSERT(!closed); + + connection->send("Hello"); + }; + + client.on_close = [&](shared_ptr /*connection*/, int /*status*/, const string & /*reason*/) { + ++client_callback_count; + ASSERT(!closed); + closed = true; + }; + + client.on_error = [](shared_ptr /*connection*/, const SimpleWeb::error_code &ec) { + cerr << ec.message() << endl; + ASSERT(false); + }; + + thread client_thread([&client]() { + client.start(); + }); + + while(!closed) + this_thread::sleep_for(chrono::milliseconds(5)); + + client.stop(); + client_thread.join(); + + ASSERT(client_callback_count == 3); + } + ASSERT(server_callback_count == 1200); + + for(size_t i = 0; i < 400; ++i) { + WsClient client("localhost:8080/echo_thrice"); + + atomic client_callback_count(0); + atomic closed(false); + + client.on_message = [&](shared_ptr connection, shared_ptr in_message) { + ASSERT(in_message->string() == "Hello"); + + ++client_callback_count; + + ASSERT(!closed); + + if(client_callback_count == 4) + connection->send_close(1000); + }; + + client.on_open = [&](shared_ptr connection) { + ++client_callback_count; + + ASSERT(!closed); + + connection->send("Hello"); + }; + + client.on_close = [&](shared_ptr /*connection*/, int /*status*/, const string & /*reason*/) { + ++client_callback_count; + ASSERT(!closed); + closed = true; + }; + + client.on_error = [](shared_ptr /*connection*/, const SimpleWeb::error_code &ec) { + cerr << ec.message() << endl; + ASSERT(false); + }; + + thread client_thread([&client]() { + client.start(); + }); + + while(!closed) + this_thread::sleep_for(chrono::milliseconds(5)); + + client.stop(); + client_thread.join(); + + ASSERT(client_callback_count == 5); + } + + { + WsClient client("localhost:8080/echo"); + + server_callback_count = 0; + atomic client_callback_count(0); + atomic closed(false); + + client.on_message = [&](shared_ptr connection, shared_ptr in_message) { + ASSERT(in_message->string() == "Hello"); + + ++client_callback_count; + + ASSERT(!closed); + + if(client_callback_count == 201) + connection->send_close(1000); + }; + + client.on_open = [&](shared_ptr connection) { + ++client_callback_count; + + ASSERT(!closed); + + for(size_t i = 0; i < 200; ++i) { + auto send_stream = make_shared(); + *send_stream << "Hello"; + connection->send(send_stream); + } + }; + + client.on_close = [&](shared_ptr /*connection*/, int /*status*/, const string & /*reason*/) { + ++client_callback_count; + ASSERT(!closed); + closed = true; + }; + + client.on_error = [](shared_ptr /*connection*/, const SimpleWeb::error_code &ec) { + cerr << ec.message() << endl; + ASSERT(false); + }; + + thread client_thread([&client]() { + client.start(); + }); + + while(!closed) + this_thread::sleep_for(chrono::milliseconds(5)); + + client.stop(); + client_thread.join(); + + ASSERT(client_callback_count == 202); + ASSERT(server_callback_count == 202); + } + + { + WsClient client("localhost:8080/fragmented_message"); + + server_callback_count = 0; + atomic client_callback_count(0); + atomic closed(false); + + client.on_message = [&](shared_ptr connection, shared_ptr in_message) { + ASSERT(in_message->string() == "fragmented message"); + + ++client_callback_count; + + connection->send_close(1000); + }; + + client.on_open = [&](shared_ptr connection) { + ++client_callback_count; + + ASSERT(!closed); + + connection->send("fragmented", nullptr, 1); + connection->send(" ", nullptr, 0); + connection->send("message", nullptr, 128); + }; + + client.on_close = [&](shared_ptr /*connection*/, int /*status*/, const string & /*reason*/) { + ASSERT(!closed); + closed = true; + }; + + client.on_error = [](shared_ptr /*connection*/, const SimpleWeb::error_code &ec) { + cerr << ec.message() << endl; + ASSERT(false); + }; + + thread client_thread([&client]() { + client.start(); + }); + + while(!closed) + this_thread::sleep_for(chrono::milliseconds(5)); + + client.stop(); + client_thread.join(); + + ASSERT(client_callback_count == 2); + ASSERT(server_callback_count == 1); + } + + server.stop(); + server_thread.join(); +} diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/tests/parse_test.cpp b/src/comm/ros_bridge/Simple-WebSocket-Server/tests/parse_test.cpp new file mode 100644 index 000000000..3345cdf31 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/tests/parse_test.cpp @@ -0,0 +1,153 @@ +#include "assert.hpp" +#include "client_ws.hpp" +#include "server_ws.hpp" +#include + +using namespace std; +using namespace SimpleWeb; + +class SocketServerTest : public SocketServerBase { +public: + SocketServerTest() : SocketServerBase::SocketServerBase(8080) {} + + void accept() {} + + void parse_request_test() { + std::shared_ptr connection(new Connection(handler_runner, 0, *io_service)); + + ostream ss(&connection->read_buffer); + ss << "GET /test/ HTTP/1.1\r\n"; + ss << "TestHeader: test\r\n"; + ss << "TestHeader2:test2\r\n"; + ss << "TestHeader3:test3a\r\n"; + ss << "TestHeader3:test3b\r\n"; + ss << "\r\n"; + + std::istream stream(&connection->read_buffer); + ASSERT(RequestMessage::parse(stream, connection->method, connection->path, connection->query_string, connection->http_version, connection->header)); + + ASSERT(connection->method == "GET"); + ASSERT(connection->path == "/test/"); + ASSERT(connection->http_version == "1.1"); + + ASSERT(connection->header.size() == 4); + auto header_it = connection->header.find("TestHeader"); + ASSERT(header_it != connection->header.end() && header_it->second == "test"); + header_it = connection->header.find("TestHeader2"); + ASSERT(header_it != connection->header.end() && header_it->second == "test2"); + + header_it = connection->header.find("testheader"); + ASSERT(header_it != connection->header.end() && header_it->second == "test"); + header_it = connection->header.find("testheader2"); + ASSERT(header_it != connection->header.end() && header_it->second == "test2"); + + auto range = connection->header.equal_range("testheader3"); + auto first = range.first; + auto second = first; + ++second; + ASSERT(range.first != connection->header.end() && range.second != connection->header.end() && + ((first->second == "test3a" && second->second == "test3b") || + (first->second == "test3b" && second->second == "test3a"))); + } +}; + +class SocketClientTest : public SocketClientBase { +public: + SocketClientTest(const std::string &server_port_path) : SocketClientBase::SocketClientBase(server_port_path, 80) {} + + void connect() {} + + void constructor_parse_test1() { + ASSERT(path == "/test"); + ASSERT(host == "test.org"); + ASSERT(port == 8080); + } + + void constructor_parse_test2() { + ASSERT(path == "/test"); + ASSERT(host == "test.org"); + ASSERT(port == 80); + } + + void constructor_parse_test3() { + ASSERT(path == "/"); + ASSERT(host == "test.org"); + ASSERT(port == 80); + } + + void constructor_parse_test4() { + ASSERT(path == "/"); + ASSERT(host == "test.org"); + ASSERT(port == 8080); + } + + void parse_response_header_test() { + auto connection = std::shared_ptr(new Connection(handler_runner, config.timeout_idle, *io_service)); + connection->in_message = std::shared_ptr(new InMessage()); + + ostream stream(&connection->in_message->streambuf); + stream << "HTTP/1.1 200 OK\r\n"; + stream << "TestHeader: test\r\n"; + stream << "TestHeader2:test2\r\n"; + stream << "TestHeader3:test3a\r\n"; + stream << "TestHeader3:test3b\r\n"; + stream << "\r\n"; + + ASSERT(ResponseMessage::parse(*connection->in_message, connection->http_version, connection->status_code, connection->header)); + + ASSERT(connection->header.size() == 4); + auto header_it = connection->header.find("TestHeader"); + ASSERT(header_it != connection->header.end() && header_it->second == "test"); + header_it = connection->header.find("TestHeader2"); + ASSERT(header_it != connection->header.end() && header_it->second == "test2"); + + header_it = connection->header.find("testheader"); + ASSERT(header_it != connection->header.end() && header_it->second == "test"); + header_it = connection->header.find("testheader2"); + ASSERT(header_it != connection->header.end() && header_it->second == "test2"); + + auto range = connection->header.equal_range("testheader3"); + auto first = range.first; + auto second = first; + ++second; + ASSERT(range.first != connection->header.end() && range.second != connection->header.end() && + ((first->second == "test3a" && second->second == "test3b") || + (first->second == "test3b" && second->second == "test3a"))); + + connection.reset(); + } +}; + +int main() { + ASSERT(case_insensitive_equal("Test", "tesT")); + ASSERT(case_insensitive_equal("tesT", "test")); + ASSERT(!case_insensitive_equal("test", "tseT")); + CaseInsensitiveEqual equal; + ASSERT(equal("Test", "tesT")); + ASSERT(equal("tesT", "test")); + ASSERT(!equal("test", "tset")); + CaseInsensitiveHash hash; + ASSERT(hash("Test") == hash("tesT")); + ASSERT(hash("tesT") == hash("test")); + ASSERT(hash("test") != hash("tset")); + + SocketServerTest serverTest; + serverTest.io_service = std::make_shared(); + + serverTest.parse_request_test(); + + SocketClientTest clientTest("test.org:8080/test"); + clientTest.constructor_parse_test1(); + + SocketClientTest clientTest2("test.org/test"); + clientTest2.constructor_parse_test2(); + + SocketClientTest clientTest3("test.org"); + clientTest3.constructor_parse_test3(); + + SocketClientTest clientTest4("test.org:8080"); + clientTest4.io_service = std::make_shared(); + clientTest4.constructor_parse_test4(); + + clientTest4.parse_response_header_test(); +} diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/utility.hpp b/src/comm/ros_bridge/Simple-WebSocket-Server/utility.hpp new file mode 100644 index 000000000..98808226a --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/utility.hpp @@ -0,0 +1,363 @@ +#ifndef SIMPLE_WEB_UTILITY_HPP +#define SIMPLE_WEB_UTILITY_HPP + +#include "status_code.hpp" +#include +#include +#include +#include +#include +#include + +#if __cplusplus > 201402L || _MSVC_LANG > 201402L +#include +namespace SimpleWeb { + using string_view = std::string_view; +} +#elif !defined(USE_STANDALONE_ASIO) +#include +namespace SimpleWeb { + using string_view = boost::string_ref; +} +#else +namespace SimpleWeb { + using string_view = const std::string &; +} +#endif + +namespace SimpleWeb { + inline bool case_insensitive_equal(const std::string &str1, const std::string &str2) noexcept { + return str1.size() == str2.size() && + std::equal(str1.begin(), str1.end(), str2.begin(), [](char a, char b) { + return tolower(a) == tolower(b); + }); + } + class CaseInsensitiveEqual { + public: + bool operator()(const std::string &str1, const std::string &str2) const noexcept { + return case_insensitive_equal(str1, str2); + } + }; + // Based on https://stackoverflow.com/questions/2590677/how-do-i-combine-hash-values-in-c0x/2595226#2595226 + class CaseInsensitiveHash { + public: + std::size_t operator()(const std::string &str) const noexcept { + std::size_t h = 0; + std::hash hash; + for(auto c : str) + h ^= hash(tolower(c)) + 0x9e3779b9 + (h << 6) + (h >> 2); + return h; + } + }; + + using CaseInsensitiveMultimap = std::unordered_multimap; + + /// Percent encoding and decoding + class Percent { + public: + /// Returns percent-encoded string + static std::string encode(const std::string &value) noexcept { + static auto hex_chars = "0123456789ABCDEF"; + + std::string result; + result.reserve(value.size()); // Minimum size of result + + for(auto &chr : value) { + if(!((chr >= '0' && chr <= '9') || (chr >= 'A' && chr <= 'Z') || (chr >= 'a' && chr <= 'z') || chr == '-' || chr == '.' || chr == '_' || chr == '~')) + result += std::string("%") + hex_chars[static_cast(chr) >> 4] + hex_chars[static_cast(chr) & 15]; + else + result += chr; + } + + return result; + } + + /// Returns percent-decoded string + static std::string decode(const std::string &value) noexcept { + std::string result; + result.reserve(value.size() / 3 + (value.size() % 3)); // Minimum size of result + + for(std::size_t i = 0; i < value.size(); ++i) { + auto &chr = value[i]; + if(chr == '%' && i + 2 < value.size()) { + auto hex = value.substr(i + 1, 2); + auto decoded_chr = static_cast(std::strtol(hex.c_str(), nullptr, 16)); + result += decoded_chr; + i += 2; + } + else if(chr == '+') + result += ' '; + else + result += chr; + } + + return result; + } + }; + + /// Query string creation and parsing + class QueryString { + public: + /// Returns query string created from given field names and values + static std::string create(const CaseInsensitiveMultimap &fields) noexcept { + std::string result; + + bool first = true; + for(auto &field : fields) { + result += (!first ? "&" : "") + field.first + '=' + Percent::encode(field.second); + first = false; + } + + return result; + } + + /// Returns query keys with percent-decoded values. + static CaseInsensitiveMultimap parse(const std::string &query_string) noexcept { + CaseInsensitiveMultimap result; + + if(query_string.empty()) + return result; + + std::size_t name_pos = 0; + auto name_end_pos = std::string::npos; + auto value_pos = std::string::npos; + for(std::size_t c = 0; c < query_string.size(); ++c) { + if(query_string[c] == '&') { + auto name = query_string.substr(name_pos, (name_end_pos == std::string::npos ? c : name_end_pos) - name_pos); + if(!name.empty()) { + auto value = value_pos == std::string::npos ? std::string() : query_string.substr(value_pos, c - value_pos); + result.emplace(std::move(name), Percent::decode(value)); + } + name_pos = c + 1; + name_end_pos = std::string::npos; + value_pos = std::string::npos; + } + else if(query_string[c] == '=') { + name_end_pos = c; + value_pos = c + 1; + } + } + if(name_pos < query_string.size()) { + auto name = query_string.substr(name_pos, name_end_pos - name_pos); + if(!name.empty()) { + auto value = value_pos >= query_string.size() ? std::string() : query_string.substr(value_pos); + result.emplace(std::move(name), Percent::decode(value)); + } + } + + return result; + } + }; + + class HttpHeader { + public: + /// Parse header fields + static CaseInsensitiveMultimap parse(std::istream &stream) noexcept { + CaseInsensitiveMultimap result; + std::string line; + std::size_t param_end; + while(getline(stream, line) && (param_end = line.find(':')) != std::string::npos) { + std::size_t value_start = param_end + 1; + while(value_start + 1 < line.size() && line[value_start] == ' ') + ++value_start; + if(value_start < line.size()) + result.emplace(line.substr(0, param_end), line.substr(value_start, line.size() - value_start - (line.back() == '\r' ? 1 : 0))); + } + return result; + } + + class FieldValue { + public: + class SemicolonSeparatedAttributes { + public: + /// Parse Set-Cookie or Content-Disposition header field value. Attribute values are percent-decoded. + static CaseInsensitiveMultimap parse(const std::string &str) { + CaseInsensitiveMultimap result; + + std::size_t name_start_pos = std::string::npos; + std::size_t name_end_pos = std::string::npos; + std::size_t value_start_pos = std::string::npos; + for(std::size_t c = 0; c < str.size(); ++c) { + if(name_start_pos == std::string::npos) { + if(str[c] != ' ' && str[c] != ';') + name_start_pos = c; + } + else { + if(name_end_pos == std::string::npos) { + if(str[c] == ';') { + result.emplace(str.substr(name_start_pos, c - name_start_pos), std::string()); + name_start_pos = std::string::npos; + } + else if(str[c] == '=') + name_end_pos = c; + } + else { + if(value_start_pos == std::string::npos) { + if(str[c] == '"' && c + 1 < str.size()) + value_start_pos = c + 1; + else + value_start_pos = c; + } + else if(str[c] == '"' || str[c] == ';') { + result.emplace(str.substr(name_start_pos, name_end_pos - name_start_pos), Percent::decode(str.substr(value_start_pos, c - value_start_pos))); + name_start_pos = std::string::npos; + name_end_pos = std::string::npos; + value_start_pos = std::string::npos; + } + } + } + } + if(name_start_pos != std::string::npos) { + if(name_end_pos == std::string::npos) + result.emplace(str.substr(name_start_pos), std::string()); + else if(value_start_pos != std::string::npos) { + if(str.back() == '"') + result.emplace(str.substr(name_start_pos, name_end_pos - name_start_pos), Percent::decode(str.substr(value_start_pos, str.size() - 1))); + else + result.emplace(str.substr(name_start_pos, name_end_pos - name_start_pos), Percent::decode(str.substr(value_start_pos))); + } + } + + return result; + } + }; + }; + }; // namespace SimpleWeb + + class RequestMessage { + public: + /// Parse request line and header fields + static bool parse(std::istream &stream, std::string &method, std::string &path, std::string &query_string, std::string &version, CaseInsensitiveMultimap &header) noexcept { + std::string line; + std::size_t method_end; + if(getline(stream, line) && (method_end = line.find(' ')) != std::string::npos) { + method = line.substr(0, method_end); + + std::size_t query_start = std::string::npos; + std::size_t path_and_query_string_end = std::string::npos; + for(std::size_t i = method_end + 1; i < line.size(); ++i) { + if(line[i] == '?' && (i + 1) < line.size()) + query_start = i + 1; + else if(line[i] == ' ') { + path_and_query_string_end = i; + break; + } + } + if(path_and_query_string_end != std::string::npos) { + if(query_start != std::string::npos) { + path = line.substr(method_end + 1, query_start - method_end - 2); + query_string = line.substr(query_start, path_and_query_string_end - query_start); + } + else + path = line.substr(method_end + 1, path_and_query_string_end - method_end - 1); + + std::size_t protocol_end; + if((protocol_end = line.find('/', path_and_query_string_end + 1)) != std::string::npos) { + if(line.compare(path_and_query_string_end + 1, protocol_end - path_and_query_string_end - 1, "HTTP") != 0) + return false; + version = line.substr(protocol_end + 1, line.size() - protocol_end - 2); + } + else + return false; + + header = HttpHeader::parse(stream); + } + else + return false; + } + else + return false; + return true; + } + }; + + class ResponseMessage { + public: + /// Parse status line and header fields + static bool parse(std::istream &stream, std::string &version, std::string &status_code, CaseInsensitiveMultimap &header) noexcept { + std::string line; + std::size_t version_end; + if(getline(stream, line) && (version_end = line.find(' ')) != std::string::npos) { + if(5 < line.size()) + version = line.substr(5, version_end - 5); + else + return false; + if((version_end + 1) < line.size()) + status_code = line.substr(version_end + 1, line.size() - (version_end + 1) - (line.back() == '\r' ? 1 : 0)); + else + return false; + + header = HttpHeader::parse(stream); + } + else + return false; + return true; + } + }; +} // namespace SimpleWeb + +#ifdef __SSE2__ +#include +namespace SimpleWeb { + inline void spin_loop_pause() noexcept { _mm_pause(); } +} // namespace SimpleWeb +// TODO: need verification that the following checks are correct: +#elif defined(_MSC_VER) && _MSC_VER >= 1800 && (defined(_M_X64) || defined(_M_IX86)) +#include +namespace SimpleWeb { + inline void spin_loop_pause() noexcept { _mm_pause(); } +} // namespace SimpleWeb +#else +namespace SimpleWeb { + inline void spin_loop_pause() noexcept {} +} // namespace SimpleWeb +#endif + +namespace SimpleWeb { + /// Makes it possible to for instance cancel Asio handlers without stopping asio::io_service + class ScopeRunner { + /// Scope count that is set to -1 if scopes are to be canceled + std::atomic count; + + public: + class SharedLock { + friend class ScopeRunner; + std::atomic &count; + SharedLock(std::atomic &count) noexcept : count(count) {} + SharedLock &operator=(const SharedLock &) = delete; + SharedLock(const SharedLock &) = delete; + + public: + ~SharedLock() noexcept { + count.fetch_sub(1); + } + }; + + ScopeRunner() noexcept : count(0) {} + + /// Returns nullptr if scope should be exited, or a shared lock otherwise + std::unique_ptr continue_lock() noexcept { + long expected = count; + while(expected >= 0 && !count.compare_exchange_weak(expected, expected + 1)) + spin_loop_pause(); + + if(expected < 0) + return nullptr; + else + return std::unique_ptr(new SharedLock(count)); + } + + /// Blocks until all shared locks are released, then prevents future shared locks + void stop() noexcept { + long expected = 0; + while(!count.compare_exchange_weak(expected, -1)) { + if(expected < 0) + return; + expected = 0; + spin_loop_pause(); + } + } + }; +} // namespace SimpleWeb + +#endif // SIMPLE_WEB_UTILITY_HPP diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/ws_examples.cpp b/src/comm/ros_bridge/Simple-WebSocket-Server/ws_examples.cpp new file mode 100644 index 000000000..b85804868 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/ws_examples.cpp @@ -0,0 +1,145 @@ +#include "client_ws.hpp" +#include "server_ws.hpp" + +using namespace std; + +using WsServer = SimpleWeb::SocketServer; +using WsClient = SimpleWeb::SocketClient; + +int main() { + // WebSocket (WS)-server at port 8080 using 1 thread + WsServer server; + server.config.port = 8080; + + // Example 1: echo WebSocket endpoint + // Added debug messages for example use of the callbacks + // Test with the following JavaScript: + // var ws=new WebSocket("ws://localhost:8080/echo"); + // ws.onmessage=function(evt){console.log(evt.data);}; + // ws.send("test"); + auto &echo = server.endpoint["^/echo/?$"]; + + echo.on_message = [](shared_ptr connection, shared_ptr in_message) { + auto out_message = in_message->string(); + + cout << "Server: Message received: \"" << out_message << "\" from " << connection.get() << endl; + + cout << "Server: Sending message \"" << out_message << "\" to " << connection.get() << endl; + + // connection->send is an asynchronous function + connection->send(out_message, [](const SimpleWeb::error_code &ec) { + if(ec) { + cout << "Server: Error sending message. " << + // See http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference.html, Error Codes for error code meanings + "Error: " << ec << ", error message: " << ec.message() << endl; + } + }); + + // Alternatively use streams: + // auto out_message = make_shared(); + // *out_message << in_message->string(); + // connection->send(out_message); + }; + + echo.on_open = [](shared_ptr connection) { + cout << "Server: Opened connection " << connection.get() << endl; + }; + + // See RFC 6455 7.4.1. for status codes + echo.on_close = [](shared_ptr connection, int status, const string & /*reason*/) { + cout << "Server: Closed connection " << connection.get() << " with status code " << status << endl; + }; + + // Can modify handshake response headers here if needed + echo.on_handshake = [](shared_ptr /*connection*/, SimpleWeb::CaseInsensitiveMultimap & /*response_header*/) { + return SimpleWeb::StatusCode::information_switching_protocols; // Upgrade to websocket + }; + + // See http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference.html, Error Codes for error code meanings + echo.on_error = [](shared_ptr connection, const SimpleWeb::error_code &ec) { + cout << "Server: Error in connection " << connection.get() << ". " + << "Error: " << ec << ", error message: " << ec.message() << endl; + }; + + // Example 2: Echo thrice + // Demonstrating queuing of messages by sending a received message three times back to the client. + // Concurrent send operations are automatically queued by the library. + // Test with the following JavaScript: + // var ws=new WebSocket("ws://localhost:8080/echo_thrice"); + // ws.onmessage=function(evt){console.log(evt.data);}; + // ws.send("test"); + auto &echo_thrice = server.endpoint["^/echo_thrice/?$"]; + echo_thrice.on_message = [](shared_ptr connection, shared_ptr in_message) { + auto out_message = make_shared(in_message->string()); + + connection->send(*out_message, [connection, out_message](const SimpleWeb::error_code &ec) { + if(!ec) + connection->send(*out_message); // Sent after the first send operation is finished + }); + connection->send(*out_message); // Most likely queued. Sent after the first send operation is finished. + }; + + // Example 3: Echo to all WebSocket endpoints + // Sending received messages to all connected clients + // Test with the following JavaScript on more than one browser windows: + // var ws=new WebSocket("ws://localhost:8080/echo_all"); + // ws.onmessage=function(evt){console.log(evt.data);}; + // ws.send("test"); + auto &echo_all = server.endpoint["^/echo_all/?$"]; + echo_all.on_message = [&server](shared_ptr /*connection*/, shared_ptr in_message) { + auto out_message = in_message->string(); + + // echo_all.get_connections() can also be used to solely receive connections on this endpoint + for(auto &a_connection : server.get_connections()) + a_connection->send(out_message); + }; + + thread server_thread([&server]() { + // Start WS-server + server.start(); + }); + + // Wait for server to start so that the client can connect + this_thread::sleep_for(chrono::seconds(1)); + + // Example 4: Client communication with server + // Possible output: + // Server: Opened connection 0x7fcf21600380 + // Client: Opened connection + // Client: Sending message: "Hello" + // Server: Message received: "Hello" from 0x7fcf21600380 + // Server: Sending message "Hello" to 0x7fcf21600380 + // Client: Message received: "Hello" + // Client: Sending close connection + // Server: Closed connection 0x7fcf21600380 with status code 1000 + // Client: Closed connection with status code 1000 + WsClient client("localhost:8080/echo"); + client.on_message = [](shared_ptr connection, shared_ptr in_message) { + cout << "Client: Message received: \"" << in_message->string() << "\"" << endl; + + cout << "Client: Sending close connection" << endl; + connection->send_close(1000); + }; + + client.on_open = [](shared_ptr connection) { + cout << "Client: Opened connection" << endl; + + string out_message("Hello"); + cout << "Client: Sending message: \"" << out_message << "\"" << endl; + + connection->send(out_message); + }; + + client.on_close = [](shared_ptr /*connection*/, int status, const string & /*reason*/) { + cout << "Client: Closed connection with status code " << status << endl; + }; + + // See http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference.html, Error Codes for error code meanings + client.on_error = [](shared_ptr /*connection*/, const SimpleWeb::error_code &ec) { + cout << "Client: Error: " << ec << ", error message: " << ec.message() << endl; + }; + + client.start(); + + server_thread.join(); +} diff --git a/src/comm/ros_bridge/Simple-WebSocket-Server/wss_examples.cpp b/src/comm/ros_bridge/Simple-WebSocket-Server/wss_examples.cpp new file mode 100644 index 000000000..28995c9f2 --- /dev/null +++ b/src/comm/ros_bridge/Simple-WebSocket-Server/wss_examples.cpp @@ -0,0 +1,146 @@ +#include "client_wss.hpp" +#include "server_wss.hpp" + +using namespace std; + +using WssServer = SimpleWeb::SocketServer; +using WssClient = SimpleWeb::SocketClient; + +int main() { + // WebSocket Secure (WSS)-server at port 8080 using 1 thread + WssServer server("server.crt", "server.key"); + server.config.port = 8080; + + // Example 1: echo WebSocket Secure endpoint + // Added debug messages for example use of the callbacks + // Test with the following JavaScript: + // var wss=new WebSocket("wss://localhost:8080/echo"); + // wss.onmessage=function(evt){console.log(evt.data);}; + // wss.send("test"); + auto &echo = server.endpoint["^/echo/?$"]; + + echo.on_message = [](shared_ptr connection, shared_ptr in_message) { + auto out_message = in_message->string(); + + cout << "Server: Message received: \"" << out_message << "\" from " << connection.get() << endl; + + cout << "Server: Sending message \"" << out_message << "\" to " << connection.get() << endl; + + // connection->send is an asynchronous function + connection->send(out_message, [](const SimpleWeb::error_code &ec) { + if(ec) { + cout << "Server: Error sending message. " << + // See http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference.html, Error Codes for error code meanings + "Error: " << ec << ", error message: " << ec.message() << endl; + } + }); + + // Alternatively use streams: + // auto out_message = make_shared(); + // *out_message << in_message->string(); + // connection->send(out_message); + }; + + echo.on_open = [](shared_ptr connection) { + cout << "Server: Opened connection " << connection.get() << endl; + }; + + // See RFC 6455 7.4.1. for status codes + echo.on_close = [](shared_ptr connection, int status, const string & /*reason*/) { + cout << "Server: Closed connection " << connection.get() << " with status code " << status << endl; + }; + + // Can modify handshake response header here if needed + echo.on_handshake = [](shared_ptr /*connection*/, SimpleWeb::CaseInsensitiveMultimap & /*response_header*/) { + return SimpleWeb::StatusCode::information_switching_protocols; // Upgrade to websocket + }; + + // See http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference.html, Error Codes for error code meanings + echo.on_error = [](shared_ptr connection, const SimpleWeb::error_code &ec) { + cout << "Server: Error in connection " << connection.get() << ". " + << "Error: " << ec << ", error message: " << ec.message() << endl; + }; + + // Example 2: Echo thrice + // Demonstrating queuing of messages by sending a received message three times back to the client. + // Concurrent send operations are automatically queued by the library. + // Test with the following JavaScript: + // var wss=new WebSocket("wss://localhost:8080/echo_thrice"); + // wss.onmessage=function(evt){console.log(evt.data);}; + // wss.send("test"); + auto &echo_thrice = server.endpoint["^/echo_thrice/?$"]; + echo_thrice.on_message = [](shared_ptr connection, shared_ptr in_message) { + auto out_message = make_shared(in_message->string()); + + connection->send(*out_message, [connection, out_message](const SimpleWeb::error_code &ec) { + if(!ec) + connection->send(*out_message); // Sent after the first send operation is finished + }); + connection->send(*out_message); // Most likely queued. Sent after the first send operation is finished. + }; + + // Example 3: Echo to all WebSocket Secure endpoints + // Sending received messages to all connected clients + // Test with the following JavaScript on more than one browser windows: + // var wss=new WebSocket("wss://localhost:8080/echo_all"); + // wss.onmessage=function(evt){console.log(evt.data);}; + // wss.send("test"); + auto &echo_all = server.endpoint["^/echo_all/?$"]; + echo_all.on_message = [&server](shared_ptr /*connection*/, shared_ptr in_message) { + auto out_message = in_message->string(); + + // echo_all.get_connections() can also be used to solely receive connections on this endpoint + for(auto &a_connection : server.get_connections()) + a_connection->send(out_message); + }; + + thread server_thread([&server]() { + // Start WSS-server + server.start(); + }); + + // Wait for server to start so that the client can connect + this_thread::sleep_for(chrono::seconds(1)); + + // Example 4: Client communication with server + // Second Client() parameter set to false: no certificate verification + // Possible output: + // Server: Opened connection 0x7fcf21600380 + // Client: Opened connection + // Client: Sending message: "Hello" + // Server: Message received: "Hello" from 0x7fcf21600380 + // Server: Sending message "Hello" to 0x7fcf21600380 + // Client: Message received: "Hello" + // Client: Sending close connection + // Server: Closed connection 0x7fcf21600380 with status code 1000 + // Client: Closed connection with status code 1000 + WssClient client("localhost:8080/echo", false); + client.on_message = [](shared_ptr connection, shared_ptr in_message) { + cout << "Client: Message received: \"" << in_message->string() << "\"" << endl; + + cout << "Client: Sending close connection" << endl; + connection->send_close(1000); + }; + + client.on_open = [](shared_ptr connection) { + cout << "Client: Opened connection" << endl; + + string out_message("Hello"); + cout << "Client: Sending message: \"" << out_message << "\"" << endl; + + connection->send(out_message); + }; + + client.on_close = [](shared_ptr /*connection*/, int status, const string & /*reason*/) { + cout << "Client: Closed connection with status code " << status << endl; + }; + + // See http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference.html, Error Codes for error code meanings + client.on_error = [](shared_ptr /*connection*/, const SimpleWeb::error_code &ec) { + cout << "Client: Error: " << ec << ", error message: " << ec.message() << endl; + }; + + client.start(); + + server_thread.join(); +} diff --git a/src/comm/ros_bridge/include/jsongenerator.h b/src/comm/ros_bridge/include/jsongenerator.h new file mode 100644 index 000000000..55cc35950 --- /dev/null +++ b/src/comm/ros_bridge/include/jsongenerator.h @@ -0,0 +1,16 @@ +#ifndef JSONGENERATOR_H +#define JSONGENERATOR_H + +#include "rapidjson/include/rapidjson/document.h" + +namespace ros_bridge { + +template +class JsonGenerator { + +}; + +} +#endif // JSONGENERATOR_H diff --git a/src/comm/ros_bridge/include/messages.h b/src/comm/ros_bridge/include/messages.h new file mode 100644 index 000000000..279386c85 --- /dev/null +++ b/src/comm/ros_bridge/include/messages.h @@ -0,0 +1,155 @@ +#ifndef MESSAGES_H +#define MESSAGES_H + +#include +#include +#include + +namespace ros_bridge { + + //! @brief C++ representation of ros::Time + class Time{ + public: + Time(); + Time(uint32_t secs, uint32_t nsecs); + + uint32_t getSecs() const; + uint32_t getNSecs() const; + + void setSecs (uint32_t secs); + void setNSecs (uint32_t nsecs); + + private: + uint32_t _secs; + uint32_t _nsecs; + }; + + //! @brief C++ representation of std_msgs/Header + class Header{ + public: + Header(); + Header(uint32_t seq, const Time &stamp, const std::string &frame_id); + + uint32_t getSeq() const; + const Time &getStamp() const; + const std::string &getFrameId() const; + + void setSeq (uint32_t seq); + void setStamp (const Time & stamp); + void setFrameId (const std::string &frame_id); + + private: + uint32_t _seq; + Time _stamp; + std::string _frame_id; + }; + + //! @brief C++ representation of geometry_msgs/Point32 + class Point32{ + public: + Point32(); + Point32(_Float32 x, _Float32 y, _Float32 z); + + template + void set(_Float32 component) + { + static_assert (i < 3, "Index out of bonds."); + _components[i] = component; + } + + template + _Float32 get(void) const + { + static_assert (i < 3, "Index out of bonds."); + return _components[i]; + } + + private: + std::array<_Float32, 3> _components; + }; + + //! @brief C++ representation of geometry_msgs/Polygon + template + class Polygon{ + public: + Polygon(){} + Polygon(const std::vector &points) : _points(points) {} + Polygon(const Polygon &poly) : _points(poly.get()) {} + + const std::vector &get() const + { + return _points; + } + + void set(std::vector &points) + { + _points = points; + } + + void clear() + { + _points.clear(); + } + + PointType &at(unsigned int i) + { + return _points.at(i); + } + + void push_back(const Point32 &p) + { + _points.push_back(p); + } + + void pop_back() + { + _points.pop_back(); + } + + private: + std::vector _points; + }; + + //! @brief C++ representation of geometry_msgs/PolygonStamped + template > + class PolygonStamped : public PolygonType{ + public: + PolygonStamped(); + PolygonStamped(const Header &header, const PolygonType &polygon) : + _header(header) + , PolygonType(polygon) {} + + private: + Header _header; + }; + + //! @brief C++ representation of jsk_recognition_msgs/PolygonArray + template , class HeaderType = Header, template class ContainerType = std::vector > + class PolygonArray{ + public: + PolygonArray() + : PolygonArray(HeaderType() + , ContainerType() + , ContainerType() + , ContainerType<_Float32>()) + {} + + PolygonArray(const HeaderType &header, + const ContainerType &polygons, + const ContainerType &labels, + const ContainerType<_Float32> &likelihood) + : _header(header) + , _polygons(polygons) + , _labels(labels) + , _likelihood(likelihood) + {} + + private: + HeaderType _header; + ContainerType _polygons; + ContainerType _labels; + ContainerType<_Float32> _likelihood; + }; +} + +#endif // MESSAGES_H diff --git a/src/comm/ros_bridge/rapidjson/.gitattributes b/src/comm/ros_bridge/rapidjson/.gitattributes new file mode 100644 index 000000000..6f598bb7f --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/.gitattributes @@ -0,0 +1,22 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text +*.h text +*.txt text +*.md text +*.cmake text +*.svg text +*.dot text +*.yml text +*.in text +*.sh text +*.autopkg text +Dockerfile text + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary +*.json binary \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/.gitignore b/src/comm/ros_bridge/rapidjson/.gitignore new file mode 100644 index 000000000..1d3073f7e --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/.gitignore @@ -0,0 +1,28 @@ +/bin/* +!/bin/data +!/bin/encodings +!/bin/jsonchecker +!/bin/types +/build +/doc/html +/doc/doxygen_*.db +*.a + +# Temporary files created during CMake build +CMakeCache.txt +CMakeFiles +cmake_install.cmake +CTestTestfile.cmake +Makefile +RapidJSON*.cmake +RapidJSON.pc +Testing +/googletest +install_manifest.txt +Doxyfile +Doxyfile.zh-cn +DartConfiguration.tcl +*.nupkg + +# Files created by OS +*.DS_Store diff --git a/src/comm/ros_bridge/rapidjson/.gitmodules b/src/comm/ros_bridge/rapidjson/.gitmodules new file mode 100644 index 000000000..5e41f7c97 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/.gitmodules @@ -0,0 +1,3 @@ +[submodule "thirdparty/gtest"] + path = thirdparty/gtest + url = https://github.com/google/googletest.git diff --git a/src/comm/ros_bridge/rapidjson/.travis.yml b/src/comm/ros_bridge/rapidjson/.travis.yml new file mode 100644 index 000000000..df821a709 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/.travis.yml @@ -0,0 +1,99 @@ +sudo: required +dist: trusty +group: edge + +language: cpp +cache: + - ccache + +env: + global: + - USE_CCACHE=1 + - CCACHE_SLOPPINESS=pch_defines,time_macros + - CCACHE_COMPRESS=1 + - CCACHE_MAXSIZE=100M + - ARCH_FLAGS_x86='-m32' # #266: don't use SSE on 32-bit + - ARCH_FLAGS_x86_64='-msse4.2' # use SSE4.2 on 64-bit + - GITHUB_REPO='Tencent/rapidjson' + - secure: "HrsaCb+N66EG1HR+LWH1u51SjaJyRwJEDzqJGYMB7LJ/bfqb9mWKF1fLvZGk46W5t7TVaXRDD5KHFx9DPWvKn4gRUVkwTHEy262ah5ORh8M6n/6VVVajeV/AYt2C0sswdkDBDO4Xq+xy5gdw3G8s1A4Inbm73pUh+6vx+7ltBbk=" + +before_install: + - sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test + - sudo apt-get update -qq + - sudo apt-get install -y cmake valgrind g++-multilib libc6-dbg:i386 + +matrix: + include: + # gcc + - env: CONF=release ARCH=x86 CXX11=ON + compiler: gcc + - env: CONF=release ARCH=x86_64 CXX11=ON + compiler: gcc + - env: CONF=debug ARCH=x86 CXX11=OFF + compiler: gcc + - env: CONF=debug ARCH=x86_64 CXX11=OFF + compiler: gcc + # clang + - env: CONF=debug ARCH=x86 CXX11=ON CCACHE_CPP2=yes + compiler: clang + - env: CONF=debug ARCH=x86_64 CXX11=ON CCACHE_CPP2=yes + compiler: clang + - env: CONF=debug ARCH=x86 CXX11=OFF CCACHE_CPP2=yes + compiler: clang + - env: CONF=debug ARCH=x86_64 CXX11=OFF CCACHE_CPP2=yes + compiler: clang + - env: CONF=release ARCH=x86 CXX11=ON CCACHE_CPP2=yes + compiler: clang + - env: CONF=release ARCH=x86_64 CXX11=ON CCACHE_CPP2=yes + compiler: clang + # coverage report + - env: CONF=debug ARCH=x86 CXX11=ON GCOV_FLAGS='--coverage' + compiler: gcc + cache: + - ccache + - pip + after_success: + - pip install --user cpp-coveralls + - coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h + - env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage' + compiler: gcc + cache: + - ccache + - pip + after_success: + - pip install --user cpp-coveralls + - coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h + - script: # Documentation task + - cd build + - cmake .. -DRAPIDJSON_HAS_STDSTRING=ON -DCMAKE_VERBOSE_MAKEFILE=ON + - make travis_doc + cache: false + addons: + apt: + packages: + - doxygen + +before_script: + - ccache -s + # hack to avoid Valgrind bug (https://bugs.kde.org/show_bug.cgi?id=326469), + # exposed by merging PR#163 (using -march=native) + # TODO: Since this bug is already fixed. Remove this when valgrind can be upgraded. + - sed -i "s/-march=native//" CMakeLists.txt + - mkdir build + +script: + - if [ "$CXX" = "clang++" ]; then export CXXFLAGS="-stdlib=libc++ ${CXXFLAGS}"; fi + - > + eval "ARCH_FLAGS=\${ARCH_FLAGS_${ARCH}}" ; + (cd build && cmake + -DRAPIDJSON_HAS_STDSTRING=ON + -DRAPIDJSON_BUILD_CXX11=$CXX11 + -DCMAKE_VERBOSE_MAKEFILE=ON + -DCMAKE_BUILD_TYPE=$CONF + -DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS" + -DCMAKE_EXE_LINKER_FLAGS=$GCOV_FLAGS + ..) + - cd build + - make tests -j 2 + - make examples -j 2 + - ctest -j 2 -V `[ "$CONF" = "release" ] || echo "-E perftest"` diff --git a/src/comm/ros_bridge/rapidjson/CHANGELOG.md b/src/comm/ros_bridge/rapidjson/CHANGELOG.md new file mode 100644 index 000000000..1c580bd14 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/CHANGELOG.md @@ -0,0 +1,158 @@ +# Change Log +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] + +## 1.1.0 - 2016-08-25 + +### Added +* Add GenericDocument ctor overload to specify JSON type (#369) +* Add FAQ (#372, #373, #374, #376) +* Add forward declaration header `fwd.h` +* Add @PlatformIO Library Registry manifest file (#400) +* Implement assignment operator for BigInteger (#404) +* Add comments support (#443) +* Adding coapp definition (#460) +* documenttest.cpp: EXPECT_THROW when checking empty allocator (470) +* GenericDocument: add implicit conversion to ParseResult (#480) +* Use with C++ linkage on Windows ARM (#485) +* Detect little endian for Microsoft ARM targets +* Check Nan/Inf when writing a double (#510) +* Add JSON Schema Implementation (#522) +* Add iostream wrapper (#530) +* Add Jsonx example for converting JSON into JSONx (a XML format) (#531) +* Add optional unresolvedTokenIndex parameter to Pointer::Get() (#532) +* Add encoding validation option for Writer/PrettyWriter (#534) +* Add Writer::SetMaxDecimalPlaces() (#536) +* Support {0, } and {0, m} in Regex (#539) +* Add Value::Get/SetFloat(), Value::IsLossLessFloat/Double() (#540) +* Add stream position check to reader unit tests (#541) +* Add Templated accessors and range-based for (#542) +* Add (Pretty)Writer::RawValue() (#543) +* Add Document::Parse(std::string), Document::Parse(const char*, size_t length) and related APIs. (#553) +* Add move constructor for GenericSchemaDocument (#554) +* Add VS2010 and VS2015 to AppVeyor CI (#555) +* Add parse-by-parts example (#556, #562) +* Support parse number as string (#564, #589) +* Add kFormatSingleLineArray for PrettyWriter (#577) +* Added optional support for trailing commas (#584) +* Added filterkey and filterkeydom examples (#615) +* Added npm docs (#639) +* Allow options for writing and parsing NaN/Infinity (#641) +* Add std::string overload to PrettyWriter::Key() when RAPIDJSON_HAS_STDSTRING is defined (#698) + +### Fixed +* Fix gcc/clang/vc warnings (#350, #394, #397, #444, #447, #473, #515, #582, #589, #595, #667) +* Fix documentation (#482, #511, #550, #557, #614, #635, #660) +* Fix emscripten alignment issue (#535) +* Fix missing allocator to uses of AddMember in document (#365) +* CMake will no longer complain that the minimum CMake version is not specified (#501) +* Make it usable with old VC8 (VS2005) (#383) +* Prohibit C++11 move from Document to Value (#391) +* Try to fix incorrect 64-bit alignment (#419) +* Check return of fwrite to avoid warn_unused_result build failures (#421) +* Fix UB in GenericDocument::ParseStream (#426) +* Keep Document value unchanged on parse error (#439) +* Add missing return statement (#450) +* Fix Document::Parse(const Ch*) for transcoding (#478) +* encodings.h: fix typo in preprocessor condition (#495) +* Custom Microsoft headers are necessary only for Visual Studio 2012 and lower (#559) +* Fix memory leak for invalid regex (26e69ffde95ba4773ab06db6457b78f308716f4b) +* Fix a bug in schema minimum/maximum keywords for 64-bit integer (e7149d665941068ccf8c565e77495521331cf390) +* Fix a crash bug in regex (#605) +* Fix schema "required" keyword cannot handle duplicated keys (#609) +* Fix cmake CMP0054 warning (#612) +* Added missing include guards in istreamwrapper.h and ostreamwrapper.h (#634) +* Fix undefined behaviour (#646) +* Fix buffer overrun using PutN (#673) +* Fix rapidjson::value::Get() may returns wrong data (#681) +* Add Flush() for all value types (#689) +* Handle malloc() fail in PoolAllocator (#691) +* Fix builds on x32 platform. #703 + +### Changed +* Clarify problematic JSON license (#392) +* Move Travis to container based infrastructure (#504, #558) +* Make whitespace array more compact (#513) +* Optimize Writer::WriteString() with SIMD (#544) +* x86-64 48-bit pointer optimization for GenericValue (#546) +* Define RAPIDJSON_HAS_CXX11_RVALUE_REFS directly in clang (#617) +* Make GenericSchemaDocument constructor explicit (#674) +* Optimize FindMember when use std::string (#690) + +## [1.0.2] - 2015-05-14 + +### Added +* Add Value::XXXMember(...) overloads for std::string (#335) + +### Fixed +* Include rapidjson.h for all internal/error headers. +* Parsing some numbers incorrectly in full-precision mode (`kFullPrecisionParseFlag`) (#342) +* Fix some numbers parsed incorrectly (#336) +* Fix alignment of 64bit platforms (#328) +* Fix MemoryPoolAllocator::Clear() to clear user-buffer (0691502573f1afd3341073dd24b12c3db20fbde4) + +### Changed +* CMakeLists for include as a thirdparty in projects (#334, #337) +* Change Document::ParseStream() to use stack allocator for Reader (ffbe38614732af8e0b3abdc8b50071f386a4a685) + +## [1.0.1] - 2015-04-25 + +### Added +* Changelog following [Keep a CHANGELOG](https://github.com/olivierlacan/keep-a-changelog) suggestions. + +### Fixed +* Parsing of some numbers (e.g. "1e-00011111111111") causing assertion (#314). +* Visual C++ 32-bit compilation error in `diyfp.h` (#317). + +## [1.0.0] - 2015-04-22 + +### Added +* 100% [Coverall](https://coveralls.io/r/Tencent/rapidjson?branch=master) coverage. +* Version macros (#311) + +### Fixed +* A bug in trimming long number sequence (4824f12efbf01af72b8cb6fc96fae7b097b73015). +* Double quote in unicode escape (#288). +* Negative zero roundtrip (double only) (#289). +* Standardize behavior of `memcpy()` and `malloc()` (0c5c1538dcfc7f160e5a4aa208ddf092c787be5a, #305, 0e8bbe5e3ef375e7f052f556878be0bd79e9062d). + +### Removed +* Remove an invalid `Document::ParseInsitu()` API (e7f1c6dd08b522cfcf9aed58a333bd9a0c0ccbeb). + +## 1.0-beta - 2015-04-8 + +### Added +* RFC 7159 (#101) +* Optional Iterative Parser (#76) +* Deep-copy values (#20) +* Error code and message (#27) +* ASCII Encoding (#70) +* `kParseStopWhenDoneFlag` (#83) +* `kParseFullPrecisionFlag` (881c91d696f06b7f302af6d04ec14dd08db66ceb) +* Add `Key()` to handler concept (#134) +* C++11 compatibility and support (#128) +* Optimized number-to-string and vice versa conversions (#137, #80) +* Short-String Optimization (#131) +* Local stream optimization by traits (#32) +* Travis & Appveyor Continuous Integration, with Valgrind verification (#24, #242) +* Redo all documentation (English, Simplified Chinese) + +### Changed +* Copyright ownership transferred to THL A29 Limited (a Tencent company). +* Migrating from Premake to CMAKE (#192) +* Resolve all warning reports + +### Removed +* Remove other JSON libraries for performance comparison (#180) + +## 0.11 - 2012-11-16 + +## 0.1 - 2011-11-18 + +[Unreleased]: https://github.com/Tencent/rapidjson/compare/v1.1.0...HEAD +[1.1.0]: https://github.com/Tencent/rapidjson/compare/v1.0.2...v1.1.0 +[1.0.2]: https://github.com/Tencent/rapidjson/compare/v1.0.1...v1.0.2 +[1.0.1]: https://github.com/Tencent/rapidjson/compare/v1.0.0...v1.0.1 +[1.0.0]: https://github.com/Tencent/rapidjson/compare/v1.0-beta...v1.0.0 diff --git a/src/comm/ros_bridge/rapidjson/CMakeLists.txt b/src/comm/ros_bridge/rapidjson/CMakeLists.txt new file mode 100644 index 000000000..0275672e0 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/CMakeLists.txt @@ -0,0 +1,221 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +if(POLICY CMP0025) + # detect Apple's Clang + cmake_policy(SET CMP0025 NEW) +endif() +if(POLICY CMP0054) + cmake_policy(SET CMP0054 NEW) +endif() + +SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules) + +PROJECT(RapidJSON CXX) + +set(LIB_MAJOR_VERSION "1") +set(LIB_MINOR_VERSION "1") +set(LIB_PATCH_VERSION "0") +set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}") + +# compile in release with debug info mode by default +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) +endif() + +# Build all binaries in a separate directory +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +option(RAPIDJSON_BUILD_DOC "Build rapidjson documentation." ON) +option(RAPIDJSON_BUILD_EXAMPLES "Build rapidjson examples." ON) +option(RAPIDJSON_BUILD_TESTS "Build rapidjson perftests and unittests." ON) +option(RAPIDJSON_BUILD_THIRDPARTY_GTEST + "Use gtest installation in `thirdparty/gtest` by default if available" OFF) + +option(RAPIDJSON_BUILD_CXX11 "Build rapidjson with C++11 (gcc/clang)" ON) +if(RAPIDJSON_BUILD_CXX11) + set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD_REQUIRED TRUE) +endif() + +option(RAPIDJSON_BUILD_ASAN "Build rapidjson with address sanitizer (gcc/clang)" OFF) +option(RAPIDJSON_BUILD_UBSAN "Build rapidjson with undefined behavior sanitizer (gcc/clang)" OFF) + +option(RAPIDJSON_ENABLE_INSTRUMENTATION_OPT "Build rapidjson with -march or -mcpu options" ON) + +option(RAPIDJSON_HAS_STDSTRING "" OFF) +if(RAPIDJSON_HAS_STDSTRING) + add_definitions(-DRAPIDJSON_HAS_STDSTRING) +endif() + +find_program(CCACHE_FOUND ccache) +if(CCACHE_FOUND) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fcolor-diagnostics") + endif() +endif(CCACHE_FOUND) + +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if(RAPIDJSON_ENABLE_INSTRUMENTATION_OPT AND NOT CMAKE_CROSSCOMPILING) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "powerpc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64le") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native") + else() + #FIXME: x86 is -march=native, but doesn't mean every arch is this option. To keep original project's compatibility, I leave this except POWER. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") + endif() + endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") + set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wsign-conversion) + if (RAPIDJSON_BUILD_CXX11 AND CMAKE_VERSION VERSION_LESS 3.1) + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.7.0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + if (RAPIDJSON_BUILD_ASAN) + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.0") + message(FATAL_ERROR "GCC < 4.8 doesn't support the address sanitizer") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + endif() + endif() + if (RAPIDJSON_BUILD_UBSAN) + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9.0") + message(FATAL_ERROR "GCC < 4.9 doesn't support the undefined behavior sanitizer") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined") + endif() + endif() +elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if(NOT CMAKE_CROSSCOMPILING) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "powerpc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64le") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native") + else() + #FIXME: x86 is -march=native, but doesn't mean every arch is this option. To keep original project's compatibility, I leave this except POWER. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") + endif() + endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -Wno-missing-field-initializers") + set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wimplicit-fallthrough) + if (RAPIDJSON_BUILD_CXX11 AND CMAKE_VERSION VERSION_LESS 3.1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + if (RAPIDJSON_BUILD_ASAN) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + endif() + if (RAPIDJSON_BUILD_UBSAN) + if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined") + endif() + endif() +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") +elseif (CMAKE_CXX_COMPILER_ID MATCHES "XL") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -qarch=auto") +endif() + +#add extra search paths for libraries and includes +SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "The directory the headers are installed in") +SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE STRING "Directory where lib will install") +SET(DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}" CACHE PATH "Path to the documentation") + +IF(UNIX OR CYGWIN) + SET(_CMAKE_INSTALL_DIR "${LIB_INSTALL_DIR}/cmake/${PROJECT_NAME}") +ELSEIF(WIN32) + SET(_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/cmake") +ENDIF() +SET(CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" CACHE PATH "The directory cmake files are installed in") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +if(RAPIDJSON_BUILD_DOC) + add_subdirectory(doc) +endif() + +add_custom_target(travis_doc) +add_custom_command(TARGET travis_doc + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/travis-doxygen.sh) + +if(RAPIDJSON_BUILD_EXAMPLES) + add_subdirectory(example) +endif() + +if(RAPIDJSON_BUILD_TESTS) + if(MSVC11) + # required for VS2012 due to missing support for variadic templates + add_definitions(-D_VARIADIC_MAX=10) + endif(MSVC11) + add_subdirectory(test) + include(CTest) +endif() + +# pkg-config +IF (UNIX OR CYGWIN) + CONFIGURE_FILE (${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + @ONLY) + INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + DESTINATION "${LIB_INSTALL_DIR}/pkgconfig" + COMPONENT pkgconfig) +ENDIF() + +install(FILES readme.md + DESTINATION "${DOC_INSTALL_DIR}" + COMPONENT doc) + +install(DIRECTORY include/rapidjson + DESTINATION "${INCLUDE_INSTALL_DIR}" + COMPONENT dev) + +install(DIRECTORY example/ + DESTINATION "${DOC_INSTALL_DIR}/examples" + COMPONENT examples + # Following patterns are for excluding the intermediate/object files + # from an install of in-source CMake build. + PATTERN "CMakeFiles" EXCLUDE + PATTERN "Makefile" EXCLUDE + PATTERN "cmake_install.cmake" EXCLUDE) + +# Provide config and version files to be used by other applications +# =============================== + +################################################################################ +# Export package for use from the build tree +EXPORT( PACKAGE ${PROJECT_NAME} ) + +# Create the RapidJSONConfig.cmake file for other cmake projects. +# ... for the build tree +SET( CONFIG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +SET( CONFIG_DIR ${CMAKE_CURRENT_BINARY_DIR}) +SET( ${PROJECT_NAME}_INCLUDE_DIR "\${${PROJECT_NAME}_SOURCE_DIR}/include" ) + +CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake @ONLY ) +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}ConfigVersion.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake @ONLY) + +# ... for the install tree +SET( CMAKECONFIG_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/${PROJECT_NAME} ) +FILE( RELATIVE_PATH REL_INCLUDE_DIR + "${CMAKECONFIG_INSTALL_DIR}" + "${CMAKE_INSTALL_PREFIX}/include" ) + +SET( ${PROJECT_NAME}_INCLUDE_DIR "\${${PROJECT_NAME}_CMAKE_DIR}/${REL_INCLUDE_DIR}" ) +SET( CONFIG_SOURCE_DIR ) +SET( CONFIG_DIR ) +CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake @ONLY ) + +INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake" + DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) + +# Install files +INSTALL(FILES + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + DESTINATION "${CMAKE_INSTALL_DIR}" + COMPONENT dev) diff --git a/src/comm/ros_bridge/rapidjson/CMakeModules/FindGTestSrc.cmake b/src/comm/ros_bridge/rapidjson/CMakeModules/FindGTestSrc.cmake new file mode 100644 index 000000000..f3cb8c990 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/CMakeModules/FindGTestSrc.cmake @@ -0,0 +1,30 @@ + +SET(GTEST_SEARCH_PATH + "${GTEST_SOURCE_DIR}" + "${CMAKE_CURRENT_LIST_DIR}/../thirdparty/gtest/googletest") + +IF(UNIX) + IF(RAPIDJSON_BUILD_THIRDPARTY_GTEST) + LIST(APPEND GTEST_SEARCH_PATH "/usr/src/gtest") + ELSE() + LIST(INSERT GTEST_SEARCH_PATH 1 "/usr/src/gtest") + ENDIF() +ENDIF() + +FIND_PATH(GTEST_SOURCE_DIR + NAMES CMakeLists.txt src/gtest_main.cc + PATHS ${GTEST_SEARCH_PATH}) + + +# Debian installs gtest include directory in /usr/include, thus need to look +# for include directory separately from source directory. +FIND_PATH(GTEST_INCLUDE_DIR + NAMES gtest/gtest.h + PATH_SUFFIXES include + HINTS ${GTEST_SOURCE_DIR} + PATHS ${GTEST_SEARCH_PATH}) + +INCLUDE(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GTestSrc DEFAULT_MSG + GTEST_SOURCE_DIR + GTEST_INCLUDE_DIR) diff --git a/src/comm/ros_bridge/rapidjson/RapidJSON.pc.in b/src/comm/ros_bridge/rapidjson/RapidJSON.pc.in new file mode 100644 index 000000000..6afb079f8 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/RapidJSON.pc.in @@ -0,0 +1,7 @@ +includedir=@INCLUDE_INSTALL_DIR@ + +Name: @PROJECT_NAME@ +Description: A fast JSON parser/generator for C++ with both SAX/DOM style API +Version: @LIB_VERSION_STRING@ +URL: https://github.com/Tencent/rapidjson +Cflags: -I${includedir} diff --git a/src/comm/ros_bridge/rapidjson/RapidJSONConfig.cmake.in b/src/comm/ros_bridge/rapidjson/RapidJSONConfig.cmake.in new file mode 100644 index 000000000..e3c65a541 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/RapidJSONConfig.cmake.in @@ -0,0 +1,15 @@ +################################################################################ +# RapidJSON source dir +set( RapidJSON_SOURCE_DIR "@CONFIG_SOURCE_DIR@") + +################################################################################ +# RapidJSON build dir +set( RapidJSON_DIR "@CONFIG_DIR@") + +################################################################################ +# Compute paths +get_filename_component(RapidJSON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + +set( RapidJSON_INCLUDE_DIR "@RapidJSON_INCLUDE_DIR@" ) +set( RapidJSON_INCLUDE_DIRS "@RapidJSON_INCLUDE_DIR@" ) +message(STATUS "RapidJSON found. Headers: ${RapidJSON_INCLUDE_DIRS}") diff --git a/src/comm/ros_bridge/rapidjson/RapidJSONConfigVersion.cmake.in b/src/comm/ros_bridge/rapidjson/RapidJSONConfigVersion.cmake.in new file mode 100644 index 000000000..25741fc09 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/RapidJSONConfigVersion.cmake.in @@ -0,0 +1,10 @@ +SET(PACKAGE_VERSION "@LIB_VERSION_STRING@") + +IF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) + SET(PACKAGE_VERSION_EXACT "true") +ENDIF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) +IF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) + SET(PACKAGE_VERSION_COMPATIBLE "true") +ELSE (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) + SET(PACKAGE_VERSION_UNSUITABLE "true") +ENDIF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) diff --git a/src/comm/ros_bridge/rapidjson/appveyor.yml b/src/comm/ros_bridge/rapidjson/appveyor.yml new file mode 100644 index 000000000..376dc1976 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/appveyor.yml @@ -0,0 +1,54 @@ +version: 1.1.0.{build} + +configuration: +- Debug +- Release + +environment: + matrix: + # - VS_VERSION: 9 2008 + # VS_PLATFORM: win32 + # - VS_VERSION: 9 2008 + # VS_PLATFORM: x64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + VS_VERSION: 10 2010 + VS_PLATFORM: win32 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + VS_VERSION: 10 2010 + VS_PLATFORM: x64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + VS_VERSION: 11 2012 + VS_PLATFORM: win32 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + VS_VERSION: 11 2012 + VS_PLATFORM: x64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + VS_VERSION: 12 2013 + VS_PLATFORM: win32 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + VS_VERSION: 12 2013 + VS_PLATFORM: x64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + VS_VERSION: 14 2015 + VS_PLATFORM: win32 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + VS_VERSION: 14 2015 + VS_PLATFORM: x64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + VS_VERSION: 15 2017 + VS_PLATFORM: win32 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + VS_VERSION: 15 2017 + VS_PLATFORM: x64 + +before_build: +- git submodule update --init --recursive +- cmake -H. -BBuild/VS -G "Visual Studio %VS_VERSION%" -DCMAKE_GENERATOR_PLATFORM=%VS_PLATFORM% -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=true -Wno-dev + +build: + project: Build\VS\RapidJSON.sln + parallel: true + verbosity: minimal + +test_script: +- cd Build\VS && if %CONFIGURATION%==Debug (ctest --verbose -E perftest --build-config %CONFIGURATION%) else (ctest --verbose --build-config %CONFIGURATION%) diff --git a/src/comm/ros_bridge/rapidjson/bin/data/abcde.txt b/src/comm/ros_bridge/rapidjson/bin/data/abcde.txt new file mode 100644 index 000000000..6a8165460 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/data/abcde.txt @@ -0,0 +1 @@ +abcde \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/data/glossary.json b/src/comm/ros_bridge/rapidjson/bin/data/glossary.json new file mode 100644 index 000000000..d6e6ca150 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/data/glossary.json @@ -0,0 +1,22 @@ +{ + "glossary": { + "title": "example glossary", + "GlossDiv": { + "title": "S", + "GlossList": { + "GlossEntry": { + "ID": "SGML", + "SortAs": "SGML", + "GlossTerm": "Standard Generalized Markup Language", + "Acronym": "SGML", + "Abbrev": "ISO 8879:1986", + "GlossDef": { + "para": "A meta-markup language, used to create markup languages such as DocBook.", + "GlossSeeAlso": ["GML", "XML"] + }, + "GlossSee": "markup" + } + } + } + } +} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/data/menu.json b/src/comm/ros_bridge/rapidjson/bin/data/menu.json new file mode 100644 index 000000000..539c3af20 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/data/menu.json @@ -0,0 +1,27 @@ +{"menu": { + "header": "SVG Viewer", + "items": [ + {"id": "Open"}, + {"id": "OpenNew", "label": "Open New"}, + null, + {"id": "ZoomIn", "label": "Zoom In"}, + {"id": "ZoomOut", "label": "Zoom Out"}, + {"id": "OriginalView", "label": "Original View"}, + null, + {"id": "Quality"}, + {"id": "Pause"}, + {"id": "Mute"}, + null, + {"id": "Find", "label": "Find..."}, + {"id": "FindAgain", "label": "Find Again"}, + {"id": "Copy"}, + {"id": "CopyAgain", "label": "Copy Again"}, + {"id": "CopySVG", "label": "Copy SVG"}, + {"id": "ViewSVG", "label": "View SVG"}, + {"id": "ViewSource", "label": "View Source"}, + {"id": "SaveAs", "label": "Save As"}, + null, + {"id": "Help"}, + {"id": "About", "label": "About Adobe CVG Viewer..."} + ] +}} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/data/readme.txt b/src/comm/ros_bridge/rapidjson/bin/data/readme.txt new file mode 100644 index 000000000..c53bfb8b7 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/data/readme.txt @@ -0,0 +1 @@ +sample.json is obtained from http://code.google.com/p/json-test-suite/downloads/detail?name=sample.zip diff --git a/src/comm/ros_bridge/rapidjson/bin/data/sample.json b/src/comm/ros_bridge/rapidjson/bin/data/sample.json new file mode 100644 index 000000000..30930e765 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/data/sample.json @@ -0,0 +1,3315 @@ +{ + "a": { + "6U閆崬밺뀫颒myj츥휘:$薈mY햚#rz飏+玭V㭢뾿愴YꖚX亥ᮉ푊\u0006垡㐭룝\"厓ᔧḅ^Sqpv媫\"⤽걒\"˽Ἆ?ꇆ䬔未tv{DV鯀Tἆl凸g\\㈭ĭ즿UH㽤": null, + "b茤z\\.N": [[ + "ZL:ᅣዎ*Y|猫劁櫕荾Oj为1糕쪥泏S룂w࡛Ᏺ⸥蚙)", + { + "\"䬰ỐwD捾V`邀⠕VD㺝sH6[칑.:醥葹*뻵倻aD\"": true, + "e浱up蔽Cr෠JK軵xCʨ<뜡癙Y獩ケ齈X/螗唻?<蘡+뷄㩤쳖3偑犾&\\첊xz坍崦ݻ鍴\"嵥B3㰃詤豺嚼aqJ⑆∥韼@\u000b㢊\u0015L臯.샥": false, + "l?Ǩ喳e6㔡$M꼄I,(3᝝縢,䊀疅뉲B㴔傳䂴\u0088㮰钘ꜵ!ᅛ韽>": -5514085325291784739, + "o㮚?\"춛㵉<\/﬊ࠃ䃪䝣wp6ἀ䱄[s*S嬈貒pᛥ㰉'돀": [{ + "(QP윤懊FI<ꃣ『䕷[\"珒嶮?%Ḭ壍಻䇟0荤!藲끹bd浶tl\u2049#쯀@僞": {"i妾8홫": { + ",M맃䞛K5nAㆴVN㒊햬$n꩑&ꎝ椞阫?/ṏ세뉪1x쥼㻤㪙`\"$쟒薟B煌܀쨝ଢ଼2掳7㙟鴙X婢\u0002": "Vዉ菈᧷⦌kﮞఈnz*﷜FM\"荭7ꍀ-VR<\/';䁙E9$䩉\f @s?퍪o3^衴cඎ䧪aK鼟q䆨c{䳠5mᒲՙ蘹ᮩ": { + "F㲷JGo⯍P덵x뒳p䘧☔\"+ꨲ吿JfR㔹)4n紬G练Q፞!C|": true, + "p^㫮솎oc.೚A㤠??r\u000f)⾽⌲們M2.䴘䩳:⫭胃\\፾@Fᭌ\\K": false, + "蟌Tk愙潦伩": { + "a<\/@ᾛ慂侇瘎": -7271305752851720826, + "艓藬/>၄ṯ,XW~㲆w": {"E痧郶)㜓ha朗!N赻瞉駠uC\u20ad辠x퓮⣫P1ࠫLMMX'M刼唳됤": null, + "P쓫晥%k覛ዩIUᇸ滨:噐혲lMR5䋈V梗>%幽u頖\\)쟟": null, + "eg+昉~矠䧞难\b?gQ쭷筝\\eꮠNl{ಢ哭|]Mn銌╥zꖘzⱷ⭤ᮜ^": [ + -1.30142114406914976E17, + -1.7555215491128452E-19, + null, + "渾㨝ߏ牄귛r?돌?w[⚞ӻ~廩輫㼧/", + -4.5737191805302129E18, + null, + "xy࿑M[oc셒竓Ⓔx?뜓y䊦>-D켍(&&?XKkc꩖ﺸᏋ뵞K伕6ী)딀P朁yW揙?훻魢傎EG碸9類៌g踲C⟌aEX舲:z꒸许", + 3808159498143417627, + null, + {"m試\u20df1{G8&뚈h홯J<\/": { + "3ஸ厠zs#1K7:rᥞoꅔꯧ&띇鵼鞫6跜#赿5l'8{7㕳(b/j\"厢aq籀ꏚ\u0015厼稥": [ + -2226135764510113982, + true, + null, + { + "h%'맞S싅Hs&dl슾W0j鿏MםD놯L~S-㇡R쭬%": null, + "⟓咔謡칲\u0000孺ꛭx旑檉㶆?": null, + "恇I転;￸B2Y`z\\獓w,놏濐撐埵䂄)!䶢D=ഭ㴟jyY": { + "$ࡘt厛毣ൢI芁<겿骫⫦6tr惺a": [ + 6.385779736989334E-20, + false, + true, + true, + [ + -6.891946211462334E-19, + null, + { + "]-\\Ꟑ1/薓❧Ὂ\\l牑\u0007A郃)阜ᇒᓌ-塯`W峬G}SDb㬨Q臉⮻빌O鞟톴첂B㺱<ƈmu챑J㴹㷳픷Oㆩs": { + "\"◉B\"pᶉt骔J꩸ᄇᛐi╰栛K쉷㉯鐩!㈐n칍䟅難>盥y铿e୔蒏M貹ヅ8嘋퀯䉶ጥ㏢殊뻳\"絧╿ꉑ䠥?∃蓊{}㣣Gk긔H1哵峱": false, + "6.瀫cN䇮F㧺?\\椯=ڈT䘆4␘8qv": -3.5687501019676885E-19, + "Q?yऴr혴{஀䳘p惭f1ﹸ䅷䕋贲<ྃᄊ繲hq\\b|#QSTs1c-7(䵢\u2069匏絘ꯉ:l毴汞t戀oෟᵶ뮱፣-醇Jx䙬䐁햢0࣫ᡁgrㄛ": "\u0011_xM/蘇Chv;dhA5.嗀绱V爤ﰦi뵲M", + "⏑[\"ugoy^儣횎~U\\섯겜論l2jw஌yD腅̂\u0019": true, + "ⵯɇ䐲᫿࢚!㯢l샅笶戮1꣖0Xe": null, + "劅f넀識b宁焊E찓橵G!ʱ獓뭔雩괛": [{"p⹣켙[q>燣䍃㞽ᩲx:쓤삘7玑퇼0<\/q璂ᑁ[Z\\3䅵䧳\u0011㤧|妱緒C['췓Yꞟ3Z鳱雼P錻BU씧U`ᢶg蓱>.1ӧ譫'L_5V䏵Ц": [ + false, + false, + {"22䂍盥N霂얢躰e9⑩_뵜斌n@B}$괻Yᐱ@䧋V\"☒-諯cV돯ʠ": true, + "Ű螧ᔼ檍鍎땒딜qꄃH뜣<獧ूCY吓⸏>XQ㵡趌o끬k픀빯a(ܵ甏끆୯/6Nᪧ}搚ᆚ짌P牰泱鈷^d꣟#L삀\"㕹襻;k㸊\\f+": true, + "쎣\",|⫝̸阊x庿k잣v庅$鈏괎炔k쬪O_": [ + "잩AzZGz3v愠ꉈⵎ?㊱}S尳௏p\r2>췝IP䘈M)w|\u000eE", + -9222726055990423201, + null, + [ + false, + {"´킮'뮤쯽Wx讐V,6ᩪ1紲aႈ\u205czD": [ + -930994432421097536, + 3157232031581030121, + "l貚PY䃛5@䭄귻m㎮琸f": 1.0318894506812084E-19, + "࢜⩢Ш䧔1肽씮+༎ᣰ闺馺窃䕨8Mƶq腽xc(៯夐J5굄䕁Qj_훨/~価.䢵慯틠퇱豠㼇Qﵘ$DuSp(8Uญ<\/ಟ룴𥳐ݩ$": 8350772684161555590, + "ㆎQ䄾\u001bpᩭ${[諟^^骴᤮b^ㅥI┧T㉇⾞\"绦r䰂f矩'-7䡭桥Dz兔V9谶居㺍ᔊ䩯덲.\u001eL0ὅㅷ釣": [{ + "<쯬J卷^숞u࠯䌗艞R9닪g㐾볎a䂈歖意:%鐔|ﵤ|y}>;2,覂⶚啵tb*仛8乒㓶B࿠㯉戩oX 貘5V嗆렽낁߼4h䧛ꍺM空\\b꿋貼": 8478577078537189402, + "VD*|吝z~h譺aᯒ": { + "YI췢K<\/濳xNne玗rJo쾘3핰鴊\"↱AR:ࢷ\"9?\"臁說)?誚ꊏe)_D翾W?&F6J@뺾ꍰNZ醊Z쾈വH嶿?炫㷱鬰M겈᭨b,⻁鈵P䕡䀠८ⱄ홎鄣": { + "@?k2鶖㋮\"Oರ K㨇廪儲\u0017䍾J?);\b*묀㗠섳햭1MC V": null, + "UIICP!BUA`ᢈ㋸~袩㗪⾒=fB﮴l1ꡛ죘R辂여ҳ7쮡<䩲`熕8頁": 4481809488267626463, + "Y?+8먙ᚔ鋳蜩럶1㥔y璜౩`": [ + null, + 1.2850335807501874E-19, + "~V2", + 2035406654801997866, + { + "<숻1>\"": -8062468865199390827, + "M㿣E]}qwG莎Gn᝶(ꔙ\\D⬲iꇲs寢t駇S뀡ꢜ": false, + "pꝤ㎏9W%>M;-U璏f(^j1?&RB隧 忓b똊E": "#G?C8.躬ꥯ'?냪#< 渟&헿란zpo왓Kj}鷧XﻘMツb䕖;㪻", + "vE풤幉xz뱕쫥Ug㦲aH} ᣟp:鬼YᰟH3镔ᴚ斦\\鏑r*2橱G⼔F/.j": true, + "RK좬뎂a홠f*f㱉ᮍ⦋潙㨋Gu곌SGI3I뿐\\F',)t`荁蘯囯ﮉ裲뇟쥼_ገ驪▵撏ᕤV": 1.52738225997956557E18, + "^k굲䪿꠹B逤%F㱢漥O披M㽯镞竇霒i꼂焅륓\u00059=皫之눃\u2047娤閍銤唫ၕb<\/w踲䔼u솆맚,䝒ᝳ'/it": "B餹饴is権ꖪ怯ꦂẉဎt\"!凢谵⧿0\\<=(uL䷍刨쑪>俆揓Cy襸Q힆䆭涷<\/ᐱ0ɧ䗾䚹\\ኜ?ꄢᇘ`䴢{囇}᠈䴥X4퓪檄]ꥷ/3謒ሴn+g騍X", + "GgG꽬[(嫓몍6\u0004궍宩㙻/>\u0011^辍dT腪hxǑ%ꊇk,8(W⧂結P鬜O": [{ + "M㴾c>\\ᓲ\u0019V{>ꤩ혙넪㭪躂TS-痴໸闓⍵/徯O.M㏥ʷD囎⧔쁳휤T??鉬뇙=#ꢫ숣BX䭼<\/d똬졬g榿)eꨋﯪ좇첻\u001a\u0011\";~쓆BH4坋攊7힪", + "iT:L闞椕윚*滛gI≀Wਟඊ'ꢆ縺뱹鮚Nꩁ᧬蕼21줧\\䋯``⍐\\㏱鳨": 1927052677739832894, + "쮁缦腃g]礿Y㬙 fヺSɪ꾾N㞈": [ + null, + null, + { + "!t,灝Y 1䗉罵?c饃호䉂Cᐭ쒘z(즽sZG㬣sഖE4뢜㓕䏞丮Qp簍6EZឪ겛fx'ꩱQ0罣i{k锩*㤴㯞r迎jTⲤ渔m炅肳": [ + -3.3325685522591933E18, + [{"㓁5]A䢕1룥BC?Ꙍ`r룔Ⳛ䙡u伲+\u0001്o": [ + null, + 4975309147809803991, + null, + null, + {"T팘8Dﯲ稟MM☻㧚䥧/8ﻥ⥯aXLaH\"顾S☟耲ît7fS෉놁뮔/ꕼ䓈쁺4\\霶䠴ᩢ<\/t4?죵>uD5➶༆쉌럮⢀秙䘥\u20972ETR3濡恆vB? ~鸆\u0005": { + "`閖m璝㥉b뜴?Wf;?DV콜\u2020퍉౓擝宏ZMj3mJ먡-傷뱙yח㸷꥿ ໘u=M읝!5吭L4v\\?ǎ7C홫": null, + "|": false, + "~Ztᛋ䚘\\擭㗝傪W陖+㗶qᵿ蘥ᙄp%䫎)}=⠔6ᮢS湟-螾-mXH?cp": 448751162044282216, + "\u209fad놹j檋䇌ᶾ梕㉝bוּ": {"?苴ꩠD䋓帘5騱qﱖPF?☸珗顒yU ᡫcb䫎 S@㥚gꮒ쎘泴멖\\:I鮱TZ듒ᶨQ3+f7캙\"?\f풾\\o杞紟﻽M.⏎靑OP": [ + -2.6990368911551596E18, + [{"䒖@<᰿<\/⽬tTr腞&G%᳊秩蜰擻f㎳?S㵧\r*k뎾-乢겹隷j軛겷0룁鮁": {")DO0腦:춍逿:1㥨่!蛍樋2": [{ + ",ꌣf侴笾m๫ꆽ?1?U?\u0011ꌈꂇ": { + "x捗甠nVq䅦w`CD⦂惺嘴0I#vỵ} \\귂S끴D얾?Ԓj溯\"v餄a": { + "@翙c⢃趚痋i\u0015OQ⍝lq돆Y0pࢥ3쉨䜩^<8g懥0w)]䊑n洺o5쭝QL댊랖L镈Qnt⪟㒅십q헎鳒⮤眉ᔹ梠@O縠u泌ㄘb榚癸XޔFtj;iC": false, + "I&뱋゘|蓔䔕측瓯%6ᗻHW\\N1貇#?僐ᗜgh᭪o'䗈꽹Rc욏/蔳迄༝!0邔䨷푪8疩)[쭶緄㇈୧ፐ": { + "B+:ꉰ`s쾭)빼C羍A䫊pMgjdx䐝Hf9᥸W0!C樃'蘿f䫤סи\u0017Jve? 覝f둀⬣퓉Whk\"஼=չﳐ皆笁BIW虨쫓F廰饞": -642906201042308791, + "sb,XcZ<\/m㉹ ;䑷@c䵀s奤⬷7`ꘖ蕘戚?Feb#輜}p4nH⬮eKL트}": [ + "RK鳗z=袤Pf|[,u욺", + "Ẏᏻ罯뉋⺖锅젯㷻{H䰞쬙-쩓D]~\u0013O㳢gb@揶蔉|kᦂ❗!\u001ebM褐sca쨜襒y⺉룓", + null, + null, + true, + -1.650777344339075E-19, + false, + "☑lꄆs힨꤇]'uTന⌳농].1⋔괁沰\"IWഩ\u0019氜8쟇䔻;3衲恋,窌z펏喁횗?4?C넁问?ᥙ橭{稻Ⴗ_썔", + "n?]讇빽嗁}1孅9#ꭨ靶v\u0014喈)vw祔}룼쮿I", + -2.7033457331882025E18, + { + ";⚃^㱋x:饬ኡj'꧵T☽O㔬RO婎?향ᒭ搩$渣y4i;(Q>꿘e8q": "j~錘}0g;L萺*;ᕭꄮ0l潛烢5H▄쳂ꏒוֹꙶT犘≫x閦웧v", + "~揯\u2018c4職렁E~ᑅቚꈂ?nq뎤.:慹`F햘+%鉎O瀜쟏敛菮⍌浢<\/㮺紿P鳆ࠉ8I-o?#jﮨ7v3Dt赻J9": null, + "ࣝW䌈0ꍎqC逖,횅c၃swj;jJS櫍5槗OaB>D踾Y": {"㒰䵝F%?59.㍈cᕨ흕틎ḏ㋩B=9IېⓌ{:9.yw}呰ㆮ肒᎒tI㾴62\"ዃ抡C﹬B<\/촋jo朣", + [ + -7675533242647793366, + {"ᙧ呃:[㒺쳀쌡쏂H稈㢤\u001dᶗGG-{GHྻຊꡃ哸䵬;$?&d\\⥬こN圴됤挨-'ꕮ$PU%?冕눖i魁q騎Q": [ + false, + [[ + 7929823049157504248, + [[ + true, + "Z菙\u0017'eꕤ᱕l,0\\X\u001c[=雿8蠬L<\/낲긯W99g톉4ퟋb㝺\u0007劁'!麕Q궈oW:@X၎z蘻m絙璩귓죉+3柚怫tS捇蒣䝠-擶D[0=퉿8)q0ٟ", + "唉\nFA椭穒巯\\䥴䅺鿤S#b迅獘 ﶗ꬘\\?q1qN犠pX꜅^䤊⛤㢌[⬛휖岺q唻ⳡ틍\"㙙Eh@oA賑㗠y必Nꊑᗘ", + -2154220236962890773, + -3.2442003245397908E18, + "Wᄿ筠:瘫퀩?o貸q⊻(᎞KWf宛尨h^残3[U(='橄", + -7857990034281549164, + 1.44283696979059942E18, + null, + {"ꫯAw跭喀 ?_9\"Aty背F=9缉ྦྷ@;?^鞀w:uN㘢Rỏ": [ + 7.393662029337442E15, + 3564680942654233068, + [ + false, + -5253931502642112194, + "煉\\辎ೆ罍5⒭1䪁䃑s䎢:[e5}峳ﴱn騎3?腳Hyꏃ膼N潭錖,Yᝋ˜YAၓ㬠bG렣䰣:", + true, + null, + { + "⒛'P&%죮|:⫶춞": -3818336746965687085, + "钖m<\/0ݎMtF2Pk=瓰୮洽겎.": [[ + -8757574841556350607, + -3045234949333270161, + null, + { + "Ꮬr輳>⫇9hU##w@귪A\\C 鋺㘓ꖐ梒뒬묹㹻+郸嬏윤'+g<\/碴,}ꙫ>손;情d齆J䬁ຩ撛챝탹/R澡7剌tꤼ?ặ!`⏲睤\u00002똥଴⟏": null, + "\u20f2ܹe\\tAꥍư\\x当뿖렉禛;G檳ﯪS૰3~㘠#[J<}{奲 5箉⨔{놁<\/釿抋,嚠/曳m&WaOvT赋皺璑텁": [[ + false, + null, + true, + -5.7131445659795661E18, + "萭m䓪D5|3婁ఞ>蠇晼6nﴺPp禽羱DS<睓닫屚삏姿", + true, + [ + -8759747687917306831, + { + ">ⓛ\t,odKr{䘠?b퓸C嶈=DyEᙬ@ᴔ쨺芛髿UT퓻春<\/yꏸ>豚W釺N뜨^?꽴﨟5殺ᗃ翐%>퍂ဿ䄸沂Ea;A_\u0005閹殀W+窊?Ꭼd\u0013P汴G5썓揘": 4.342729067882445E-18, + "Q^즾眆@AN\u0011Kb榰냎Y#䝀ꀒᳺ'q暇睵s\"!3#I⊆畼寤@HxJ9": false, + "⿾D[)袨㇩i]웪䀤ᛰMvR<蟏㣨": {"v퇓L㪱ꖣ豛톤\\곱#kDTN": [{ + "(쾴䡣,寴ph(C\"㳶w\"憳2s馆E!n!&柄<\/0Pꈗſ?㿳Qd鵔": {"娇堰孹L錮h嵅⛤躏顒?CglN束+쨣ﺜ\\MrH": {"獞䎇둃ቲ弭팭^ꄞ踦涟XK錆쳞ឌ`;੶S炥騞ଋ褂B៎{ڒ䭷ᶼ靜pI荗虶K$": [{"◖S~躘蒉꫿輜譝Q㽙闐@ᢗ¥E榁iء5┄^B[絮跉ᰥ遙PWi3wㄾⵀDJ9!w㞣ᄎ{듒ꓓb6\\篴??c⼰鶹⟧\\鮇ꮇ": [[ + 654120831325413520, + -1.9562073916357608E-19, + { + "DC(昐衵ἡ긙갵姭|֛[t": 7.6979110359897907E18, + "J␅))嫼❳9Xfd飉j7猬ᩉ+⤻眗벎E鰉Zᄊ63zၝ69}ZᶐL崭ᦥ⡦靚⋛ꎨ~i㨃咊ꧭo䰠阀3C(": -3.5844809362512589E17, + "p꣑팱쒬ꎑ뛡Ꙩ挴恍胔&7ᔈ묒4Hd硶훐㎖zꢼ豍㿢aሃ=<\/湉鵲EӅ%$F!퍶棌孼{O駍਺geu+": ")\u001b잓kŀX쩫A밁®ڣ癦狢)扔弒p}k縕ꩋ,䃉tࣼi", + "ァF肿輸<솄G-䢹䛸ꊏl`Tqꕗ蒞a氷⸅ᴉ蠰]S/{J왲m5{9.uέ~㕚㣹u>x8U讁B덺襪盎QhVS맅킃i识{벂磄Iහ䙅xZy/抍૭Z鲁-霳V据挦ℒ": null, + "㯛|Nꐸb7ⵐb?拠O\u0014ކ?-(EꞨ4ꕷᄤYᯕOW瞺~螸\"욿ќe㺰\"'㌢ƐW\u0004瞕>0?V鷵엳": true, + "뤥G\\迋䠿[庩'꼡\u001aiᩮV쯁ᳪ䦪Ô;倱ନ뛁誈": null, + "쥹䄆䚟Q榁䎐᢭<\/2㕣p}HW蟔|䃏꿈ꚉ锳2Pb7㙑Tⅹᵅ": { + "Y?֭$>#cVBꩨ:>eL蒁務": { + "86柡0po 䏚&-捑Ћ祌<\/휃-G*㶢הּ쩍s㶟餇c걺yu꽎還5*턧簕Og婥SꝐ": null, + "a+葞h٥ࠆ裈嗫ﵢ5輙퀟ᛜ,QDﹼ⟶Y騠锪E_|x죗j侵;m蜫轘趥?븅w5+mi콛L": { + ";⯭ﱢ!买F⽍柤鶂n䵣V㫚墱2렾ELEl⣆": [ + true, + -3.6479311868339015E-18, + -7270785619461995400, + 3.334081886177621E18, + 2.581457786298155E18, + -6.605252412954115E-20, + -3.9232347037744167E-20, + { + "B6㊕.k1": null, + "ZAꄮJ鮷ᳱo갘硥鈠䠒츼": { + "ᕅ}럡}.@y陪鶁r業'援퀉x䉴ﵴl퍘):씭脴ᥞhiꃰblﲂ䡲엕8߇M㶭0燋標挝-?PCwe⾕J碻Ᾱ䬈䈥뷰憵賣뵓痬+": {"a췩v礗X⋈耓ፊf罅靮!㔽YYᣓw澍33⎔芲F|\"䜏T↮輦挑6ᓘL侘?ᅥ]덆1R௯✎餘6ꏽ<\/௨\\?q喷ꁫj~@ulq": {"嗫欆뾔Xꆹ4H㌋F嵧]ࠎ]㠖1ꞤT<$m뫏O i댳0䲝i": {"?෩?\u20cd슮|ꯆjs{?d7?eNs⢚嫥氂䡮쎱:鑵롟2hJꎒﯭ鱢3춲亄:뼣v䊭諱Yj択cVmR䩃㘬T\"N홝*ै%x^F\\_s9보zz4淗?q": [ + null, + "?", + 2941869570821073737, + "{5{殇0䝾g6밖퍋臩綹R$䖭j紋釰7sXI繳漪행y", + false, + "aH磂?뛡#惇d婅?Fe,쐘+늵䍘\"3r瘆唊勐j⳧࠴ꇓ<\/唕윈x⬌讣䋵%拗ᛆⰿ妴᝔M2㳗必꧂淲?ゥ젯檢<8끒MidX䏒3᳻Q▮佐UT|⤪봦靏⊏", + [[{ + "颉(&뜸귙{y^\"P퟉춝Ჟ䮭D顡9=?}Y誱<$b뱣RvO8cH煉@tk~4ǂ⤧⩝屋SS;J{vV#剤餓ᯅc?#a6D,s": [ + -7.8781018564821536E16, + true, + [ + -2.28770899315832371E18, + false, + -1.0863912140143876E-20, + -6282721572097446995, + 6767121921199223078, + -2545487755405567831, + false, + null, + -9065970397975641765, + [ + -5.928721243413937E-20, + {"6촊\u001a홯kB0w撨燠룉{绎6⳹!턍贑y▾鱧ժ[;7ᨷ∀*땒䪮1x霆Hᩭ☔\"r䝐7毟ᝰr惃3ꉭE+>僒澐": [ + "Ta쎩aƝt쵯ⰪVb", + [ + -5222472249213580702, + null, + -2851641861541559595, + null, + 4808804630502809099, + 5657671602244269874, + "5犲﨣4mᥣ?yf젫꾯|䋬잁$`Iⳉﴷ扳兝,'c", + false, + [ + null, + { + "DyUIN쎾M仼惀⮥裎岶泭lh扠\u001e礼.tEC癯튻@_Qd4c5S熯A<\/\6U윲蹴Q=%푫汹\\\u20614b[௒C⒥Xe⊇囙b,服3ss땊뢍i~逇PA쇸1": -2.63273619193485312E17, + "Mq꺋貘k휕=nK硍뫞輩>㾆~἞ࡹ긐榵l⋙Hw뮢帋M엳뢯v⅃^": 1877913476688465125, + "ᶴ뻗`~筗免⚽টW˃⽝b犳䓺Iz篤p;乨A\u20ef쩏?疊m㝀컩뫡b탔鄃ᾈV(遢珳=뎲ିeF仢䆡谨8t0醄7㭧瘵⻰컆r厡궥d)a阄፷Ed&c﯄伮1p": null, + "⯁w4曢\"(欷輡": "\"M᭫]䣒頳B\\燧ࠃN㡇j姈g⊸⺌忉ꡥF矉স%^", + "㣡Oᄦ昵⫮Y祎S쐐級㭻撥>{I$": -378474210562741663, + "䛒掷留Q%쓗1*1J*끓헩ᦢ﫫哉쩧EↅIcꅡ\\?ⴊl귛顮4": false, + "寔愆샠5]䗄IH贈=d﯊/偶?ॊn%晥D視N򗘈'᫂⚦|X쵩넽z질tskxDQ莮Aoﱻ뛓": true, + "钣xp?&\u001e侉/y䴼~?U篔蘚缣/I畚?Q绊": -3034854258736382234, + "꺲໣眀)⿷J暘pИfAV삕쳭Nꯗ4々'唄ⶑ伻㷯騑倭D*Ok꧁3b␽_<\/챣Xm톰ၕ䆄`*fl㭀暮滠毡?": [ + "D男p`V뙸擨忝븪9c麺`淂⢦Yw⡢+kzܖ\fY1䬡H歁)벾Z♤溊-혰셢?1<-\u0005;搢Tᐁle\\ᛵߓﭩ榩訝-xJ;巡8깊蠝ﻓU$K": { + "Vꕡ諅搓W=斸s︪vﲜ츧$)iꡟ싉e寳?ጭムVથ嵬i楝Fg<\/Z|៪ꩆ-5'@ꃱ80!燱R쇤t糳]罛逇dṌ֣XHiͦ{": true, + "Ya矲C멗Q9膲墅携휻c\\딶G甔<\/.齵휴": -1.1456247877031811E-19, + "z#.OO￝J": -8263224695871959017, + "崍_3夼ᮟ1F븍뽯ᦓ鴭V豈Ь": [{ + "N蒬74": null, + "yuB?厅vK笗!ᔸcXQ旦컶P-녫mᄉ麟_": "1R@ 톘xa_|﩯遘s槞d!d껀筤⬫薐焵먑D{\\6k共倌☀G~AS_D\"딟쬚뮥馲렓쓠攥WTMܭ8nX㩴䕅檹E\u0007ﭨN 2 ℆涐ꥏ꠵3▙玽|됨_\u2048", + "恐A C䧩G": {":M큣5e들\\ꍀ恼ᔄ靸|I﨏$)n": { + "|U䬫㟯SKV6ꛤ㗮\bn봻䲄fXT:㾯쳤'笓0b/ೢC쳖?2浓uO.䰴": "ཐ꼋e?``,ᚇ慐^8ꜙNM䂱\u0001IᖙꝧM'vKdꌊH牮r\\O@䊷ᓵ쀆(fy聻i툺\"?<\/峧ࣞ⓺ᤤ쵒߯ꎺ騬?)刦\u2072l慪y꺜ﲖTj+u", + "뽫hh䈵w>1ⲏ쐭V[ⅎ\\헑벑F_㖝⠗㫇h恽;῝汰ᱼ瀖J옆9RR셏vsZ柺鶶툤r뢱橾/ꉇ囦FGm\"謗ꉦ⨶쒿⥡%]鵩#ᖣ_蹎 u5|祥?O", + null, + 2.0150326776036215E-19, + null, + true, + false, + true, + {"\fa᭶P捤WWc᠟f뚉ᬏ퓗ⳀW睹5:HXH=q7x찙X$)모r뚥ᆟ!Jﳸf": [ + -2995806398034583407, + [ + 6441377066589744683, + "Mﶒ醹i)Gἦ廃s6몞 KJ౹礎VZ螺费힀\u0000冺업{谥'꡾뱻:.ꘘ굄奉攼Di᷑K鶲y繈욊阓v㻘}枭캗e矮1c?휐\"4\u0005厑莔뀾墓낝⽴洗ṹ䇃糞@b1\u0016즽Y轹", + { + "1⽕⌰鉟픏M㤭n⧴ỼD#%鐘⊯쿼稁븣몐紧ᅇ㓕ᛖcw嬀~ഌ㖓(0r⧦Q䑕髍ര铂㓻R儮\"@ꇱm❈௿᦯頌8}㿹犴?xn잆꥽R": 2.07321075750427366E18, + "˳b18㗈䃟柵Z曆VTAu7+㛂cb0﯑Wp執<\/臋뭡뚋刼틮荋벲TLP预庰܈G\\O@VD'鱃#乖끺*鑪ꬳ?Mޞdﭹ{␇圯쇜㼞顄︖Y홡g": [{ + "0a,FZ": true, + "2z̬蝣ꧦ驸\u0006L↛Ḣ4๚뿀'?lcwᄧ㐮!蓚䃦-|7.飑挴.樵*+1ﮊ\u0010ꛌ%貨啺/JdM:똍!FBe?鰴㨗0O财I藻ʔWA᫓G쳛u`<\/I": [{ + "$τ5V鴐a뾆両環iZp頻යn븃v": -4869131188151215571, + "*즢[⦃b礞R◚nΰꕢH=귰燙[yc誘g䆌?ଜ臛": { + "洤湌鲒)⟻\\䥳va}PeAMnN[": "㐳ɪ/(軆lZR,Cp殍ȮN啷\"3B婴?i=r$펽ᤐ쀸", + "阄R4㒿㯔ڀ69ZᲦ2癁핌噗P崜#\\-쭍袛&鐑/$4童V꩑_ZHA澢fZ3": {"x;P{긳:G閉:9?活H": [ + "繺漮6?z犞焃슳\">ỏ[Ⳛ䌜녏䂹>聵⼶煜Y桥[泥뚩MvK$4jtロ", + "E#갶霠좭㦻ୗ먵F+䪀o蝒ba쮎4X㣵 h", + -335836610224228782, + null, + null, + [ + "r1᫩0>danjY짿bs{", + [ + -9.594464059325631E-23, + 1.0456894622831624E-20, + null, + 5.803973284253454E-20, + -8141787905188892123, + true, + -4735305442504973382, + 9.513150514479281E-20, + "7넳$螔忷㶪}䪪l짴\u0007鹁P鰚HF銏ZJﳴ/⍎1ᷓ忉睇ᜋ쓈x뵠m䷐窥Ꮤ^\u0019ᶌ偭#ヂt☆၃pᎍ臶䟱5$䰵&๵分숝]䝈뉍♂坎\u0011<>", + "C蒑貑藁lﰰ}X喇몛;t밿O7/᯹f\u0015kI嘦<ዴ㟮ᗎZ`GWퟩ瑹࡮ᅴB꿊칈??R校s脚", + { + "9珵戬+AU^洘拻ቒy柭床'粙XG鞕᠜繀伪%]hC,$輙?Ut乖Qm떚W8઼}~q⠪rU䤶CQ痗ig@#≲t샌f㈥酧l;y闥ZH斦e⸬]j⸗?ঢ拻퀆滌": null, + "畯}㧢J罚帐VX㨑>1ꢶkT⿄蘥㝑o|<嗸層沈挄GEOM@-䞚䧰$만峬輏䠱V✩5宸-揂D'㗪yP掶7b⠟J㕻SfP?d}v㼂Ꮕ'猘": { + "陓y잀v>╪": null, + "鬿L+7:됑Y=焠U;킻䯌잫!韎ஔ\f": { + "駫WmGጶ": { + "\\~m6狩K": -2586304199791962143, + "ႜࠀ%͑l⿅D.瑢Dk%0紪dḨTI픸%뗜☓s榗኉\"?V籄7w髄♲쟗翛歂E䤓皹t ?)ᄟ鬲鐜6C": { + "_췤a圷1\u000eB-XOy缿請∎$`쳌eZ~杁튻/蜞`塣৙\"⪰\"沒l}蕌\\롃荫氌.望wZ|o!)Hn獝qg}": null, + "kOSܧ䖨钨:಼鉝ꭝO醧S`십`ꓭ쭁ﯢN&Et㺪馻㍢ⅳ㢺崡ຊ蜚锫\\%ahx켨|ż劻ꎄ㢄쐟A躊᰹p譞綨Ir쿯\u0016ﵚOd럂*僨郀N*b㕷63z": { + ":L5r+T㡲": [{ + "VK泓돲ᮙRy㓤➙Ⱗ38oi}LJቨ7Ó㹡৘*q)1豢⛃e᫛뙪壥镇枝7G藯g㨛oI䄽 孂L缊ꋕ'EN`": -2148138481412096818, + "`⛝ᘑ$(खꊲ⤖ᄁꤒ䦦3=)]Y㢌跨NĴ驳줟秠++d孳>8ᎊ떩EꡣSv룃 쯫أ?#E|᭙㎐?zv:5祉^⋑V": [ + -1.4691944435285607E-19, + 3.4128661569395795E17, + "㐃촗^G9佭龶n募8R厞eEw⺡_ㆱ%⼨D뉄퉠2ꩵᛅⳍ搿L팹Lවn=\"慉념ᛮy>!`g!풲晴[/;?[v겁軇}⤳⤁핏∌T㽲R홓遉㓥", + "愰_⮹T䓒妒閤둥?0aB@㈧g焻-#~跬x<\/舁P݄ꐡ=\\׳P\u0015jᳪᢁq;㯏l%᭗;砢觨▝,謁ꍰGy?躤O黩퍋Y㒝a擯\n7覌똟_䔡]fJ晋IAS", + 4367930106786121250, + -4.9421193149720582E17, + null, + { + ";ᄌ똾柉곟ⰺKpፇ䱻ฺ䖝{o~h!eꁿ઻욄ښ\u0002y?xUd\u207c悜ꌭ": [ + 1.6010824122815255E-19, + [ + "宨︩9앉檥pr쇷?WxLb", + "氇9】J玚\u000f옛呲~ 輠1D嬛,*mW3?n휂糊γ虻*ᴫ꾠?q凐趗Ko↦GT铮", + "㶢ថmO㍔k'诔栀Z蛟}GZ钹D", + false, + -6.366995517736813E-20, + -4894479530745302899, + null, + "V%᫡II璅䅛䓎풹ﱢ/pU9se되뛞x梔~C)䨧䩻蜺(g㘚R?/Ự[忓C뾠ࢤc왈邠买?嫥挤풜隊枕", + ",v碍喔㌲쟚蔚톬៓ꭶ", + 3.9625444752577524E-19, + null, + [ + "kO8란뿒䱕馔b臻⍟隨\"㜮鲣Yq5m퐔K#ꢘug㼈ᝦ=P^6탲@䧔%$CqSw铜랊0&m⟭<\/a逎ym\u0013vᯗ": true, + "洫`|XN뤮\u0018詞=紩鴘_sX)㯅鿻Ố싹": 7.168252736947373E-20, + "ꛊ饤ﴏ袁(逊+~⽫얢鈮艬O힉7D筗S곯w操I斞᠈븘蓷x": [[[[ + -7.3136069426336952E18, + -2.13572396712722688E18, + { + "硢3㇩R:o칢行E<=\u0018ၬYuH!\u00044U%卝炼2>\u001eSi$⓷ꒈ'렢gᙫ番ꯒ㛹럥嶀澈v;葷鄕x蓎\\惩+稘UEᖸﳊ㊈壋N嫿⏾挎,袯苷ኢ\\x|3c": 7540762493381776411, + "?!*^ᢏ窯?\u0001ڔꙃw虜돳FgJ?&⨫*uo籤:?}ꃹ=ٴ惨瓜Z媊@ત戹㔏똩Ԛ耦Wt轁\\枒^\\ꩵ}}}ꀣD\\]6M_⌫)H豣:36섘㑜": { + ";홗ᰰU஋㙛`D왔ཿЃS회爁\u001b-㢈`봆?盂㛣듿ᦾ蒽_AD~EEຆ㊋(eNwk=Rɠ峭q\"5Ἠ婾^>'ls\n8QAK)- Q䲌mo펹L_칍樖庫9꩝쪹ᘹ䑖瀍aK ?*趤f뭓廝p=磕", + "哑z懅ᤏ-ꍹux쀭", + [ + true, + 3998739591332339511, + "ጻ㙙?᳸aK<\/囩U`B3袗ﱱ?\"/k鏔䍧2l@쿎VZ쨎/6ꃭ脥|B?31+on颼-ꮧ,O嫚m ࡭`KH葦:粘i]aSU쓙$쐂f+詛頖b", + [{"^<9<箝&絡;%i﫡2攑紴\\켉h쓙-柂䚝ven\u20f7浯-Ꮏ\r^훁䓚헬\u000e?\\ㅡֺJ떷VOt": [{ + "-௄卶k㘆혐஽y⎱㢬sS઄+^瞥h;ᾷj;抭\u0003밫f<\/5Ⱗ裏_朻%*[-撵䷮彈-芈": { + "㩩p3篊G|宮hz䑊o곥j^Co0": [ + 653239109285256503, + {"궲?|\":N1ۿ氃NZ#깩:쇡o8킗ࡊ[\"됸Po핇1(6鰏$膓}⽐*)渽J'DN<썙긘毦끲Ys칖": { + "2Pr?Xjㆠ?搮/?㓦柖馃5뚣Nᦼ|铢r衴㩖\"甝湗ܝ憍": "\"뾯i띇筝牻$珲/4ka $匝휴译zbAᩁꇸ瑅&뵲衯ꎀᆿ7@ꈋ'ᶨH@ᠴl+", + "7뢽뚐v?4^ꊥ_⪛.>pởr渲<\/⢕疻c\"g䇘vU剺dஔ鮥꒚(dv祴X⼹\\a8y5坆": true, + "o뼄B욞羁hr﷔폘뒚⿛U5pꪴfg!6\\\"爑쏍䢱W<ﶕ\\텣珇oI/BK뺡'谑♟[Ut븷亮g(\"t⡎有?ꬊ躺翁艩nl F⤿蠜": 1695826030502619742, + "ۊ깖>ࡹ햹^ⵕ쌾BnN〳2C䌕tʬ]찠?ݾ2饺蹳ぶꌭ訍\"◹ᬁD鯎4e滨T輀ﵣ੃3\u20f3킙D瘮g\\擦+泙ၧ 鬹ﯨַ肋7놷郟lP冝{ߒhড়r5,꓋": null, + "ΉN$y{}2\\N﹯ⱙK'8ɜͣwt,.钟廣䎘ꆚk媄_": null, + "䎥eᾆᝦ읉,Jުn岪㥐s搖謽䚔5t㯏㰳㱊ZhD䃭f絕s鋡篟a`Q鬃┦鸳n_靂(E4迠_觅뷝_宪D(NL疶hL追V熑%]v肫=惂!㇫5⬒\u001f喺4랪옑": { + "2a輍85먙R㮧㚪Sm}E2yꆣꫨrRym㐱膶ᔨ\\t綾A☰.焄뙗9<쫷챻䒵셴᭛䮜.<\/慌꽒9叻Ok䰊Z㥪幸k": [ + null, + true, + {"쌞쐍": { + "▟GL K2i뛱iQ\"̠.옛1X$}涺]靎懠ڦ늷?tf灟ݞゟ{": 1.227740268699265E-19, + "꒶]퓚%ฬK❅": [{ + "(ෛ@Ǯっ䧼䵤[aテൖvEnAdU렖뗈@볓yꈪ,mԴ|꟢캁(而첸죕CX4Y믅": "2⯩㳿ꢚ훀~迯?᪑\\啚;4X\u20c2襏B箹)俣eỻw䇄", + "75༂f詳䅫ꐧ鏿 }3\u20b5'∓䝱虀f菼Iq鈆﨤g퍩)BFa왢d0뮪痮M鋡nw∵謊;ꝧf美箈ḋ*\u001c`퇚퐋䳫$!V#N㹲抗ⱉ珎(V嵟鬒_b㳅\u0019": null, + "e_m@(i㜀3ꦗ䕯䭰Oc+-련0뭦⢹苿蟰ꂏSV䰭勢덥.ྈ爑Vd,ᕥ=퀍)vz뱊ꈊB_6듯\"?{㒲&㵞뵫疝돡믈%Qw限,?\r枮\"? N~癃ruࡗdn&": null, + "㉹&'Pfs䑜공j<\/?|8oc᧨L7\\pXᭁ 9᪘": -2.423073789014103E18, + "䝄瑄䢸穊f盈᥸,B뾧푗횵B1쟢f\u001f凄": "魖⚝2儉j꼂긾껢嗎0ࢇ纬xI4](੓`蕞;픬\fC\"斒\")2櫷I﹥迧", + "ퟯ詔x悝령+T?Bg⥄섅kOeQ큼㻴*{E靼6氿L缋\u001c둌๶-㥂2==-츫I즃㠐Lg踞ꙂEG貨鞠\"\u0014d'.缗gI-lIb䋱ᎂDy缦?": null, + "紝M㦁犿w浴詟棓쵫G:䜁?V2ힽ7N*n&㖊Nd-'ຊ?-樹DIv⊜)g䑜9뉂ㄹ푍阉~ꅐ쵃#R^\u000bB䌎䦾]p.䀳": [{"ϒ爛\"ꄱ︗竒G䃓-ま帳あ.j)qgu扐徣ਁZ鼗A9A鸦甈!k蔁喙:3T%&㠘+,䷞|챽v䚞문H<\/醯r셓㶾\\a볜卺zE䝷_죤ဵ뿰᎟CB": [ + 6233512720017661219, + null, + -1638543730522713294, + false, + -8901187771615024724, + [ + 3891351109509829590, + true, + false, + -1.03836679125188032E18, + { + "j랎:g曞ѕᘼ}链N", + -1.1103819473845426E-19, + true, + [ + true, + null, + -7.9091791735309888E17, + true, + {"}蔰鋈+ꐨ啵0?g*사%`J?*": [{ + "\"2wG?yn,癷BK\\龞䑞x?蠢": -3.7220345009853505E-19, + ";饹়❀)皋`噿焒j(3⿏w>偍5X薙婏聿3aFÆÝ": "2,ꓴg?_섦_>Y쪥션钺;=趘F~?D㨫\bX?㹤+>/믟kᠪ멅쬂Uzỵ]$珧`m雁瑊ඖ鯬cꙉ梢f묛bB", + "♽n$YjKiXX*GO贩鏃豮祴遞K醞眡}ꗨv嵎꼷0୸+M菋eH徸J꣆:⼐悥B켽迚㯃b諂\u000bjꠜ碱逮m8": [ + "푷᣺ﻯd8ﱖ嬇ភH鹎⡱᱅0g:果6$GQ췎{vᷧYy-脕x偹砡館⮸C蓼ꏚ=軄H犠G谖ES詤Z蠂3l봟hᅭ7䦹1GPQG癸숟~[#駥8zQ뛣J소obg,", + null, + 1513751096373485652, + null, + -6.851466660824754E-19, + {"䩂-⴮2ٰK솖풄꾚ႻP앳1H鷛wmR䗂皎칄?醜<\/&ࠧ㬍X濬䵈K`vJ륒Q/IC묛!;$vϑ": { + "@-ꚗxྐྵ@m瘬\u0010U絨ﮌ驐\\켑寛넆T=tQ㭤L연@脸삯e-:⩼u㎳VQ㋱襗ຓ<Ⅶ䌸cML3+\u001e_C)r\\9+Jn\\Pﺔ8蠱檾萅Pq鐳话T䄐I": -1.80683891195530061E18, + "ᷭዻU~ཷsgSJ`᪅'%㖔n5픆桪砳峣3獮枾䌷⊰呀": { + "Ş੉䓰邟自~X耤pl7间懑徛s첦5ਕXexh⬖鎥᐀nNr(J컗|ૃF\"Q겮葲놔엞^겄+㈆话〾희紐G'E?飕1f❼텬悚泬먐U睬훶Qs": false, + "(\u20dag8큽튣>^Y{뤋.袊䂓;_g]S\u202a꽬L;^'#땏bႌ?C緡<䝲䲝断ꏏ6\u001asD7IK5Wxo8\u0006p弊⼂ꯍ扵\u0003`뵂픋%ꄰ⫙됶l囏尛+䗅E쟇\\": [ + true, + { + "\n鱿aK㝡␒㼙2촹f;`쾏qIࡔG}㝷䐍瓰w늮*粅9뒪ㄊCj倡翑閳R渚MiUO~仨䜶RꙀA僈㉋⦋n{㖥0딿벑逦⥻0h薓쯴Ꝼ": [ + 5188716534221998369, + 2579413015347802508, + 9.010794400256652E-21, + -6.5327297761238093E17, + 1.11635352494065523E18, + -6656281618760253655, + { + "": ")?", + "TWKLꑙ裑꺔UE俸塑炌Ũ᜕-o\"徚#": {"M/癟6!oI51ni퐚=댡>xꍨ\u0004 ?": { + "皭": {"⢫䋖>u%w잼<䕏꘍P䋵$魋拝U䮎緧皇Y훂&|羋ꋕ잿cJ䨈跓齳5\u001a삱籷I꿾뤔S8㌷繖_Yឯ䲱B턼O歵F\\l醴o_欬6籏=D": [ + false, + true, + {"Mt|ꏞD|F궣MQ뵕T,띺k+?㍵i": [ + 7828094884540988137, + false, + { + "!༦鯠,&aﳑ>[euJꏽ綷搐B.h": -7648546591767075632, + "-n켧嘰{7挐毄Y,>❏螵煫乌pv醑Q嶚!|⌝責0왾덢ꏅ蛨S\\)竰'舓Q}A釡5#v": 3344849660672723988, + "8閪麁V=鈢1녈幬6棉⪮둌\u207d᚛驉ꛃ'r䆉惏ै|bἧﺢᒙ<=穊强s혧eꮿ慩⌡ \\槳W븧J檀C,ᘉ의0俯퀉M;筷ࣴ瓿{늊埂鄧_4揸Nn阼Jੵ˥(社": true, + "o뼀vw)4A뢵(a䵢)p姃뛸\u000fK#KiQp\u0005ꅍ芅쏅": null, + "砥$ꥸ┇耽u斮Gc{z빔깎밇\\숰\u001e괷各㶇쵿_ᴄ+h穢p촀Ნ䃬z䝁酳ӂ31xꔄ1_砚W렘G#2葊P ": [ + -3709692921720865059, + null, + [ + 6669892810652602379, + -135535375466621127, + "뎴iO}Z? 馢녱稹ᄾ䐩rSt帤넆&7i騏멗畖9誧鄜'w{Ͻ^2窭외b㑎粖i矪ꦨ탪跣)KEㆹ\u0015V8[W?⽉>'kc$䨘ᮛ뉻٬M5", + 1.10439588726055846E18, + false, + -4349729830749729097, + null, + [ + false, + "_蠢㠝^䟪/D녒㡋ỎC䒈판\u0006એq@O펢%;鹐쏌o戥~A[ꡉ濽ỳ&虃᩾荣唙藍茨Ig楡꒻M窓冉?", + true, + 2.17220752996421728E17, + -5079714907315156164, + -9.960375974658589E-20, + "ᾎ戞༒", + true, + false, + [[ + "ⶉᖌX⧕홇)g엃⹪x뚐癟\u0002", + -5185853871623955469, + { + "L㜤9ợㇶK鐰⋓V뽋˖!斫as|9"፬䆪?7胜&n薑~": -2.11545634977136992E17, + "O8뀩D}캖q萂6༣㏗䈓煮吽ਆᎼDᣘ폛;": false, + "YTᡅ^L㗎cbY$pᣞ縿#fh!ꘂb삵玊颟샞ဢ$䁗鼒몁~rkH^:닮먖츸륈⪺쒉砉?㙓扫㆕꣒`R䢱B酂?C뇞<5Iޚ讳騕S瞦z": null, + "\\RB?`mG댵鉡幐物䵎有5*e骄T㌓ᛪ琾駒Ku\u001a[柆jUq8⋈5鿋츿myﻗ?雍ux঴?": 5828963951918205428, + "n0晅:黯 xu씪^퓞cB㎊ᬍ⺘٤փ~B岚3㥕擄vᲂ~F?C䶖@$m~忔S왖㲚?챴⊟W#벌{'㰝I䝠縁s樘\\X뢻9핡I6菍ㄛ8쯶]wॽ0L\"q": null, + "x增줖j⦦t䏢᎙㛿Yf鼘~꫓恄4惊\u209c": "oOhbᤃ᛽z&Bi犑\\3B㩬劇䄑oŁ쨅孥멁ຖacA㖫借㞝vg싰샂㐜#譞⢤@k]鋰嘘䜾L熶塥_<\/⍾屈ﮊ_mY菹t뙺}Ox=w鮮4S1ꐩמּ'巑", + "㗓蟵ꂾe蠅匳(JP䗏෸\u0089耀왲": [{ + "ᤃ㵥韎뤽\r?挥O쯡⇔㞚3伖\u0005P⋪\"D궣QLn(⚘罩䩢Ŏv䤘尗뼤됛O淽鋋闚r崩a{4箙{煷m6〈": { + "l곺1L": { + "T'ਤ?砅|੬Km]䄩\"(࿶<\/6U爢䫈倔郴l2㴱^줣k'L浖L鰄Rp今鎗⒗C얨M훁㡧ΘX粜뫈N꤇輊㌻켑#㮮샶-䍗룲蠝癜㱐V>=\\I尬癤t=": 7648082845323511446, + "鋞EP:<\/_`ၧe混ㇹBd⯢㮂驋\\q碽饩跓྿ᴜ+j箿렏㗑yK毢宸p謹h䦹乕U媣\\炤": [[ + "3", + [ + true, + 3.4058271399411134E-20, + true, + "揀+憱f逮@먻BpW曉\u001a㣐⎊$n劈D枤㡞좾\u001aᛁ苔౩闝1B䷒Ṋ݋➐ꀞꐃ磍$t੤_:蘺⮼(#N", + 697483894874368636, + [ + "vᘯ锴)0訶}䳅⩚0O壱韈ߜ\u0018*U鍾䏖=䧉뽑单휻ID쿇嘗?ꌸῬ07", + -5.4858784319382006E18, + 7.5467775182251151E18, + -8911128589670029195, + -7531052386005780140, + null, + [ + null, + true, + [[{ + "1欯twG<\/Q:0怯押殃탷聫사<ỗꕧ蚨䡁nDꌕ\u001c녬~蓩鲃g儊>ꏡl㻿/⑷*챳6㻜W毤緛ﹺᨪ4\u0013뺚J髬e3쳸䘦伧?恪&{L掾p+꬜M䏊d娘6": { + "2p첼양棜h䜢﮶aQ*c扦v︥뮓kC寵횂S銩&ǝ{O*य़iH`U큅ࡓr䩕5ꄸ?`\\᧫?ᮼ?t〟崾훈k薐ì/iy꤃뵰z1<\/AQ#뿩8jJ1z@u䕥": 1.82135747285215155E18, + "ZdN &=d년ᅆ'쑏ⅉ:烋5&៏ᄂ汎来L㯄固{钧u\\㊏튚e摑&t嗄ꖄUb❌?m䴘熚9EW": [{ + "ଛ{i*a(": -8.0314147546006822E17, + "⫾ꃆY\u000e+W`௸ \"M뒶+\\뷐lKE}(NT킶Yj選篒쁶'jNQ硾(똡\\\"逌ⴍy? IRꜘ὞鄬﨧:M\\f⠋Cꚜ쫊ᚴNV^D䕗ㅖἔIao꿬C⍏8": [ + 287156137829026547, + { + "H丞N逕⯲": {"": { + "7-;枮阕梒9ᑄZ": [[[[ + null, + { + "": [[[[ + -7.365909561486078E-19, + 2948694324944243408, + null, + [ + true, + "荒\"并孷䂡쵼9o䀘F\u0002龬7⮹Wz%厖/*? a*R枈㌦됾g뒠䤈q딄㺿$쮸tᶎ릑弣^鏎<\/Y鷇驜L鿽<\/춋9Mᲆឨ^<\/庲3'l낢", + "c鮦\u001b두\\~?眾ಢu݆綑෪蘛轋◜gȃ<\/ⴃcpkDt誩܅\"Y", + [[ + null, + null, + [ + 3113744396744005402, + true, + "v(y", + { + "AQ幆h쾜O+꺷铀ꛉ練A蚗⼺螔j㌍3꽂楎䥯뎸먩?": null, + "蠗渗iz鱖w]擪E": 1.2927828494783804E-17, + "튷|䀭n*曎b✿~杤U]Gz鄭kW|㴚#㟗ഠ8u擨": [[ + true, + null, + null, + {"⾪壯톽g7?㥜ώQꑐ㦀恃㧽伓\\*᧰閖樧뢇赸N휶䎈pI氇镊maᬠ탷#X?A+kНM ༑᩟؝?5꧎鰜ṚY즫궔 =ঈ;ﳈ?*s|켦蜌wM笙莔": [ + null, + -3808207793125626469, + [ + -469910450345251234, + 7852761921290328872, + -2.7979740127017492E18, + 1.4458504352519893E-20, + true, + "㽙깹?먏䆢:䴎ۻg殠JBTU⇞}ꄹꗣi#I뵣鉍r혯~脀쏃#釯:场:䔁>䰮o'㼽HZ擓௧nd", + [ + 974441101787238751, + null, + -2.1647718292441327E-19, + 1.03602824249831488E18, + [ + null, + 1.0311977941822604E-17, + false, + true, + { + "": -3.7019778830816707E18, + "E峾恆茍6xLIm縂0n2视֯J-ᤜz+ᨣ跐mYD豍繹⹺䊓몓ﴀE(@詮(!Y膽#᎙2䟓섣A䈀㟎,囪QbK插wcG湎ꤧtG엝x⥏俎j'A一ᯥ뛙6ㅑ鬀": 8999803005418087004, + "よ殳\\zD⧅%Y泥簳Uꈩ*wRL{3#3FYHା[d岀䉯T稉駅䞘礄P:闈W怏ElB㤍喬赔bG䠼U଄Nw鰯闀楈ePsDꥷ꭬⊊": [ + 6.77723657904486E-20, + null, + [ + "ཚ_뷎꾑蹝q'㾱ꂓ钚蘞慵렜떆`ⴹ⎼櫯]J?[t9Ⓢ !컶躔I᮸uz>3a㠕i,錃L$氰텰@7녫W㸮?羧W뇧ꃞ,N鋮숪2ɼ콏┍䁲6", + "&y?뢶=킕올Za惻HZk>c\u20b58i?ꦶcfBv잉ET9j䡡", + "im珊Ճb칧校\\뼾쯀", + 9.555715121193197E-20, + true, + { + "<㫚v6腓㨭e1㕔&&V∌ᗈT奄5Lጥ>탤?튣瑦㳆ꉰ!(ᙪ㿬擇_n쌯IMΉ㕨␰櫈ᱷ5풔蟹&L.첽e鰷쯃劼﫭b#ﭶ퓀7뷄Wr㢈๧Tʴશ㶑澕鍍%": -1810142373373748101, + "fg晌o?߲ꗄ;>C>?=鑰監侯Kt굅": true, + "䫡蓺ꑷ]C蒹㦘\"1ః@呫\u0014NL䏾eg呮፳,r$裢k>/\\?ㄤᇰﻛ쉕1஥'Ċ\" \\_?쨔\"ʾr: 9S䘏禺ᪧꄂ㲄", + [[{ + "*硙^+E쌺I1䀖ju?:⦈Ꞓl๴竣迃xKC/饉:\fl\"XTFᄄ蟭,芢<\/骡軺띜hꏘ\u001f銿<棔햳▨(궆*=乥b8\\媦䷀뫝}닶ꇭ(Kej䤑M": [{ + "1Ꮼ?>옿I╅C<ގ?ꊌ冉SV5A㢊㶆z-๎玶绢2F뵨@㉌뀌o嶔f9-庒茪珓뷳4": null, + ";lᰳ": "CbB+肻a䄷苝*/볳+/4fq=㰁h6瘉샴4铢Y骐.⌖@哼猎㦞+'gꋸ㒕ߤ㞑(䶒跲ti⑴a硂#No볔", + "t?/jE幸YHT셵⩎K!Eq糦ꗣv刴w\"l$ο:=6:移": { + "z]鑪醊嫗J-Xm銌翁絨c里됏炙Ep㣋鏣똼嚌䀓GP﹖cmf4鹭T䅿꣭姧␸wy6ꦶ;S&(}ᎧKxᾂQ|t뻳k\"d6\"|Ml췆hwLt꼼4$&8Պ褵婶鯀9": {"嵃닢ᒯ'd᧫䳳#NXe3-붋鸿ଢ떓%dK\u0013䲎ꖍYV.裸R⍉rR3蟛\\:젯:南ĺLʆ넕>|텩鴷矔ꋅⒹ{t孶㓑4_": [ + true, + null, + [ + false, + "l怨콈lᏒ", + { + "0w䲏嬧-:`䉅쉇漧\\܂yㄨb%㽄j7ᦶ涶<": 3.7899452730383747E-19, + "ꯛTẀq纤q嶏V⿣?\"g}ი艹(쥯B T騠I=仵및X": {"KX6颠+&ᅃ^f畒y[": { + "H?뱜^?꤂-⦲1a㋞&ꍃ精Ii᤾챪咽쬘唂쫷<땡劈훫놡o㥂\\ KⴙD秼F氮[{'좴:례晰Iq+I쭥_T綺砸GO煝䟪ᚪ`↹l羉q쐼D꽁ᜅ훦: vUV": true, + "u^yﳍ0㱓#[y뜌앸ꊬL㷩?蕶蘾⻍KӼ": -7931695755102841701, + "䤬轉車>\u001c鴵惋\"$쯃྆⇻n뽀G氠S坪]ಲꨍ捇Qxኻ椕駔\\9ࣼ﫻읜磡煮뺪ᶚ볝l㕆t+sζ": [[[ + true, + false, + [ + null, + 3363739578828074923, + true, + { + "\"鸣詩 볰㑵gL㯦῅춝旫}ED辗ﮈI쀤-ꧤ|㠦Z\"娑ᕸ4爏騍㣐\"]쳝Af]茛⬻싦o蚁k䢯䩐菽3廇喑ޅ": 4.5017999150704666E17, + "TYႇ7ʠ值4챳唤~Zo&ݛ": false, + "`塄J袛㭆끺㳀N㺣`꽐嶥KﯝSVᶔ∲퀠獾N딂X\"ᤏhNﬨvI": {"\u20bb㭘I䖵䰼?sw䂷쇪](泒f\"~;꼪Fԝsᝦ": {"p,'ꉂ軿=A蚶?bƉ㏵䅰諬'LYKL6B깯⋩겦뎙(ᜭ\u0006噣d꾆㗼Z;䄝䚔cd<情@䞂3苼㸲U{)<6&ꩻ钛\u001au〷N숨囖愙j=BXW욕^x芜堏Ῑ爂뛷꒻t✘Q\b": [[ + "籛&ଃ䩹.ꃩ㦔\\C颫#暪&!勹ꇶ놽攺J堬镙~軌C'꾖䣹㮅岃ᙴ鵣", + 4.317829988264744E15, + 6.013585322002147E-20, + false, + true, + null, + null, + -3.084633632357326E-20, + false, + null, + { + "\"짫愔昻 X\"藣j\"\"먁ཅѻ㘤㬯0晲DU꟒㸃d벀윒l䦾c੻*3": null, + "谈Wm陧阦咟ฯ歖擓N喴㋐銭rCCnVࢥ^♼Ⅾ젲씗刊S༝+_t赔\\b䚍뉨ꬫ6펛cL䊘᜼<\/澤pF懽&H": [ + null, + { + "W\"HDUuΌ퀟M'P4࿰H똆ⰱﮯ<\/凐蘲\"C鴫ﭒж}ꭩ쥾t5yd诪ﮡ퍉ⴰ@?氐醳rj4I6Qt": 6.9090159359219891E17, + "絛ﳛ⺂": {"諰P㗮聦`ZQ?ꫦh*റcb⧱}埌茥h{棩렛툽o3钛5鮁l7Q榛6_g)ὄ\u0013kj뤬^爖eO4Ⱈ槞鉨ͺ订%qX0T썗嫷$?\\\"봅늆'%": [ + -2.348150870600346E-19, + [[ + true, + -6619392047819511778, + false, + [[ + -1.2929189982356161E-20, + 1.7417192219309838E-19, + {"?嵲2࿐2\u0001啑㷳c縯": [ + null, + [ + false, + true, + 2578060295690793218, + { + "?\"殃呎#㑑F": true, + "}F炊_殛oU헢兔Ꝉ,赭9703.B数gTz3⏬": { + "5&t3,햓Mݸᵣ㴵;꣫䩍↳#@뫷䠅+W-ࣇzᓃ鿕ಔ梭?T䮑ꥬ旴]u뫵막bB讍:왳둛lEh=숾鱠p咐$짏#?g⹷ᗊv㷵.斈u頻\u0018-G.": "뽙m-ouࣤ஫牷\"`Ksꕞ筼3HlȨvC堈\"I]㖡玎r먞#'W賜鴇k'c룼髋䆿飉㗆xg巤9;芔cጐ/ax䊨♢큓r吓㸫೼䢗da᩾\"]屣`", + ":M딪<䢥喠\u0013㖅x9蕐㑂XO]f*Q呰瞊吭VP@9,㨣 D\\穎vˤƩs㜂-曱唅L걬/롬j㈹EB8g<\/섩o渀\"u0y&룣": ">氍緩L/䕑돯Ꟙ蕞^aB뒣+0jK⪄瑨痜LXK^힦1qK{淚t츔X:Vm{2r獁B뾄H첚7氥?쉟䨗ꠂv팳圎踁齀\\", + "D彤5㢷Gꪻ[lㄆ@὜⓰絳[ଃ獽쮹☒[*0ꑚ㜳": 9022717159376231865, + "ҖaV銣tW+$魿\u20c3亜~뫡ᙰ禿쨽㏡fṼzE/h": "5臐㋇Ჯ쮺? 昨탰Wム밎#'\"崲钅U?幫뺀⍾@4kh>騧\\0ҾEV=爐͌U捀%ꉼ 㮋<{j]{R>:gԩL\u001c瀈锌ﯲﳡꚒ'⫿E4暍㌗뵉X\"H᝜", + "ᱚגּ;s醒}犍SἿ㦣&{T$jkB\\\tḮ앾䤹o<避(tW": "vb⯽䴪䮢@|)", + "⥒퐁껉%惀뗌+녣迺顀q條g⚯i⤭룐M琹j̈́⽜A": -8385214638503106917, + "逨ꊶZ<\/W⫟솪㎮ᘇb?ꠔi\"H㧺x෷韒Xꫨฟ|]窽\u001a熑}Agn?Mᶖa9韲4$3Ỵ^=쏍煤ፐ돷2䣃%鷠/eQ9頸쥎", + 2398360204813891033, + false, + 3.2658897259932633E-19, + null, + "?ꚃ8Nn㞷幵d䲳䱲뀙ꪛQ瑓鎴]䩋-鰾捡䳡??掊", + false, + -1309779089385483661, + "ᦲxu_/yecR.6芏.ᜇ過 ~", + -5658779764160586501, + "쒌:曠=l썜䢜wk#s蕚\"互㮉m䉤~0듐䋙#G;h숄옥顇෤勹(C7㢅雚㐯L⠅VV簅<", + null, + -4.664877097240962E18, + -4.1931322262828017E18, + { + ",": { + "v㮟麑䄠뤵g{M띮.\u001bzt뢜뵡0Ǥ龍떟Ᾰ怷ϓRT@Lꀌ樂U㏠⾕e扉|bJg(뵒㠶唺~ꂿ(땉x⻫싉쁊;%0鎻V(o\f,N鏊%nk郼螺": -1.73631993428376141E18, + "쟧摑繮Q@Rᕾ㭚㾣4隅待㓎3蒟": [ + 4971487283312058201, + 8973067552274458613, + { + "`a揙ᣗ\u0015iBo¸": 4.3236479112537999E18, + "HW&퉡ぁ圍Y?瑡Qy훍q!帰敏s舠㫸zꚗaS歲v`G株巷Jp6킼 (귶鍔⾏⡈>M汐㞍ቴ꙲dv@i㳓ᇆ?黍": [ + null, + 4997607199327183467, + "E㻎蠫ᐾ高䙟蘬洼旾﫠텛㇛?'M$㣒蔸=A_亀绉앭rN帮", + null, + [{ + "Eᑞ)8餧A5u&㗾q?": [ + -1.969987519306507E-19, + null, + [ + 3.42437673373841E-20, + true, + "e걷M墁\"割P␛퍧厀R䱜3ﻴO퓫r﹉⹊", + [ + -8164221302779285367, + [ + true, + null, + "爘y^-?蘞Ⲽꪓa␅ꍨ}I", + 1.4645984996724427E-19, + [{ + "tY좗⧑mrzﺝ㿥ⴖ᥷j諅\u0000q賋譁Ꞅ⮱S\nࡣB/큃굪3Zɑ复o<\/;롋": null, + "彟h浠_|V4䦭Dᙣ♞u쿻=삮㍦\u001e哀鬌": [{"6횣楠,qʎꗇ鎆빙]㱭R굋鈌%栲j分僅ペ䇰w폦p蛃N溈ꡐꏀ?@(GI뉬$ﮄ9誁ꓚ2e甸ڋ[䁺,\u0011\u001cࢃ=\\+衪䷨ᯕ鬸K": [[ + "ㅩ拏鈩勥\u000etgWVXs陂規p狵w퓼{뮵_i\u0002ퟑႢ⬐d6鋫F~챿搟\u0096䚼1ۼ칥0꣯儏=鋷牋ⅈꍞ龐", + -7283717290969427831, + true, + [ + 4911644391234541055, + { + "I鈒첽P릜朸W徨觘-Hᎄ퐟⓺>8kr1{겵䍃〛ᬡ̨O귑o䝕'쿡鉕p5": "fv粖RN瞖蛐a?q꤄\u001d⸥}'ꣴ犿ꦼ?뤋?鵆쥴덋䡫s矷̄?ඣ/;괱絢oWfV<\/\u202cC,㖦0䑾%n賹g&T;|lj_欂N4w", + "짨䠗;䌕u i+r๏0": [{"9䥁\\఩8\"馇z䇔<\/ႡY3e狚쐡\"ุ6ﰆZ遖c\"Ll:ꮾ疣<\/᭙O◌납୕湞9⡳Und㫜\u0018^4pj1;䧐儂䗷ୗ>@e톬": { + "a⑂F鋻Q螰'<퇽Q贝瀧{ᘪ,cP&~䮃Z?gI彃": [ + -1.69158726118025933E18, + [ + "궂z簽㔛㮨瘥⤜䛖Gℤ逆Y⪾j08Sn昞ꘔ캻禀鴚P謦b{ꓮmN靐Mᥙ5\"睏2냑I\u0011.L&=?6ᄠ뻷X鸌t刑\"#z)o꫚n쳟줋", + null, + 7517598198523963704, + "ኑQp襟`uᩄr方]*F48ꔵn俺ሙ9뇒", + null, + null, + 6645782462773449868, + 1219168146640438184, + null, + { + ")ယ넌竀Sd䰾zq⫣⏌ʥ\u0010ΐ' |磪&p牢蔑mV蘸૰짬꺵;K": [ + -7.539062290108008E-20, + [ + true, + false, + null, + true, + 6574577753576444630, + [[ + 1.2760162530699766E-19, + [ + null, + [ + "顊\\憎zXB,", + [{ + "㇆{CVC9-MN㜋ઘR눽#{h@ퟨ!鼚׼XOvXS\u0017ᝣ=cS+梽៲綆16s덽휐y屬?ᇳG2ᴭ\u00054쫖y룇nKcW̭炦s/鰘ᬽ?J|퓀髣n勌\u0010홠P>j": false, + "箴": [ + false, + "鍞j\"ꮾ*엇칬瘫xṬ⭽쩁䃳\"-⋵?ᦽ댎Ĝ": true, + "Pg帯佃籛n㔠⭹࠳뷏≻࿟3㞱!-쒾!}쭪䃕!籿n涻J5ਲ਼yvy;Rኂ%ᔡጀ裃;M⣼)쵂쑈": 1.80447711803435366E18, + "ꈑC⡂ᑆ㤉壂뎃Xub<\/쀆༈憓ق쨐ק\\": [ + 7706977185172797197, + {"": {"K╥踮砆NWࡆFy韣7ä밥{|紒︧䃀榫rᩛꦡTSy잺iH8}ퟴ,M?Ʂ勺ᴹ@T@~꾂=I㙕뾰_涀쑜嫴曣8IY?ҿo줫fऒ}\\S\"ᦨ뵼#nDX": { + "♘k6?଱癫d68?㽚乳䬳-V顷\u0005蝕?\u0018䞊V{邾zじl]雏k臤~ൖH뒐iꢥ]g?.G碄懺䔛pR$䅒X觨l봜A刊8R梒',}u邩퉕?;91Ea䈈믁G⊶芔h袪&廣㺄j;㡏綽\u001bN頸쳘橆": -2272208444812560733, + "拑Wﵚj鵼駳Oࣿ)#㾅顂N傓纝y僱栜'Bꐍ-!KF*ꭇK¦?䈴^:啤wG逭w᧯": "xᣱmYe1ۏ@霄F$ě꧘푫O䤕퀐Pq52憬ꀜ兴㑗ᡚ?L鷝ퟐ뭐zJꑙ}╆ᅨJB]\"袌㺲u8䯆f", + "꿽၅㔂긱Ǧ?SI": -1669030251960539193, + "쇝ɨ`!葎>瞺瘡驷錶❤ﻮ酜=": -6961311505642101651, + "?f7♄꫄Jᡔ훮e읇퍾፣䭴KhखT;Qty}O\\|뫁IῒNe(5惁ꥶㆷY9ﮡ\\ oy⭖-䆩婁m#x봉>Y鈕E疣s驇↙ᙰm<": {"퉻:dꂁ&efᅫ쫢[\"돈늖꺙|Ô剐1͖-K:ʚ᭕/;쏖㷛]I痐职4gZ4⍜kเꛘZ⥺\\Bʫᇩ鄨魢弞&幟ᓮ2̊盜", + -9006004849098116748, + -3118404930403695681, + { + "_彃Y艘-\"Xx㤩㳷瑃?%2䐡鵛o귵옔夘v*탋职&㳈챗|O钧": [ + false, + "daꧺdᗹ羞쯧H㍤鄳頳<型孒ン냆㹀f4㹰\u000f|C*ሟ鰠(O<ꨭ峹ipຠ*y೧4VQ蔔hV淬{?ᵌEfrI_", + "j;ꗣ밷邍副]ᗓ", + -4299029053086432759, + -5610837526958786727, + [ + null, + [ + -1.3958390678662759E-19, + { + "lh좈T_믝Y\"伨\u001cꔌG爔겕ꫳ晚踍⿻읐T䯎]~e#฽燇\"5hٔ嶰`泯r;ᗜ쮪Q):/t筑,榄&5懶뎫狝(": [{ + "2ፁⓛ]r3C攟וּ9賵s⛔6'ஂ|\"ⵈ鶆䐹禝3\"痰ࢤ霏䵩옆䌀?栕r7O簂Isd?K᫜`^讶}z8?z얰T:X倫⨎ꑹ": -6731128077618251511, + "|︦僰~m漿햭\\Y1'Vvخ굇ቍ챢c趖": [null] + }], + "虌魿閆5⛔煊뎰㞤ᗴꥰF䮥蘦䂪樳-K᝷-(^\u20dd_": 2.11318679791770592E17 + } + ] + ] + ]}, + "묗E䀳㧯᳀逞GMc\b墹㓄끖Ơ&U??펌鑍 媋k))ᄊ": null, + "묥7콽벼諌J_DɯﮪM殴䣏,煚ྼ`Y:씧<\/⩫%yf䦀!1Ჶk춎Q米W∠WC跉鬽*ᛱi㴕L꘻ꀏ쓪\"_g鿄'#t⽙?,Wg㥖|D鑆e⥏쪸僬h鯔咼ඡ;4TK聎졠嫞" + } + ] + ] + } + ] + ] + ]}} + } + ]} + }, + "뿋뀾淣截䔲踀&XJ펖꙯^Xb訅ꫥgᬐ>棟S\"혧騾밫겁7-": "擹8C憎W\"쵮yR뢩浗絆䠣簿9䏈引Wcy䤶孖ꯥ;퐌]輩䍐3@{叝 뽸0ᡈ쵡Ⲇ\u001dL匁꧐2F~ݕ㪂@W^靽L襒ᦘ~沦zZ棸!꒲栬R" + } + ] + ], + "Z:덃൛5Iz찇䅄駠㭧蓡K1": "e8᧤좱U%?ⵇ䯿鿝\u0013縮R∱骒EO\u000fg?幤@֗퉙vU`", + "䐃쪈埽້=Ij,쭗쓇చ": false + }]}} + ] + } + ]} + } + ] + ] + ], + "咰긖VM]᝼6䓑쇎琺etDҌ?㞏ꩄ퇫밉gj8蠃\"⩐5䛹1ࣚ㵪": "ക蹊?⎲⧘⾚̀I#\"䈈⦞돷`wo窭戕෱휾䃼)앷嵃꾞稧,Ⴆ윧9S?೗EMk3Მ3+e{⹔Te驨7䵒?타Ulg悳o43" + } + ], + "zQᤚ纂땺6#ٽ﹧v￿#ࠫ휊冟蹧텈ꃊʆ?&a䥯De潝|쿓pt瓞㭻啹^盚2Ꝋf醪,얏T窧\\Di䕎谄nn父ꋊE": -2914269627845628872, + "䉩跐|㨻ᷢ㝉B{蓧瞸`I!℄욃힕#ೲᙾ竛ᔺCjk췒늕貭词\u0017署?W딚%(pꍁ⤼띳^=on뺲l䆼bzrﳨ[&j狸䠠=ᜑꦦ\u2061յnj=牲攑)M\\龏": false, + "뎕y絬᫡⥮Ϙᯑ㌔/NF*˓.,QEzvK!Iwz?|쥾\"ꩻL꼗Bꔧ賴緜s뉣隤茛>ロ?(?^`>冺飒=噸泥⺭Ᲊ婓鎔븜z^坷裮êⓅ໗jM7ﶕ找\\O": 1.376745434746303E-19 + }, + "䐛r滖w㏤,|Nዜ": false + } + ]], + "@꿙?薕尬 gd晆(띄5躕ﻫS蔺4)떒錸瓍?~": 1665108992286702624, + "w믍nᏠ=`঺ᅥC>'從됐槷䤝眷螄㎻揰扰XᅧC贽uჍ낟jKD03T!lDV쀉Ӊy뢖,袛!终캨G?鉮Q)⑗1쾅庅O4ꁉH7?d\u0010蠈줘월ސ粯Q!낇껉6텝|{": null, + "~˷jg쿤촖쉯y": -5.5527605669177098E18, + "펅Wᶺzꐆと푭e?4j仪열[D<鈑皶婆䵽ehS?袪;HꍨM뗎ば[(嗏M3q퍟g4y╸鰧茀[Bi盤~﫝唎鋆彺⦊q?B4쉓癚O洙킋툈䶯_?ퟲ": null + } + ] + ]] + ]], + "꟱Ԕ㍤7曁聯ಃ錐V䷰?v㪃૦~K\"$%请|ꇹn\"k䫛㏨鲨\u2023䄢\u0004[︊VJ?䶟ាꮈ䗱=깘U빩": -4863152493797013264 + } + ]}]} + ] + }}} + ], + "쏷쐲۹퉃~aE唙a챑,9㮹gLHd'䔏|킗㍞䎥&KZYT맵7䥺Nⱳ同莞鿧w\\༌疣n/+ꎥU\"封랾○ퟙAJᭌ?9䛝$?驔9讐짘魡T֯c藳`虉C읇쐦T" + } + ], + "谶개gTR￐>ၵ͚dt晑䉇陏滺}9㉸P漄": -3350307268584339381 + }] + ] + ] + ]] + ] + ], + "0y꟭馋X뱔瑇:䌚￐廿jg-懲鸭䷭垤㒬茭u賚찶ಽ+\\mT땱\u20821殑㐄J쩩䭛ꬿNS潔*d\\X,壠뒦e殟%LxG9:摸": 3737064585881894882, + "풵O^-⧧ⅶvѪ8廸鉵㈉ר↝Q㿴뺟EႳvNM:磇>w/៻唎뷭୥!냹D䯙i뵱貁C#⼉NH6`柴ʗ#\\!2䂗Ⱨf?諳.P덈-返I꘶6?8ꐘ": -8934657287877777844, + "溎-蘍寃i诖ര\"汵\"\ftl,?d⼡쾪⺋h匱[,෩I8MҧF{k瓿PA'橸ꩯ綷퉲翓": null + } + ] + ], + "ោ係؁<元": 1.7926963090826924E-18 + }}] + } + ] + ]]}] + }] + ] + ] + ] + ], + "ጩV<\"ڸsOᤘ": 2.0527167903723048E-19 + }] + ]} + ] + ]], + "∳㙰3젴p᧗䱙?`yZA8Ez0,^ᙛ4_0븢\u001ft:~䎼s.bb룦明yNP8弆C偯;⪾짍'蕴뮛": -6976654157771105701, + "큵ꦀ\\㇑:nv+뒤燻䀪ﴣ﷍9ᚈ኷K㚊誦撪䚛,ꮪxሲ쳊\u0005HSf?asg昱dqꬌVꙇ㼺'k*'㈈": -5.937042203633044E-20 + } + ] + }], + "?}\u20e0],s嶳菋@#2u쒴sQS䩗=ꥮ;烌,|ꘔ䘆": "ᅩ영N璠kZ먕眻?2ቲ芋眑D륟渂⸑ﴃIRE]啗`K'" + }}, + "쨀jmV賂ﰊ姐䂦玞㬙ᏪM᪟Վ씜~`uOn*ॠ8\u000ef6??\\@/?9見d筜ﳋB|S䝬葫㽁o": true + }, + "즛ꄤ酳艚␂㺘봿㎨iG৕ࡿ?1\"䘓您\u001fSኝ⺿溏zៀ뻤B\u0019?윐a䳵᭱䉺膷d:<\/": 3935553551038864272 + } + ] + ]} + ]] + ]] + ]} + } + ] + } + ]]}}, + "᥺3h↛!ꋰy\"攜(ெl䪕oUkc1A㘞ᡲ촾ᣫ<\/䒌E㛝潨i{v?W౾H\\RჅpz蝬R脾;v:碽✘↯삞鷱o㸧瑠jcmK7㶧뾥찲n": true, + "ⶸ?x䊺⬝-䰅≁!e쩆2ꎿ准G踌XXᩯ1߁}0?.헀Z馟;稄\baDꟹ{-寪⚈ꉷ鮸_L7ƽᾚ<\u001bጨA䧆송뇵⨔\\礍뗔d设룱㶉cq{HyぱR㥽吢ſtp": -7985372423148569301, + "緫#콮IB6<\/=5Eh礹\t8럭@饹韠r㰛斣$甝LV췐a갵'请o0g:^": "䔨(.", + "띳℡圤pン௄ĝ倧訜B쁟G䙔\"Sb⓮;$$▏S1J뢙SF|赡g*\"Vu䲌y": "䪈&틐),\\kT鬜1풥;뷴'Zေ䩹@J鞽NぼM?坥eWb6榀ƩZڮ淽⺞삳煳xჿ絯8eⶍ羷V}ჿ쎱䄫R뱃9Z>'\u20f1ⓕ䏜齮" + } + ] + ]]] + }} + } + ] + ]}, + "펮b.h粔폯2npX詫g錰鷇㇒<쐙S値bBi@?镬矉`剔}c2壧ଭfhY깨R()痩⺃a\\⍔?M&ﯟ<劜꺄멊ᄟA\"_=": null + }, + "~潹Rqn榢㆓aR鬨侅?䜑亡V_翅㭔(䓷w劸ၳDp䀅<\/ﰎ鶊m䵱팱긽ꆘ긓准D3掱;o:_ќ)껚콥8곤d矦8nP倥ꃸI": null, + "뾎/Q㣩㫸벯➡㠦◕挮a鶧⋓偼\u00001뱓fm覞n?㛅\"": 2.8515592202045408E17 + }], + ",": -5426918750465854828, + "2櫫@0柡g䢻/gꆑ6演&D稒肩Y?艘/놘p{f투`飷ᒉ챻돎<늛䘍ﴡ줰쫄": false, + "8(鸑嵀⵹ퟡ<9㣎Tߗ┘d슒ل蘯&㠦뮮eࠍk砝g 엻": false, + "d-\u208b?0ﳮ嵙'(J`蔿d^踅⤔榥\\J⵲v7": 6.8002426206715341E17, + "ཎ耰큓ꐕ㱷\u0013y=詽I\"盈xm{0쾽倻䉚ષso#鰑/8㸴짯%ꀄ떸b츟*\\鲷礬ZQ兩?np㋄椂榨kc᡹醅3": false, + "싊j20": false + }]] + ]], + "俛\u0017n緽Tu뫉蜍鼟烬.ꭠIⰓ\"Ἀ᜾uC쎆J@古%ꛍm뻨ᾀ画蛐휃T:錖㑸ዚ9죡$": true + } + ] + ], + "㍵⇘ꦖ辈s}㱮慀밒s`\"㞟j:`i픻Z섫^諎0Ok{켿歁෣胰a2﨤[탳뚬쎼嫭뉮m": 409440660915023105, + "w墄#*ᢄ峠밮jLa`ㆪ꺊漓Lで끎!Agk'ꁛ뢃㯐岬D#㒦": false, + "ଦPGI䕺L몥罭ꃑ궩﮶#⮈ᢓӢ䚬p7웼臧%~S菠␌힀6&t䳙y㪘냏\\*;鉏ᅧ鿵'嗕pa\"oL쇿꬈Cg": "㶽1灸D⟸䴅ᆤ뉎﷛渤csx 䝔цꬃ锚捬?ຽ+x~꘩uI࡞\u0007栲5呚ẓem?袝\")=㥴䨃pac!/揎Y", + "ᷱo\\||뎂몷r篙|#X䦜I#딌媸픕叞RD斳X4t⯩夬=[뭲r=绥jh뷱츝⪘%]⚋܈㖴スH텹m(WO曝劉0~K3c柢Ր㏉着逳~": false, + "煽_qb[첑\\륌wE❽ZtCNﭝ+餌ᕜOꛭ": "{ﳾ쉌&s惧ᭁⵆ3䢫;䨞팑꒪흘褀࢖Q䠿V5뭀䎂澻%받u5텸oA⮥U㎦;B䳌wz䕙$ឿ\\௅婺돵⪾퐆\\`Kyौꋟ._\u0006L챯l뇠Hi䧈偒5", + "艊佁ࣃ롇䱠爬!*;⨣捎慓q靓|儑ᨋL+迥=6㒺딉6弄3辅J-㕎뛄듘SG㆛(\noAzQꝱ䰩X*ぢO퀌%펠낌mo틮a^<\/F&_눊ᾉ㨦ы4\"8H": 2974648459619059400, + "鬙@뎣䫳ၮ끡?){y?5K;TA*k溱䫜J汃ꂯ싔썍\u001dA}룖(<\/^,": false, + "몏@QꋦFꊩᒐ뎶lXl垨4^郣|ꮇ;䝴ᝓ}쵲z珖": null + } + ]]]], + ":_=닧弗D䙋暨鏛. 㱻붘䂍J儒&ZK/녩䪜r囁⽯D喠죥7⹌䪥c\u001a\u2076￞妈朹oLk菮F౟覛쐧㮏7T;}蛙2{9\"崓bB<\/⡷룀;즮鿹)丒툃୤뷠5W⊢嶜(fb뭳갣": "E{响1WM" + }}, + "䘨tjJ驳豨?y輊M*᳑梵瞻઻ofQG瑮e": 2.222802939724948E-19, + "䮴=❑➶T෋w䞜\"垦ꃼUt\u001dx;B$뵣䙶E↌艣ᡥ!᧟;䱀[䔯k쬃`੍8饙른熏'2_'袻tGf蒭J땟as꯳╖&啒zWࡇᒫYSᏬ\u0014ℑ첥鈤|cG~Pᓮ\">\"": "ႆl\f7V儊㦬nHꄬꨧC{쐢~C⮃⛓嶦vꄎ1w鰠嘩뿠魄&\"_qMⵖ釔녮ꝇ 㝚{糍J哋 cv?-jkﻯྌ鹑L舟r", + "龧葆yB✱H盋夔ﶉ?n*0(": "ꧣኆ㢓氥qZZ酒ຜ)鮢樛)X䣆gTSґG텞k.J圬疝롫쯭z L:\\ྤ@w炋塜쿖ᾳy뢀䶃뱝N䥨㚔勇겁#p", + "도畎Q娡\"@S/뼋:䵏!P衅촚fVHQs✜ᐫi㻑殡B䜇%믚k*U#濨낄~": "ꍟዕ쳸ꍈ敋&l妏\u0005憡멗瘌uPgᅪm<\/To쯬锩h뒓k" + } + ] + }], + "墥홞r绚<\/⸹ⰃB}<躅\\Y;๑@䔸>韫䜲뱀X뗩鿥쩗SI%ﴞ㳕䛇?<\/\u00018x\\&侂9鋙a[LR㋭W胕)⡿8㞙0JF,}?허d1cDMᐃ␛鄝ⱕ%X)!XQ": "ⳍꗳ=橇a;3t⦾꼑仈ူaᚯ⯋ꕃAs鴷N⍕_䎃ꙎAz\u0016䯷\\<࿫>8q{}キ?ᣰ}'0ᴕ펓B┦lF#趤厃T?㕊#撹圂䆲" + }, + "܋닐龫論c웑": false, + "ㇿ/q\"6-co髨휝C큦#\u001b4~?3䐹E삇<<": 7.600917488140322E-20, + "䁝E6?㣖ꃁ间t祗*鑠{ḣV(浾h逇큞=W?ૉ?nꇽ8ꅉຉj으쮺@Ꚅ㰤u]Oyr": "v≁᫸_*όAඤԆl)ۓᦇQ}폠z༏q滚", + "ソ᥊/넺I": true + }]] + ] + ] + ] + ]] + }, + "䭑Ik攑\u0002QV烄:芩.麑㟴㘨≕": true, + "坄꿕C쇻풉~崍%碼\\8\"䬦꣙": null, + "欌L圬䅘Y8c(♺2?ON}o椳s宥2䉀eJ%闹r冁O^K諭%凞⺉⡻,掜?$ꥉ?略焕찳㯊艼誜4?\"﯎<゛XፈINT:詓 +": -1.0750456770694562E-19, + "獒àc뜭싼ﺳ뎤K`]p隨LtE": null, + "甙8䵊神EIꩤ鐯ᢀ,ﵮU䝑u疒ử驺䚿≚ഋ梶秓F`覤譐#짾蔀묊4<媍쬦靪_Yzgcࡶ4k紥`kc[Lﮗ簐*I瀑[⾰L殽鑥_mGȠ<\/|囹灠g桰iri": true, + "챓ꖙꟻ좝菇ou,嗠0\\jK핻뜠qwQ?ഩ㼕3Y彦b\u009bJ榶N棨f?됦鏖綃6鳵M[OE봨u햏.Ꮁ癜蟳뽲ꩌ뻾rM豈R嗀羫 uDꎚ%": null + }, + "V傜2<": 7175127699521359521 + }], + "铫aG切<\/\"ী⊆e<^g࢛)D顝nאַ饼\u008c猪繩嵿ﱚCꡬ㻊g엺A엦\u000f暿_f꿤볝㦕桦`蒦䎔j甬%岝rj 糏": "䚢偎눴Au<4箞7礦Iﱔ坠eȧ䪸u䵁p|逹$嗫쨘ꖾ﷐!胠z寓팢^㨔|u8Nሇe텔ꅦ抷]،鹎㳁#༔繁 ", + "낂乕ꃻ볨ϱ-ꇋ㖍fs⿫)zꜦ/K?솞♞ꑌ宭hJ᤭瑥Fu": false, + "쟰ぜ魛G\u0003u?`㾕ℾ㣭5螠烶這趩ꖢ:@咕ꐶx뒘느m䰨b痃렐0鳊喵熬딃$摉_~7*ⱦ녯1錾GKhJ惎秴6'H妈Tᧅ窹㺒疄矤铟wላ": null, + "쯆q4!3錕㲏ⵆ㇛꘷Z瑩뭆\\◪NH\u001d\\㽰U~㯶<\"쑣낞3ᵤ'峉eꢬ;鬹o꣒木X*長PXᘱu\"䠹n惞": null, + "ᅸ祊\"&ꥴCjࢼ﴿?䡉`U效5殼㮞V昽ꏪ#ﺸ\\&t6x꠹盥꣰a[\u001aꪍSpe鎿蠹": -1.1564713893659811E-19 + } + ]] + ] + ] + ], + "羵䥳H,6ⱎ겾|@t\"#햊1|稃 섭)띜=뻔ꡜ???櫎~*ῡ꫌/繣ﻠq": null + } + ]} + ]}, + "츤": false + }}, + "s": 3.7339341963399598E18 + } + ], + "N,I?1+㢓|ࣱ嶃쩥V2\u0012(4EE虪朶$|w颇v步": "~읢~_,Mzr㐫YB溓E淚\"ⅹ䈔ᏺ抙 b,nt5V㐒J檶ꏨ⻔?", + "Q껑ꡡ}$넎qH煔惍/ez^!ẳF댙䝌馻剁8": "梲;yt钰$i冄}AL%a j뜐奷걳뚾d꿽*ሬuDY3?뮟鼯뮟w㍪틱V", + "o{Q/K O胟㍏zUdꀐm&⨺J舕⾏魸訟㌥[T籨櫉唐킝 aṭ뱫촙莛>碶覆⧬짙쭰ׯdAiH໥벤퐥_恸[ 0e:죃TC弼荎뵁DA:w唵ꣁ": null, + "὏樎䵮軧|?౗aWH쩃1 ꅭsu": null + } + ] + }, + "勂\\&m鰈J釮=Ⲽ鳋+䂡郑": null, + "殣b綊倶5㥗惢⳷萢ᑀ䬄镧M^ﱴ3⣢翣n櫻1㨵}ኯ뗙顖Z.Q➷ꮨ뗇\u0004": "ꔙ䁼>n^[GीA䨟AM琢ᒊS쨲w?d㶣젊嘶纝麓+愣a%気ྞSc됓ᔘ:8bM7Xd8㶑臌]Ꙥ0ꐭ쒙䫣挵C薽Dfⵃ떼᷸", + "?紡.셪_෨j\u0013Ox┠$Xᶨ-ᅇo薹-}軫;y毝㪜K㣁?.EV쮱4둽⛻䤜'2盡\u001f60(|e쐰㼎ᦀ㒧-$l@ﻑ坳\u0003䭱响巗WFo5c㧆T턁Y맸♤(": -2.50917882560589088E17 + }} + ], + "侸\\릩.᳠뎠狣살cs项䭩畳H1s瀉븇19?.w骴崖㤊h痠볭㞳㞳䁮Ql怠㦵": "@䟴-=7f", + "鹟1x௢+d ;vi䭴FSDS\u0004hꎹ㚍?⒍⦏ў6u,扩@됷Su)Pag휛TᒗV痩!瞏釀ꖞ蘥&ೞ蘐ꭰꞇᝎ": "ah懱Ժ&\u20f7䵅♎඀䞧鿪굛ౕ湚粎蚵ᯋ幌YOE)५襦㊝Y*^\"R+ඈ咷蝶9ꥂ榨艦멎헦閝돶v좛咊E)K㓷ྭr", + "搆q쮦4綱켙셁.f4<\/g<籽늷?#蚴픘:fF\u00051㹉뀭.ᰖ풎f֦Hv蔎㧤.!䭽=鞽]음H:?\"-4": 8.740133984938656E-20 + }]} + } + ], + "tVKn딩꘥⊾蹓᤹{\u0003lR꼽ᄲQFᅏ傅ﱋ猢⤊ᔁ,E㓒秤nTතv`♛I\u0000]꫔ṞD\"麵c踝杰X&濿또꣹깳౥葂鿎\\aꡨ?": 3900062609292104525 + } + ], + "ਉ샒⊩Lu@S䧰^g": -1.1487677090371648E18, + "⎢k⑊꬗yᏫ7^err糎Dt\u000bJ礯확ㆍ沑サꋽe赔㝢^J\u0004笲㿋idra剰-᪉C錇/Ĝ䂾ညS지?~콮gR敉⬹'䧭": 1901472137232418266, + "灗k䶥:?촽贍쓉꓈㒸g獘[뵎\\胕?\u0014_榙p.j稶,$`糉妋0>Fᡰly㘽$?": "]ꙛO赎&#㠃돱剳\"<◆>0誉齐_|z|裵씪>ᐌ㼍\"Z[琕}O?G뚇諦cs⠜撺5cu痑U圲\u001c?鴴計l춥/╓哼䄗茏ꮅ뫈댽A돌롖뤫V窗讬sHd&\nOi;_u" + } + ], + "Uﺗ\\Y\\梷䄬~\u0002": null, + "k\"Y磓ᗔ휎@U冈<\/w컑)[": false, + "曏J蝷⌻덦\u001f㙳s꥓⍟邫P늮쥄c∬ྡྷ舆렮칤Z趣5콡넛A쳨\\뀙骫(棻.*&輛LiIfi{@EA婳KᬰTXT": -4.3088230431977587E17 + }]} + ] + ], + "곃㲧<\/dఓꂟs其ࡧ&N葶=?c㠤Ჴ'횠숄臼#\u001a~": false + } + ] + ]}] + }] + }} + ], + "2f`⽰E쵟>J笂裭!〛觬囀ۺ쟰#桊l鹛ⲋ|RA_Vx፭gE됓h﵀mfỐ|?juTU档[d⢼⺻p濚7E峿": 5613688852456817133 + }, + "濘끶g忮7㏵殬W팕Q曁 뫰)惃廊5%-蹚zYZ樭ﴷQ锘쯤崫gg": true, + "絥ᇑ⦏쒓븣爚H.㗊߄o蘵貆ꂚ(쎔O᥉ﮓ]姨Wꁓ!RMA|o퉢THx轮7M껁U즨'i뾘舯o": "跥f꜃?" + }} + ], + "鷰鹮K-9k;ﰰ?_ݦѷ-ꅣ䩨Zꥱ\"mꠟ屎/콑Y╘2&鸞脇㏢ꀇ࠺ⰼ拾喭틮L꽩bt俸墶 [l/웄\"꾦\u20d3iও-&+\u000fQ+໱뵞": -1.296494662286671E-19 + }, + "HX੹/⨇୕붷Uﮘ旧\\쾜͔3l鄈磣糂̖䟎Eᐳw橖b῀_딕hu葰窳闹вU颵|染H죶.fP䗮:j䫢\\b뎖i燕ꜚG⮠W-≚뉗l趕": "ଊ칭Oa᡺$IV㷧L\u0019脴셀붿餲햪$迳向쐯켂PqfT\" ?I屉鴼쿕@硙z^鏕㊵M}㚛T젣쓌-W⩐-g%⺵<뮱~빅╴瑿浂脬\u0005왦燲4Ⴭb|D堧 <\/oEQh", + "䘶#㥘੐캔f巋ἡAJ䢚쭈ࣨ뫒*mᇊK,ࣺAꑱ\u000bR<\/A\"1a6鵌㯀bh곿w(\"$ꘁ*rಐ趣.d࿩k/抶면䒎9W⊃9": "漩b挋Sw藎\u0000", + "畀e㨼mK꙼HglKb,\"'䤜": null + }]}] + ] + ] + }] + ]} + ] + ]} + ], + "歙>駿ꣂ숰Q`J΋方樛(d鱾뼣(뫖턭\u20f9lচ9歌8o]8윶l얶?镖G摄탗6폋폵+g:䱫홊<멀뀿/س|ꭺs걐跶稚W々c㫣⎖": "㣮蔊깚Cꓔ舊|XRf遻㆚︆'쾉췝\\&言", + "殭\"cށɨꝙ䞘:嬮e潽Y펪㳅/\"O@ࠗ겴]췖YǞ(t>R\"N?梳LD恭=n氯T豰2R諸#N}*灧4}㶊G䍣b얚": null, + "襞<\/啧 B|싞W瓇)6簭鼡艆lN쩝`|펭佡\\間邝[z릶&쭟愱ꅅ\\T᰽1鯯偐栈4̸s윜R7⒝/똽?치X": "⏊躖Cﱰ2Qẫ脐&இ?%냝悊", + ",鰧偵셣싹xᎹ힨᯳EṬH㹖9": -4604276727380542356 + } + } + ]]]], + "웺㚑xs}q䭵䪠馯8?LB犯zK'os䚛HZ\"L?셎s^㿧㴘Cv2": null + }] + ] + ] + ], + "Kd2Kv+|z": 7367845130646124107, + "ᦂⶨ?ᝢ 祂些ഷ牢㋇操\"腭䙾㖪\\(y4cE뽺ㆷ쫺ᔖ%zfۻ$ў1柦,㶢9r漢": -3.133230960444846E-20, + "琘M焀q%㢟f鸯O⣏蓑맕鯊$O噷|)z褫^㢦⠮ꚯ꫞`毕1qꢚ{ĭ䎀বώT\"뱘3G൴?^^of": null + } + ], + "a8V᯺?:ﺃ/8ꉿBq|9啓댚;*i2": null, + "cpT瀇H珰Ừpೃi鎪Rr␣숬-鹸ҩ䠚z脚цGoN8入y%趌I┽2ឪЀiJNcN)槣/▟6S숆牟\"箑X僛G殱娇葱T%杻:J諹昰qV쨰": 8331037591040855245 + }], + "G5ᩜ䄗巢껳": true + } + }, + "Ồ巢ゕ@_譙A`碫鄐㡥砄㠓(^K": "?܃B혢▦@犑ὺD~T⧁|醁;o=J牌9냚⢽㨘{4觍蚔9#$∺\u0016p囅\\3Xk阖⪚\"UzA穕롬✎➁㭒춺C㣌ဉ\"2瓑员ᅽꝶ뫍}꽚ꞇ鶂舟彺]ꍽJC蝧銉", + "␆Ě膝\"b-퉐ACR言J謈53~V튥x䜢?ꃽɄY뮩ꚜ": "K/↾e萃}]Bs⾿q룅鷦-膋?m+死^魊镲6", + "粡霦c枋AHퟁo礼Ke?qWcA趸㡔ꂏ?\u000e춂8iতᦜ婪\u0015㢼nﵿꍻ!ᐴ関\u001d5j㨻gfῩUK5Ju丝tかTI'?㓏t>⼟o a>i}ᰗ;뤕ܝ": false, + "ꄮ匴껢ꂰ涽+䜨B蛹H䛓-k蕞fu7kL谖,'涃V~챳逋穞cT\"vQ쓕ObaCRQ㓡Ⲯ?轭⫦輢墳?vA餽=h䮇킵n폲퉅喙?\"'1疬V嬗Qd灗'Lự": "6v!s믁㭟㣯獃!磸餠ቂh0C뿯봗F鷭gꖶ~コkK<ᦈTt\\跓w㭣횋钘ᆹ듡䑚W䟾X'ꅔ4FL勉Vܴ邨y)2'〚쭉⽵-鞣E,Q.?块", + "?(˧쩯@崟吋歄K": null + }, + "Gc럃녧>?2DYI鴿\\륨)澔0ᔬlx'觔7젘⤡縷螩%Sv׫묈/]↱&S h\u0006歋ᑛxi̘}ひY蔯_醨鯘煑橾8?䵎쨋z儬ꁏ*@츾:": null + } + } + } + ] + ] + ]} + }, + "HO츧G": 3.694949578823609E17, + "QC\u0012(翻曇Tf㷟bGBJ옉53\\嚇ᛎD/\u001b夾၉4\"핀@祎)쫆yD\"i먎Vn㿿V1W᨝䶀": -6150931500380982286, + "Z㓮P翸鍱鉼K䋞꘺튿⭁Y": -7704503411315138850, + "]모开ꬖP븣c霤<[3aΠ\"黁䖖䰑뮋ꤦ秽∼㑷冹T+YUt\"싳F↭䖏&鋌": -2.7231911483181824E18, + "tꎖ": -4.9517948741799555E-19, + "䋘즊.⬅IꬃۣQ챢ꄑ黐|f?C⾺|兕읯sC鬸섾整腨솷V": "旆柩l쪦sᖸMy㦅울썉瘗㎜檵9ꍂ駓ૉᚿ/u3씅徐拉[Z䞸ࡗ1ꆱ&Q풘?ǂ8\u0011BCDY2볨;鸏": null, + "幫 n煥s쁇펇 왊-$C\"衝:\u0014㣯舼.3뙗Yl⋇\"K迎멎[꽵s}9鉳UK8쐥\"掄㹖h㙈!얄સ?Ꜳ봺R伕UTD媚I䜘W鏨蔮": -4.150842714188901E-17, + "ﺯ^㄄\b죵@fྉkf颡팋Ꞧ{/Pm0V둳⻿/落韒ꊔᚬ@5螺G\\咸a谆⊪ቧ慷绖?财(鷇u錝F=r၍橢ឳn:^iᴵtD볠覅N赴": null + }] + }] + } + ] + ]} + ]}, + "謯?w厓奰T李헗聝ឍ貖o⪇弒L!캶$ᆅ": -4299324168507841322, + "뺊奉_垐浸延몏孄Z舰2i$q붿좾껇d▵餏\"v暜Ҭ섁m￴g>": -1.60911932510533427E18 + } + ] + } + ] + ]], + "퉝꺔㠦楶Pꅱ": 7517896876489142899, + "": false + } + ]}, + "是u&I狻餼|谖j\"7c됮sסּ-踳鉷`䣷쉄_A艣鳞凃*m⯾☦椿q㎭N溔铉tlㆈ^": 1.93547720203604352E18, + "kⲨ\\%vr#\u000bⒺY\\t<\/3﬌R訤='﹠8蝤Ꞵ렴曔r": false + } + ]}, + "阨{c?C\u001d~K?鎌Ԭ8烫#뙣P초遗t㭱E­돒䆺}甗[R*1!\\~h㕅᰺@<9JꏏષI䳖栭6綘걹ᅩM\"▯是∔v鬽顭⋊譬": "운ﶁK敂(欖C취پ℄爦賾" + } + }} + }], + "鷨赼鸙+\\䭣t圙ڹx᜾ČN<\/踘\"S_맶a鷺漇T彚⎲i㈥LT-xA캔$\u001cUH=a0츺l릦": "溣㣂0濕=鉵氬駘>Pꌢpb솇쬤h힊줎獪㪬CrQ矠a&脍꼬爼M茴/΅\u0017弝轼y#Ꞡc6둴=?R崏뷠麖w?" + }, + "閕ᘜ]CT)䵞l9z'xZF{:ؐI/躅匽졁:䟇AGF૸\u001cퟗ9)駬慟ꡒꆒRS״툋A<>\u0010\"ꂔ炃7g덚E৏bꅰ輤]o㱏_뷕ܘ暂\"u": "芢+U^+㢩^鱆8*1鈶鮀\u0002뺰9⬳ꪮlL䃣괟,G8\u20a8DF㉪錖0ㄤ瓶8Nଷd?眡GLc陓\\_죌V쁰ल二?c띦捱 \u0019JC\u0011b⤉zẒT볕\"绣蘨뚋cꡉkI\u001e鳴", + "ꃣI'{6u^㡃#཰Kq4逹y൒䧠䵮!㱙/n??{L풓ZET㙠퍿X2᩟綳跠葿㚙w཮x캽扳B唕S|尾}촕%N?o䪨": null, + "ⰴFjෟ셈[\u0018辷px?椯\\1<ﲻ栘ᣁ봢憠뉴p": -5263694954586507640 + } + ] + ]] + ]} + ]}] + ] + ], + "?#癘82禩鋆ꊝty?&": -1.9419029518535086E-19 + } + ] + ] + ]} + ] + ] + ], + "훊榲.|῕戄&.㚏Zꛦ2\"䢥ሆ⤢fV_摕婔?≍Fji冀탆꜕i㏬_ẑKᅢ꫄蔻XWc|饡Siẘ^㲦?羡2ぴ1縁ᙅ?쐉Ou": false + }]] + ]}}}, + "慂뗄卓蓔ᐓ匐嚖/颹蘯/翻ㆼL?뇊,텵<\\獷ごCボ": null + }, + "p溉ᑟi짣z:䒤棇r^٫%G9缑r砌롧.물农g?0׼ሩ4ƸO㣥㯄쩞ጩ": null, + "껎繥YxK\"F젷쨹뤤1wq轫o?鱑뜀瘊?뎃h灑\\ꛣ}K峐^ኖ⤐林ꉓhy": null + } + ], + "᱀n肓ㄛ\"堻2>m殮'1橌%Ꞵ군=Ӳ鯨9耛<\/n據0u彘8㬇៩f᏿诙]嚊": "䋯쪦S럶匏ㅛ#)O`ሀX_鐪渲⛀㨻宅闩➈ꢙஶDR⪍" + }, + "tA썓龇 ⋥bj왎录r땽✒롰;羋^\\?툳*┎?썀ma䵳넅U䳆૘〹䆀LQ0\b疀U~u$M}(鵸g⳾i抦뛹?䤈땚검.鹆?ꩡtⶥGĒ;!ቹHS峻B츪켏f5≺": 2366175040075384032, + "전pJjleb]ួ": -7.5418493141528422E18, + "n.鎖ጲ\n?,$䪘": true + }, + "欈Ar㉣螵᪚茩?O)": null + }, + "쫸M#x}D秱欐K=侫们丐.KꕾxẠ\u001e㿯䣛F܍캗qq8꟞ṢFD훎⵳簕꭛^鳜\u205c٫~⑟~冫ऊ2쫰<\/戲윱o<\"": true + }, + "㷝聥/T뱂\u0010锕|内䞇x侁≦㭖:M?iM᣿IJe煜dG࣯尃⚩gPt*辂.{磼럾䝪@a\\袛?}ᓺB珼": true + } + } + ]]}]}}, + "tn\"6ꫤ샾䄄;銞^%VBPwu묪`Y僑N.↺Ws?3C⤻9唩S䠮ᐴm;sᇷ냞඘B/;툥B?lB∤)G+O9m裢0kC햪䪤": -4.5941249382502277E18, + "ᚔt'\\愫?鵀@\\びꂕP큠<<]煹G-b!S?\nꖽ鼫,ݛ&頺y踦?E揆릱H}햧캡b@手.p탻>췽㣬ꒅ`qe佭P>ᓂ&?u}毚ᜉ蟶頳졪ᎏzl2wO": -2.53561440423275936E17 + }]} + } + ] + ]], + "潈촒⿂叡": 5495738871964062986 + } + ]] + } + ] + ]} + ]] + ]] + ]} + ] + ]}, + "ႁq킍蓅R`謈蟐ᦏ儂槐僻ﹶ9婌櫞釈~\"%匹躾ɢ뤥>࢟瀴愅?殕节/냔O✬H鲽엢?ᮈੁ⋧d␽㫐zCe*": 2.15062231586689536E17, + "㶵Ui曚珰鋪ᾼ臧P{䍏䷪쨑̟A뼿T渠誈䏚D1!잶<\/㡍7?)2l≣穷᛾稝{:;㡹nemיּ訊`G": null, + "䀕\"飕辭p圁f#뫆䶷뛮;⛴ᩍ3灚덏ᰝ쎓⦷詵%᜖Մfs⇫(\u001e~P|ﭗCⲾផv湟W첋(텪બT<บSꏉ੗⋲X婵i ӵ⇮?L䬇|ꈏ?졸": 1.548341247351782E-19 + } + ] + }, + "t;:N\u0015q鐦Rt缆{ꮐC?஛㷱敪\\+鲊㉫㓪몗릙竏(氵kYS": "XᰂT?൮ô", + "碕飦幑|+ 㚦鏶`镥ꁩ B<\/加륙": -4314053432419755959, + "秌孳(p!G?V傫%8ሽ8w;5鲗㦙LI檸\u2098": "zG N볞䆭鎍흘\\ONK3횙<\/樚立圌Q튅k쩎Ff쁋aׂJK銆ઘ즐狩6༥✙䩜篥CzP(聻駇HHퟲ讃%,ά{렍p而刲vy䦅ክ^톺M楒鍢㹳]Mdg2>䤉洞", + "踛M젧>忔芿㌜Zk": 2215369545966507819, + "씐A`$槭頰퍻^U覒\bG毲aᣴU;8!팲f꜇E⸃_卵{嫏羃X쀳C7뗮m(嚼u N܁谟D劯9]#": true, + "ﻩ!뵸-筚P᭛}ἰ履lPh?౮ⶹꆛ穉뎃g萑㑓溢CX뾇G㖬A錟]RKaꄘ]Yo+@䘁's섎襠$^홰}F": null + }, + "粘ꪒ4HXᕘ蹵.$區\r\u001d묁77pPc^y笲Q<\/ꖶ 訍䃍ᨕG?*": 1.73773035935040224E17 + }, + "婅拳?bkU;#D矠❴vVN쩆t㜷A풃갮娪a%鮏絪3dAv룒#tm쑬⌛qYwc4|L8KZ;xU⓭㳔밆拓EZ7襨eD|隰ऌ䧼u9Ԣ+]贴P荿": 2.9628516456987075E18 + }]}}] + ]} + }} + ]}] + ], + "|g翉F*湹̶\u0005⏐1脉̀eI쩓ᖂ㫱0碞l䴨ꑅ㵽7AtἈ턧yq䳥塑:z:遀ᄐX눔擉)`N3昛oQ셖y-ڨ⾶恢ꈵq^<\/": null, + "菹\\랓G^璬x৴뭸ゆUS겧﮷Bꮤ ┉銜᯻0%N7}~f洋坄Xꔼ<\/4妟Vꄟ9:౟곡t킅冩䧉笭裟炂4봋ⱳ叺怊t+怯涗\"0㖈Hq": false, + "졬믟'ﺇফ圪쓬멤m邸QLব䗁愍4jvs翙 ྍ꧀艳H-|": null, + "컮襱⣱뗠 R毪/鹙꾀%헳8&": -5770986448525107020 + } + ], + "B䔚bꐻ뙏姓展槰T-똌鷺tc灿᫽^㓟䏀o3o$꘭趙萬I顩)뇭Ἑ䓝\f@{ᣨ`x3蔛": null + } + ] + ] + }], + "⦖扚vWꃱ꥙㾠壢輓{-⎳鹷贏璿䜑bG倛⋐磎c皇皩7a~ﳫU╣Q࠭ꎉS摅姽OW.홌ೞ.": null, + "蚪eVlH献r}ᮏ믠ﰩꔄ@瑄ⲱ": null, + "퀭$JWoꩢg역쁍䖔㑺h&ୢtXX愰㱇?㾫I_6 OaB瑈q裿": null, + "꽦ﲼLyr纛Zdu珍B絟쬴糔?㕂짹䏵e": "ḱ\u2009cX9멀i䶛簆㳀k" + } + ]]]], + "(_ꏮg່澮?ᩑyM<艷\u001aꪽ\\庼뙭Z맷㰩Vm\\lY筺]3㋲2㌩㄀Eਟ䝵⨄쐨ᔟgङHn鐖⤇놋瓇Q탚單oY\"♆臾jHᶈ征ቄ??uㇰA?#1侓": null + }, + "觓^~ሢ&iI띆g륎ḱ캀.ᓡꀮ胙鈉": 1.0664523593012836E-19, + "y詭Gbᔶऽs댁U:杜⤎ϲ쁗⮼D醄诿q뙰I#즧v蔎xHᵿt᡽[**?崮耖p缫쿃L菝,봬ꤦC쯵#=X1瞻@OZc鱗CQTx": null + } + ] + }}], + "剘紁\u0004\\Xn⊠6,တױ;嵣崇}讃iႽ)d1\\䔓": null + }, + "脨z\"{X,1u찜<'k&@?1}Yn$\u0015Rd輲ーa쮂굄+B$l": true, + "諳>*쭮괐䵟Ґ+<箁}빀䅱⡔檏臒hIH脟ꩪC핝ଗP좕\"0i<\/C褻D۞恗+^5?'ꂱ䚫^7}㡠cq6\\쨪ꔞꥢ?纖䫀氮蒫侲빦敶q{A煲G": -6880961710038544266 + }}] + }, + "5s⨲JvಽῶꭂᄢI.a৊": null, + "?1q꽏쿻ꛋDR%U娝>DgN乭G": -1.2105047302732358E-19 + } + ] + ]}, + "qZz`撋뙹둣j碇쁏\\ꆥ\u0018@藴疰Wz)O{F䶛l᷂绘訥$]뮍夻䢋䩇萿獰樧猵⣭j萶q)$꬚⵷0馢W:Ⱍ!Qoe": -1666634370862219540, + "t": "=wp|~碎Q鬳Ӎ\\l-<\/^ﳊhn퐖}䍔t碵ḛ혷?靻䊗", + "邙쇡㯇%#=,E4勃驆V繚q[Y댻XV㡸[逹ᰏ葢B@u=JS5?bLRn얮㍉⏅ﰳ?a6[&큟!藈": 1.2722786745736667E-19 + }, + "X블땨4{ph鵋ꉯ웸 5p簂䦭s_E徔濧d稝~No穔噕뽲)뉈c5M윅>⚋[岦䲟懷恁?鎐꓆ฬ爋獠䜔s{\u001bm鐚儸煛%bﯿXT>ꗘ@8G": 1157841540507770724, + "媤娪Q杸\u0011SAyᡈ쿯": true, + "灚^ಸ%걁<\/蛯?\"祴坓\\\\'흍": -3.4614808555942579E18, + "釴U:O湛㴑䀣렑縓\ta)(j:숾却䗌gCiB뽬Oyuq輥厁/7)?今hY︺Q": null + } + ] + ]]]}] + ], + "I笔趠Ph!<ཛྷ㸞诘X$畉F\u0005笷菟.Esr릙!W☆䲖뗷莾뒭U\"䀸犜Uo3Gꯌx4r蔇᡹㧪쨢準<䂀%ࡡꟼ瑍8炝Xs0䀝销?fi쥱ꆝલBB": -8571484181158525797, + "L⦁o#J|\"⽩-㱢d㌛8d\\㶤傩儻E[Y熯)r噤὘勇 }": "e(濨쓌K䧚僒㘍蠤Vᛸ\"络QJL2,嬓왍伢㋒䴿考澰@(㏾`kX$끑эE斡,蜍&~y", + "vj.|统圪ᵮPL?2oŶ`밧\"勃+0ue%⿥绬췈체$6:qa렐Q;~晘3㙘鹑": true, + "ශؙ4獄⶿c︋i⚅:ん閝Ⳙ苆籦kw{䙞셕pC췃ꍬ␜꟯ꚓ酄b힝hwk꭭M鬋8B耳쑘WQ\\偙ac'唀x᪌\u2048*h짎#ፇ鮠뾏ឿ뀌": false, + "⎀jꄒ牺3Ⓝ컴~?親ꕽぼܓ喏瘘!@<튋㐌꿱⩦{a?Yv%⪧笯Uܱ栅E搚i뚬:ꄃx7䙳ꦋ&䓹vq☶I䁘ᾘ涜\\썉뺌Lr%Bc㍜3?ꝭ砿裞]": null, + "⭤뙓z(㡂%亳K䌽꫿AԾ岺㦦㼴輞낚Vꦴw냟鬓㹈뽈+o3譻K1잞": 2091209026076965894, + "ㇲ\t⋇轑ꠤ룫X긒\"zoY읇희wj梐쐑l侸`e%s": -9.9240075473576563E17, + "啸ꮑ㉰!ᚓ}銏": -4.0694813896301194E18, + ">]囋੽EK뇜>_ꀣ緳碖{쐐裔[<ನ\"䇅\"5L?#xTwv#罐\u0005래t应\\N?빗;": "v쮽瞭p뭃" + } + ]], + "斴槾?Z翁\"~慍弞ﻆ=꜡o5鐋dw\"?K蠡i샾ogDﲰ_C*⬟iㇷ4nય蟏[㟉U꽌娛苸 ঢ়操贻洞펻)쿗૊許X⨪VY츚Z䍾㶭~튃ᵦ<\/E臭tve猑x嚢": null, + "锡⛩<\/칥ꈙᬙ蝀&Ꚑ籬■865?_>L詏쿨䈌浿弥爫̫lj&zx<\/C쉾?覯n?": null, + "꾳鑤/꼩d=ᘈn挫ᑩ䰬ZC": "3錢爋6Ƹ䴗v⪿Wr益G韠[\u0010屗9쁡钁u?殢c䳀蓃樄욂NAq赟c튒瘁렶Aૡɚ捍" + } + ] + ] + ]} + ] + ] + }]]]}} + ]}], + "Ej䗳U<\/Q=灒샎䞦,堰頠@褙g_\u0003ꤾfⶽ?퇋!łB〙ד3CC䌴鈌U:뭔咎(Qો臃䡬荋BO7㢝䟸\"Yb": 2.36010731779814E-20, + "逸'0岔j\u000e눘먷翌C츊秦=ꭣ棭ှ;鳸=麱$XP⩉駚橄A\\좱⛌jqv䰞3Ь踌v㳆¹gT┌gvLB賖烡m?@E঳i": null + }, + "曺v찘ׁ?&绫O័": 9107241066550187880 + } + ] + ], + "(e屄\u0019昜훕琖b蓘ᬄ0/۲묇Z蘮ဏ⨏蛘胯뢃@㘉8ሪWᨮ⦬ᅳ䅴HI၇쨳z囕陻엣1赳o": true, + ",b刈Z,ၠ晐T솝ŕB⩆ou'퐼≃绗雗d譊": null, + "a唥KB\"ﳝ肕$u\n^⅄P䟼냉䞸⩪u윗瀱ꔨ#yşs꒬=1|ﲤ爢`t౐튼쳫_Az(Ṋ擬㦷좕耈6": 2099309172767331582, + "?㴸U<\/䢔ꯡ阽扆㐤q鐋?f㔫wM嬙-;UV죫嚔픞G&\"Cᗍ䪏풊Q": "VM7疹+陕枡툩窲}翡䖶8欞čsT뮐}璤:jﺋ鎴}HfA൝⧻Zd#Qu茅J髒皣Y-︴[?-~쉜v딏璮㹚䅊﩯<-#\u000e걀h\u0004u抱﵊㼃U<㱷⊱IC進" + }, + "숌dee節鏽邺p넱蹓+e罕U": true + } + ], + "b⧴룏??ᔠ3ぱ>%郿劃翐ꏬꠛW瞳᫏누躨狀ໄy੽\"ីuS=㨞馸k乆E": "トz݈^9R䬑<ﮛGRꨳ\u000fTT泠纷꽀MRᴱ纊:㠭볮?%N56%鈕1䗍䜁a䲗j陇=뿻偂衋࿘ᓸ?ᕵZ+<\/}H耢b䀁z^f$&㝒LkꢳI脚뙛u": 5.694374481577558E-20 + }] + } + ]], + "obj": {"key": "wrong value"}, + "퓲꽪m{㶩/뇿#⼢&᭙硞㪔E嚉c樱㬇1a綑᝖DḾ䝩": null + }, + "key": "6.908319653520691E8", + "z": { + "6U閆崬밺뀫颒myj츥휘:$薈mY햚#rz飏+玭V㭢뾿愴YꖚX亥ᮉ푊\u0006垡㐭룝\"厓ᔧḅ^Sqpv媫\"⤽걒\"˽Ἆ?ꇆ䬔未tv{DV鯀Tἆl凸g\\㈭ĭ즿UH㽤": null, + "b茤z\\.N": [[ + "ZL:ᅣዎ*Y|猫劁櫕荾Oj为1糕쪥泏S룂w࡛Ᏺ⸥蚙)", + { + "\"䬰ỐwD捾V`邀⠕VD㺝sH6[칑.:醥葹*뻵倻aD\"": true, + "e浱up蔽Cr෠JK軵xCʨ<뜡癙Y獩ケ齈X/螗唻?<蘡+뷄㩤쳖3偑犾&\\첊xz坍崦ݻ鍴\"嵥B3㰃詤豺嚼aqJ⑆∥韼@\u000b㢊\u0015L臯.샥": false, + "l?Ǩ喳e6㔡$M꼄I,(3᝝縢,䊀疅뉲B㴔傳䂴\u0088㮰钘ꜵ!ᅛ韽>": -5514085325291784739, + "o㮚?\"춛㵉<\/﬊ࠃ䃪䝣wp6ἀ䱄[s*S嬈貒pᛥ㰉'돀": [{ + "(QP윤懊FI<ꃣ『䕷[\"珒嶮?%Ḭ壍಻䇟0荤!藲끹bd浶tl\u2049#쯀@僞": {"i妾8홫": { + ",M맃䞛K5nAㆴVN㒊햬$n꩑&ꎝ椞阫?/ṏ세뉪1x쥼㻤㪙`\"$쟒薟B煌܀쨝ଢ଼2掳7㙟鴙X婢\u0002": "Vዉ菈᧷⦌kﮞఈnz*﷜FM\"荭7ꍀ-VR<\/';䁙E9$䩉\f @s?퍪o3^衴cඎ䧪aK鼟q䆨c{䳠5mᒲՙ蘹ᮩ": { + "F㲷JGo⯍P덵x뒳p䘧☔\"+ꨲ吿JfR㔹)4n紬G练Q፞!C|": true, + "p^㫮솎oc.೚A㤠??r\u000f)⾽⌲們M2.䴘䩳:⫭胃\\፾@Fᭌ\\K": false, + "蟌Tk愙潦伩": { + "a<\/@ᾛ慂侇瘎": -7271305752851720826, + "艓藬/>၄ṯ,XW~㲆w": {"E痧郶)㜓ha朗!N赻瞉駠uC\u20ad辠x퓮⣫P1ࠫLMMX'M刼唳됤": null, + "P쓫晥%k覛ዩIUᇸ滨:噐혲lMR5䋈V梗>%幽u頖\\)쟟": null, + "eg+昉~矠䧞难\b?gQ쭷筝\\eꮠNl{ಢ哭|]Mn銌╥zꖘzⱷ⭤ᮜ^": [ + -1.30142114406914976E17, + -1.7555215491128452E-19, + null, + "渾㨝ߏ牄귛r?돌?w[⚞ӻ~廩輫㼧/", + -4.5737191805302129E18, + null, + "xy࿑M[oc셒竓Ⓔx?뜓y䊦>-D켍(&&?XKkc꩖ﺸᏋ뵞K伕6ী)딀P朁yW揙?훻魢傎EG碸9類៌g踲C⟌aEX舲:z꒸许", + 3808159498143417627, + null, + {"m試\u20df1{G8&뚈h홯J<\/": { + "3ஸ厠zs#1K7:rᥞoꅔꯧ&띇鵼鞫6跜#赿5l'8{7㕳(b/j\"厢aq籀ꏚ\u0015厼稥": [ + -2226135764510113982, + true, + null, + { + "h%'맞S싅Hs&dl슾W0j鿏MםD놯L~S-㇡R쭬%": null, + "⟓咔謡칲\u0000孺ꛭx旑檉㶆?": null, + "恇I転;￸B2Y`z\\獓w,놏濐撐埵䂄)!䶢D=ഭ㴟jyY": { + "$ࡘt厛毣ൢI芁<겿骫⫦6tr惺a": [ + 6.385779736989334E-20, + false, + true, + true, + [ + -6.891946211462334E-19, + null, + { + "]-\\Ꟑ1/薓❧Ὂ\\l牑\u0007A郃)阜ᇒᓌ-塯`W峬G}SDb㬨Q臉⮻빌O鞟톴첂B㺱<ƈmu챑J㴹㷳픷Oㆩs": { + "\"◉B\"pᶉt骔J꩸ᄇᛐi╰栛K쉷㉯鐩!㈐n칍䟅難>盥y铿e୔蒏M貹ヅ8嘋퀯䉶ጥ㏢殊뻳\"絧╿ꉑ䠥?∃蓊{}㣣Gk긔H1哵峱": false, + "6.瀫cN䇮F㧺?\\椯=ڈT䘆4␘8qv": -3.5687501019676885E-19, + "Q?yऴr혴{஀䳘p惭f1ﹸ䅷䕋贲<ྃᄊ繲hq\\b|#QSTs1c-7(䵢\u2069匏絘ꯉ:l毴汞t戀oෟᵶ뮱፣-醇Jx䙬䐁햢0࣫ᡁgrㄛ": "\u0011_xM/蘇Chv;dhA5.嗀绱V爤ﰦi뵲M", + "⏑[\"ugoy^儣횎~U\\섯겜論l2jw஌yD腅̂\u0019": true, + "ⵯɇ䐲᫿࢚!㯢l샅笶戮1꣖0Xe": null, + "劅f넀識b宁焊E찓橵G!ʱ獓뭔雩괛": [{"p⹣켙[q>燣䍃㞽ᩲx:쓤삘7玑퇼0<\/q璂ᑁ[Z\\3䅵䧳\u0011㤧|妱緒C['췓Yꞟ3Z鳱雼P錻BU씧U`ᢶg蓱>.1ӧ譫'L_5V䏵Ц": [ + false, + false, + {"22䂍盥N霂얢躰e9⑩_뵜斌n@B}$괻Yᐱ@䧋V\"☒-諯cV돯ʠ": true, + "Ű螧ᔼ檍鍎땒딜qꄃH뜣<獧ूCY吓⸏>XQ㵡趌o끬k픀빯a(ܵ甏끆୯/6Nᪧ}搚ᆚ짌P牰泱鈷^d꣟#L삀\"㕹襻;k㸊\\f+": true, + "쎣\",|⫝̸阊x庿k잣v庅$鈏괎炔k쬪O_": [ + "잩AzZGz3v愠ꉈⵎ?㊱}S尳௏p\r2>췝IP䘈M)w|\u000eE", + -9222726055990423201, + null, + [ + false, + {"´킮'뮤쯽Wx讐V,6ᩪ1紲aႈ\u205czD": [ + -930994432421097536, + 3157232031581030121, + "l貚PY䃛5@䭄귻m㎮琸f": 1.0318894506812084E-19, + "࢜⩢Ш䧔1肽씮+༎ᣰ闺馺窃䕨8Mƶq腽xc(៯夐J5굄䕁Qj_훨/~価.䢵慯틠퇱豠㼇Qﵘ$DuSp(8Uญ<\/ಟ룴𥳐ݩ$": 8350772684161555590, + "ㆎQ䄾\u001bpᩭ${[諟^^骴᤮b^ㅥI┧T㉇⾞\"绦r䰂f矩'-7䡭桥Dz兔V9谶居㺍ᔊ䩯덲.\u001eL0ὅㅷ釣": [{ + "<쯬J卷^숞u࠯䌗艞R9닪g㐾볎a䂈歖意:%鐔|ﵤ|y}>;2,覂⶚啵tb*仛8乒㓶B࿠㯉戩oX 貘5V嗆렽낁߼4h䧛ꍺM空\\b꿋貼": 8478577078537189402, + "VD*|吝z~h譺aᯒ": { + "YI췢K<\/濳xNne玗rJo쾘3핰鴊\"↱AR:ࢷ\"9?\"臁說)?誚ꊏe)_D翾W?&F6J@뺾ꍰNZ醊Z쾈വH嶿?炫㷱鬰M겈᭨b,⻁鈵P䕡䀠८ⱄ홎鄣": { + "@?k2鶖㋮\"Oರ K㨇廪儲\u0017䍾J?);\b*묀㗠섳햭1MC V": null, + "UIICP!BUA`ᢈ㋸~袩㗪⾒=fB﮴l1ꡛ죘R辂여ҳ7쮡<䩲`熕8頁": 4481809488267626463, + "Y?+8먙ᚔ鋳蜩럶1㥔y璜౩`": [ + null, + 1.2850335807501874E-19, + "~V2", + 2035406654801997866, + { + "<숻1>\"": -8062468865199390827, + "M㿣E]}qwG莎Gn᝶(ꔙ\\D⬲iꇲs寢t駇S뀡ꢜ": false, + "pꝤ㎏9W%>M;-U璏f(^j1?&RB隧 忓b똊E": "#G?C8.躬ꥯ'?냪#< 渟&헿란zpo왓Kj}鷧XﻘMツb䕖;㪻", + "vE풤幉xz뱕쫥Ug㦲aH} ᣟp:鬼YᰟH3镔ᴚ斦\\鏑r*2橱G⼔F/.j": true, + "RK좬뎂a홠f*f㱉ᮍ⦋潙㨋Gu곌SGI3I뿐\\F',)t`荁蘯囯ﮉ裲뇟쥼_ገ驪▵撏ᕤV": 1.52738225997956557E18, + "^k굲䪿꠹B逤%F㱢漥O披M㽯镞竇霒i꼂焅륓\u00059=皫之눃\u2047娤閍銤唫ၕb<\/w踲䔼u솆맚,䝒ᝳ'/it": "B餹饴is権ꖪ怯ꦂẉဎt\"!凢谵⧿0\\<=(uL䷍刨쑪>俆揓Cy襸Q힆䆭涷<\/ᐱ0ɧ䗾䚹\\ኜ?ꄢᇘ`䴢{囇}᠈䴥X4퓪檄]ꥷ/3謒ሴn+g騍X", + "GgG꽬[(嫓몍6\u0004궍宩㙻/>\u0011^辍dT腪hxǑ%ꊇk,8(W⧂結P鬜O": [{ + "M㴾c>\\ᓲ\u0019V{>ꤩ혙넪㭪躂TS-痴໸闓⍵/徯O.M㏥ʷD囎⧔쁳휤T??鉬뇙=#ꢫ숣BX䭼<\/d똬졬g榿)eꨋﯪ좇첻\u001a\u0011\";~쓆BH4坋攊7힪", + "iT:L闞椕윚*滛gI≀Wਟඊ'ꢆ縺뱹鮚Nꩁ᧬蕼21줧\\䋯``⍐\\㏱鳨": 1927052677739832894, + "쮁缦腃g]礿Y㬙 fヺSɪ꾾N㞈": [ + null, + null, + { + "!t,灝Y 1䗉罵?c饃호䉂Cᐭ쒘z(즽sZG㬣sഖE4뢜㓕䏞丮Qp簍6EZឪ겛fx'ꩱQ0罣i{k锩*㤴㯞r迎jTⲤ渔m炅肳": [ + -3.3325685522591933E18, + [{"㓁5]A䢕1룥BC?Ꙍ`r룔Ⳛ䙡u伲+\u0001്o": [ + null, + 4975309147809803991, + null, + null, + {"T팘8Dﯲ稟MM☻㧚䥧/8ﻥ⥯aXLaH\"顾S☟耲ît7fS෉놁뮔/ꕼ䓈쁺4\\霶䠴ᩢ<\/t4?죵>uD5➶༆쉌럮⢀秙䘥\u20972ETR3濡恆vB? ~鸆\u0005": { + "`閖m璝㥉b뜴?Wf;?DV콜\u2020퍉౓擝宏ZMj3mJ먡-傷뱙yח㸷꥿ ໘u=M읝!5吭L4v\\?ǎ7C홫": null, + "|": false, + "~Ztᛋ䚘\\擭㗝傪W陖+㗶qᵿ蘥ᙄp%䫎)}=⠔6ᮢS湟-螾-mXH?cp": 448751162044282216, + "\u209fad놹j檋䇌ᶾ梕㉝bוּ": {"?苴ꩠD䋓帘5騱qﱖPF?☸珗顒yU ᡫcb䫎 S@㥚gꮒ쎘泴멖\\:I鮱TZ듒ᶨQ3+f7캙\"?\f풾\\o杞紟﻽M.⏎靑OP": [ + -2.6990368911551596E18, + [{"䒖@<᰿<\/⽬tTr腞&G%᳊秩蜰擻f㎳?S㵧\r*k뎾-乢겹隷j軛겷0룁鮁": {")DO0腦:춍逿:1㥨่!蛍樋2": [{ + ",ꌣf侴笾m๫ꆽ?1?U?\u0011ꌈꂇ": { + "x捗甠nVq䅦w`CD⦂惺嘴0I#vỵ} \\귂S끴D얾?Ԓj溯\"v餄a": { + "@翙c⢃趚痋i\u0015OQ⍝lq돆Y0pࢥ3쉨䜩^<8g懥0w)]䊑n洺o5쭝QL댊랖L镈Qnt⪟㒅십q헎鳒⮤眉ᔹ梠@O縠u泌ㄘb榚癸XޔFtj;iC": false, + "I&뱋゘|蓔䔕측瓯%6ᗻHW\\N1貇#?僐ᗜgh᭪o'䗈꽹Rc욏/蔳迄༝!0邔䨷푪8疩)[쭶緄㇈୧ፐ": { + "B+:ꉰ`s쾭)빼C羍A䫊pMgjdx䐝Hf9᥸W0!C樃'蘿f䫤סи\u0017Jve? 覝f둀⬣퓉Whk\"஼=չﳐ皆笁BIW虨쫓F廰饞": -642906201042308791, + "sb,XcZ<\/m㉹ ;䑷@c䵀s奤⬷7`ꘖ蕘戚?Feb#輜}p4nH⬮eKL트}": [ + "RK鳗z=袤Pf|[,u욺", + "Ẏᏻ罯뉋⺖锅젯㷻{H䰞쬙-쩓D]~\u0013O㳢gb@揶蔉|kᦂ❗!\u001ebM褐sca쨜襒y⺉룓", + null, + null, + true, + -1.650777344339075E-19, + false, + "☑lꄆs힨꤇]'uTന⌳농].1⋔괁沰\"IWഩ\u0019氜8쟇䔻;3衲恋,窌z펏喁횗?4?C넁问?ᥙ橭{稻Ⴗ_썔", + "n?]讇빽嗁}1孅9#ꭨ靶v\u0014喈)vw祔}룼쮿I", + -2.7033457331882025E18, + { + ";⚃^㱋x:饬ኡj'꧵T☽O㔬RO婎?향ᒭ搩$渣y4i;(Q>꿘e8q": "j~錘}0g;L萺*;ᕭꄮ0l潛烢5H▄쳂ꏒוֹꙶT犘≫x閦웧v", + "~揯\u2018c4職렁E~ᑅቚꈂ?nq뎤.:慹`F햘+%鉎O瀜쟏敛菮⍌浢<\/㮺紿P鳆ࠉ8I-o?#jﮨ7v3Dt赻J9": null, + "ࣝW䌈0ꍎqC逖,횅c၃swj;jJS櫍5槗OaB>D踾Y": {"㒰䵝F%?59.㍈cᕨ흕틎ḏ㋩B=9IېⓌ{:9.yw}呰ㆮ肒᎒tI㾴62\"ዃ抡C﹬B<\/촋jo朣", + [ + -7675533242647793366, + {"ᙧ呃:[㒺쳀쌡쏂H稈㢤\u001dᶗGG-{GHྻຊꡃ哸䵬;$?&d\\⥬こN圴됤挨-'ꕮ$PU%?冕눖i魁q騎Q": [ + false, + [[ + 7929823049157504248, + [[ + true, + "Z菙\u0017'eꕤ᱕l,0\\X\u001c[=雿8蠬L<\/낲긯W99g톉4ퟋb㝺\u0007劁'!麕Q궈oW:@X၎z蘻m絙璩귓죉+3柚怫tS捇蒣䝠-擶D[0=퉿8)q0ٟ", + "唉\nFA椭穒巯\\䥴䅺鿤S#b迅獘 ﶗ꬘\\?q1qN犠pX꜅^䤊⛤㢌[⬛휖岺q唻ⳡ틍\"㙙Eh@oA賑㗠y必Nꊑᗘ", + -2154220236962890773, + -3.2442003245397908E18, + "Wᄿ筠:瘫퀩?o貸q⊻(᎞KWf宛尨h^残3[U(='橄", + -7857990034281549164, + 1.44283696979059942E18, + null, + {"ꫯAw跭喀 ?_9\"Aty背F=9缉ྦྷ@;?^鞀w:uN㘢Rỏ": [ + 7.393662029337442E15, + 3564680942654233068, + [ + false, + -5253931502642112194, + "煉\\辎ೆ罍5⒭1䪁䃑s䎢:[e5}峳ﴱn騎3?腳Hyꏃ膼N潭錖,Yᝋ˜YAၓ㬠bG렣䰣:", + true, + null, + { + "⒛'P&%죮|:⫶춞": -3818336746965687085, + "钖m<\/0ݎMtF2Pk=瓰୮洽겎.": [[ + -8757574841556350607, + -3045234949333270161, + null, + { + "Ꮬr輳>⫇9hU##w@귪A\\C 鋺㘓ꖐ梒뒬묹㹻+郸嬏윤'+g<\/碴,}ꙫ>손;情d齆J䬁ຩ撛챝탹/R澡7剌tꤼ?ặ!`⏲睤\u00002똥଴⟏": null, + "\u20f2ܹe\\tAꥍư\\x当뿖렉禛;G檳ﯪS૰3~㘠#[J<}{奲 5箉⨔{놁<\/釿抋,嚠/曳m&WaOvT赋皺璑텁": [[ + false, + null, + true, + -5.7131445659795661E18, + "萭m䓪D5|3婁ఞ>蠇晼6nﴺPp禽羱DS<睓닫屚삏姿", + true, + [ + -8759747687917306831, + { + ">ⓛ\t,odKr{䘠?b퓸C嶈=DyEᙬ@ᴔ쨺芛髿UT퓻春<\/yꏸ>豚W釺N뜨^?꽴﨟5殺ᗃ翐%>퍂ဿ䄸沂Ea;A_\u0005閹殀W+窊?Ꭼd\u0013P汴G5썓揘": 4.342729067882445E-18, + "Q^즾眆@AN\u0011Kb榰냎Y#䝀ꀒᳺ'q暇睵s\"!3#I⊆畼寤@HxJ9": false, + "⿾D[)袨㇩i]웪䀤ᛰMvR<蟏㣨": {"v퇓L㪱ꖣ豛톤\\곱#kDTN": [{ + "(쾴䡣,寴ph(C\"㳶w\"憳2s馆E!n!&柄<\/0Pꈗſ?㿳Qd鵔": {"娇堰孹L錮h嵅⛤躏顒?CglN束+쨣ﺜ\\MrH": {"獞䎇둃ቲ弭팭^ꄞ踦涟XK錆쳞ឌ`;੶S炥騞ଋ褂B៎{ڒ䭷ᶼ靜pI荗虶K$": [{"◖S~躘蒉꫿輜譝Q㽙闐@ᢗ¥E榁iء5┄^B[絮跉ᰥ遙PWi3wㄾⵀDJ9!w㞣ᄎ{듒ꓓb6\\篴??c⼰鶹⟧\\鮇ꮇ": [[ + 654120831325413520, + -1.9562073916357608E-19, + { + "DC(昐衵ἡ긙갵姭|֛[t": 7.6979110359897907E18, + "J␅))嫼❳9Xfd飉j7猬ᩉ+⤻眗벎E鰉Zᄊ63zၝ69}ZᶐL崭ᦥ⡦靚⋛ꎨ~i㨃咊ꧭo䰠阀3C(": -3.5844809362512589E17, + "p꣑팱쒬ꎑ뛡Ꙩ挴恍胔&7ᔈ묒4Hd硶훐㎖zꢼ豍㿢aሃ=<\/湉鵲EӅ%$F!퍶棌孼{O駍਺geu+": ")\u001b잓kŀX쩫A밁®ڣ癦狢)扔弒p}k縕ꩋ,䃉tࣼi", + "ァF肿輸<솄G-䢹䛸ꊏl`Tqꕗ蒞a氷⸅ᴉ蠰]S/{J왲m5{9.uέ~㕚㣹u>x8U讁B덺襪盎QhVS맅킃i识{벂磄Iහ䙅xZy/抍૭Z鲁-霳V据挦ℒ": null, + "㯛|Nꐸb7ⵐb?拠O\u0014ކ?-(EꞨ4ꕷᄤYᯕOW瞺~螸\"욿ќe㺰\"'㌢ƐW\u0004瞕>0?V鷵엳": true, + "뤥G\\迋䠿[庩'꼡\u001aiᩮV쯁ᳪ䦪Ô;倱ନ뛁誈": null, + "쥹䄆䚟Q榁䎐᢭<\/2㕣p}HW蟔|䃏꿈ꚉ锳2Pb7㙑Tⅹᵅ": { + "Y?֭$>#cVBꩨ:>eL蒁務": { + "86柡0po 䏚&-捑Ћ祌<\/휃-G*㶢הּ쩍s㶟餇c걺yu꽎還5*턧簕Og婥SꝐ": null, + "a+葞h٥ࠆ裈嗫ﵢ5輙퀟ᛜ,QDﹼ⟶Y騠锪E_|x죗j侵;m蜫轘趥?븅w5+mi콛L": { + ";⯭ﱢ!买F⽍柤鶂n䵣V㫚墱2렾ELEl⣆": [ + true, + -3.6479311868339015E-18, + -7270785619461995400, + 3.334081886177621E18, + 2.581457786298155E18, + -6.605252412954115E-20, + -3.9232347037744167E-20, + { + "B6㊕.k1": null, + "ZAꄮJ鮷ᳱo갘硥鈠䠒츼": { + "ᕅ}럡}.@y陪鶁r業'援퀉x䉴ﵴl퍘):씭脴ᥞhiꃰblﲂ䡲엕8߇M㶭0燋標挝-?PCwe⾕J碻Ᾱ䬈䈥뷰憵賣뵓痬+": {"a췩v礗X⋈耓ፊf罅靮!㔽YYᣓw澍33⎔芲F|\"䜏T↮輦挑6ᓘL侘?ᅥ]덆1R௯✎餘6ꏽ<\/௨\\?q喷ꁫj~@ulq": {"嗫欆뾔Xꆹ4H㌋F嵧]ࠎ]㠖1ꞤT<$m뫏O i댳0䲝i": {"?෩?\u20cd슮|ꯆjs{?d7?eNs⢚嫥氂䡮쎱:鑵롟2hJꎒﯭ鱢3춲亄:뼣v䊭諱Yj択cVmR䩃㘬T\"N홝*ै%x^F\\_s9보zz4淗?q": [ + null, + "?", + 2941869570821073737, + "{5{殇0䝾g6밖퍋臩綹R$䖭j紋釰7sXI繳漪행y", + false, + "aH磂?뛡#惇d婅?Fe,쐘+늵䍘\"3r瘆唊勐j⳧࠴ꇓ<\/唕윈x⬌讣䋵%拗ᛆⰿ妴᝔M2㳗必꧂淲?ゥ젯檢<8끒MidX䏒3᳻Q▮佐UT|⤪봦靏⊏", + [[{ + "颉(&뜸귙{y^\"P퟉춝Ჟ䮭D顡9=?}Y誱<$b뱣RvO8cH煉@tk~4ǂ⤧⩝屋SS;J{vV#剤餓ᯅc?#a6D,s": [ + -7.8781018564821536E16, + true, + [ + -2.28770899315832371E18, + false, + -1.0863912140143876E-20, + -6282721572097446995, + 6767121921199223078, + -2545487755405567831, + false, + null, + -9065970397975641765, + [ + -5.928721243413937E-20, + {"6촊\u001a홯kB0w撨燠룉{绎6⳹!턍贑y▾鱧ժ[;7ᨷ∀*땒䪮1x霆Hᩭ☔\"r䝐7毟ᝰr惃3ꉭE+>僒澐": [ + "Ta쎩aƝt쵯ⰪVb", + [ + -5222472249213580702, + null, + -2851641861541559595, + null, + 4808804630502809099, + 5657671602244269874, + "5犲﨣4mᥣ?yf젫꾯|䋬잁$`Iⳉﴷ扳兝,'c", + false, + [ + null, + { + "DyUIN쎾M仼惀⮥裎岶泭lh扠\u001e礼.tEC癯튻@_Qd4c5S熯A<\/\6U윲蹴Q=%푫汹\\\u20614b[௒C⒥Xe⊇囙b,服3ss땊뢍i~逇PA쇸1": -2.63273619193485312E17, + "Mq꺋貘k휕=nK硍뫞輩>㾆~἞ࡹ긐榵l⋙Hw뮢帋M엳뢯v⅃^": 1877913476688465125, + "ᶴ뻗`~筗免⚽টW˃⽝b犳䓺Iz篤p;乨A\u20ef쩏?疊m㝀컩뫡b탔鄃ᾈV(遢珳=뎲ିeF仢䆡谨8t0醄7㭧瘵⻰컆r厡궥d)a阄፷Ed&c﯄伮1p": null, + "⯁w4曢\"(欷輡": "\"M᭫]䣒頳B\\燧ࠃN㡇j姈g⊸⺌忉ꡥF矉স%^", + "㣡Oᄦ昵⫮Y祎S쐐級㭻撥>{I$": -378474210562741663, + "䛒掷留Q%쓗1*1J*끓헩ᦢ﫫哉쩧EↅIcꅡ\\?ⴊl귛顮4": false, + "寔愆샠5]䗄IH贈=d﯊/偶?ॊn%晥D視N򗘈'᫂⚦|X쵩넽z질tskxDQ莮Aoﱻ뛓": true, + "钣xp?&\u001e侉/y䴼~?U篔蘚缣/I畚?Q绊": -3034854258736382234, + "꺲໣眀)⿷J暘pИfAV삕쳭Nꯗ4々'唄ⶑ伻㷯騑倭D*Ok꧁3b␽_<\/챣Xm톰ၕ䆄`*fl㭀暮滠毡?": [ + "D男p`V뙸擨忝븪9c麺`淂⢦Yw⡢+kzܖ\fY1䬡H歁)벾Z♤溊-혰셢?1<-\u0005;搢Tᐁle\\ᛵߓﭩ榩訝-xJ;巡8깊蠝ﻓU$K": { + "Vꕡ諅搓W=斸s︪vﲜ츧$)iꡟ싉e寳?ጭムVથ嵬i楝Fg<\/Z|៪ꩆ-5'@ꃱ80!燱R쇤t糳]罛逇dṌ֣XHiͦ{": true, + "Ya矲C멗Q9膲墅携휻c\\딶G甔<\/.齵휴": -1.1456247877031811E-19, + "z#.OO￝J": -8263224695871959017, + "崍_3夼ᮟ1F븍뽯ᦓ鴭V豈Ь": [{ + "N蒬74": null, + "yuB?厅vK笗!ᔸcXQ旦컶P-녫mᄉ麟_": "1R@ 톘xa_|﩯遘s槞d!d껀筤⬫薐焵먑D{\\6k共倌☀G~AS_D\"딟쬚뮥馲렓쓠攥WTMܭ8nX㩴䕅檹E\u0007ﭨN 2 ℆涐ꥏ꠵3▙玽|됨_\u2048", + "恐A C䧩G": {":M큣5e들\\ꍀ恼ᔄ靸|I﨏$)n": { + "|U䬫㟯SKV6ꛤ㗮\bn봻䲄fXT:㾯쳤'笓0b/ೢC쳖?2浓uO.䰴": "ཐ꼋e?``,ᚇ慐^8ꜙNM䂱\u0001IᖙꝧM'vKdꌊH牮r\\O@䊷ᓵ쀆(fy聻i툺\"?<\/峧ࣞ⓺ᤤ쵒߯ꎺ騬?)刦\u2072l慪y꺜ﲖTj+u", + "뽫hh䈵w>1ⲏ쐭V[ⅎ\\헑벑F_㖝⠗㫇h恽;῝汰ᱼ瀖J옆9RR셏vsZ柺鶶툤r뢱橾/ꉇ囦FGm\"謗ꉦ⨶쒿⥡%]鵩#ᖣ_蹎 u5|祥?O", + null, + 2.0150326776036215E-19, + null, + true, + false, + true, + {"\fa᭶P捤WWc᠟f뚉ᬏ퓗ⳀW睹5:HXH=q7x찙X$)모r뚥ᆟ!Jﳸf": [ + -2995806398034583407, + [ + 6441377066589744683, + "Mﶒ醹i)Gἦ廃s6몞 KJ౹礎VZ螺费힀\u0000冺업{谥'꡾뱻:.ꘘ굄奉攼Di᷑K鶲y繈욊阓v㻘}枭캗e矮1c?휐\"4\u0005厑莔뀾墓낝⽴洗ṹ䇃糞@b1\u0016즽Y轹", + { + "1⽕⌰鉟픏M㤭n⧴ỼD#%鐘⊯쿼稁븣몐紧ᅇ㓕ᛖcw嬀~ഌ㖓(0r⧦Q䑕髍ര铂㓻R儮\"@ꇱm❈௿᦯頌8}㿹犴?xn잆꥽R": 2.07321075750427366E18, + "˳b18㗈䃟柵Z曆VTAu7+㛂cb0﯑Wp執<\/臋뭡뚋刼틮荋벲TLP预庰܈G\\O@VD'鱃#乖끺*鑪ꬳ?Mޞdﭹ{␇圯쇜㼞顄︖Y홡g": [{ + "0a,FZ": true, + "2z̬蝣ꧦ驸\u0006L↛Ḣ4๚뿀'?lcwᄧ㐮!蓚䃦-|7.飑挴.樵*+1ﮊ\u0010ꛌ%貨啺/JdM:똍!FBe?鰴㨗0O财I藻ʔWA᫓G쳛u`<\/I": [{ + "$τ5V鴐a뾆両環iZp頻යn븃v": -4869131188151215571, + "*즢[⦃b礞R◚nΰꕢH=귰燙[yc誘g䆌?ଜ臛": { + "洤湌鲒)⟻\\䥳va}PeAMnN[": "㐳ɪ/(軆lZR,Cp殍ȮN啷\"3B婴?i=r$펽ᤐ쀸", + "阄R4㒿㯔ڀ69ZᲦ2癁핌噗P崜#\\-쭍袛&鐑/$4童V꩑_ZHA澢fZ3": {"x;P{긳:G閉:9?活H": [ + "繺漮6?z犞焃슳\">ỏ[Ⳛ䌜녏䂹>聵⼶煜Y桥[泥뚩MvK$4jtロ", + "E#갶霠좭㦻ୗ먵F+䪀o蝒ba쮎4X㣵 h", + -335836610224228782, + null, + null, + [ + "r1᫩0>danjY짿bs{", + [ + -9.594464059325631E-23, + 1.0456894622831624E-20, + null, + 5.803973284253454E-20, + -8141787905188892123, + true, + -4735305442504973382, + 9.513150514479281E-20, + "7넳$螔忷㶪}䪪l짴\u0007鹁P鰚HF銏ZJﳴ/⍎1ᷓ忉睇ᜋ쓈x뵠m䷐窥Ꮤ^\u0019ᶌ偭#ヂt☆၃pᎍ臶䟱5$䰵&๵分숝]䝈뉍♂坎\u0011<>", + "C蒑貑藁lﰰ}X喇몛;t밿O7/᯹f\u0015kI嘦<ዴ㟮ᗎZ`GWퟩ瑹࡮ᅴB꿊칈??R校s脚", + { + "9珵戬+AU^洘拻ቒy柭床'粙XG鞕᠜繀伪%]hC,$輙?Ut乖Qm떚W8઼}~q⠪rU䤶CQ痗ig@#≲t샌f㈥酧l;y闥ZH斦e⸬]j⸗?ঢ拻퀆滌": null, + "畯}㧢J罚帐VX㨑>1ꢶkT⿄蘥㝑o|<嗸層沈挄GEOM@-䞚䧰$만峬輏䠱V✩5宸-揂D'㗪yP掶7b⠟J㕻SfP?d}v㼂Ꮕ'猘": { + "陓y잀v>╪": null, + "鬿L+7:됑Y=焠U;킻䯌잫!韎ஔ\f": { + "駫WmGጶ": { + "\\~m6狩K": -2586304199791962143, + "ႜࠀ%͑l⿅D.瑢Dk%0紪dḨTI픸%뗜☓s榗኉\"?V籄7w髄♲쟗翛歂E䤓皹t ?)ᄟ鬲鐜6C": { + "_췤a圷1\u000eB-XOy缿請∎$`쳌eZ~杁튻/蜞`塣৙\"⪰\"沒l}蕌\\롃荫氌.望wZ|o!)Hn獝qg}": null, + "kOSܧ䖨钨:಼鉝ꭝO醧S`십`ꓭ쭁ﯢN&Et㺪馻㍢ⅳ㢺崡ຊ蜚锫\\%ahx켨|ż劻ꎄ㢄쐟A躊᰹p譞綨Ir쿯\u0016ﵚOd럂*僨郀N*b㕷63z": { + ":L5r+T㡲": [{ + "VK泓돲ᮙRy㓤➙Ⱗ38oi}LJቨ7Ó㹡৘*q)1豢⛃e᫛뙪壥镇枝7G藯g㨛oI䄽 孂L缊ꋕ'EN`": -2148138481412096818, + "`⛝ᘑ$(खꊲ⤖ᄁꤒ䦦3=)]Y㢌跨NĴ驳줟秠++d孳>8ᎊ떩EꡣSv룃 쯫أ?#E|᭙㎐?zv:5祉^⋑V": [ + -1.4691944435285607E-19, + 3.4128661569395795E17, + "㐃촗^G9佭龶n募8R厞eEw⺡_ㆱ%⼨D뉄퉠2ꩵᛅⳍ搿L팹Lවn=\"慉념ᛮy>!`g!풲晴[/;?[v겁軇}⤳⤁핏∌T㽲R홓遉㓥", + "愰_⮹T䓒妒閤둥?0aB@㈧g焻-#~跬x<\/舁P݄ꐡ=\\׳P\u0015jᳪᢁq;㯏l%᭗;砢觨▝,謁ꍰGy?躤O黩퍋Y㒝a擯\n7覌똟_䔡]fJ晋IAS", + 4367930106786121250, + -4.9421193149720582E17, + null, + { + ";ᄌ똾柉곟ⰺKpፇ䱻ฺ䖝{o~h!eꁿ઻욄ښ\u0002y?xUd\u207c悜ꌭ": [ + 1.6010824122815255E-19, + [ + "宨︩9앉檥pr쇷?WxLb", + "氇9】J玚\u000f옛呲~ 輠1D嬛,*mW3?n휂糊γ虻*ᴫ꾠?q凐趗Ko↦GT铮", + "㶢ថmO㍔k'诔栀Z蛟}GZ钹D", + false, + -6.366995517736813E-20, + -4894479530745302899, + null, + "V%᫡II璅䅛䓎풹ﱢ/pU9se되뛞x梔~C)䨧䩻蜺(g㘚R?/Ự[忓C뾠ࢤc왈邠买?嫥挤풜隊枕", + ",v碍喔㌲쟚蔚톬៓ꭶ", + 3.9625444752577524E-19, + null, + [ + "kO8란뿒䱕馔b臻⍟隨\"㜮鲣Yq5m퐔K#ꢘug㼈ᝦ=P^6탲@䧔%$CqSw铜랊0&m⟭<\/a逎ym\u0013vᯗ": true, + "洫`|XN뤮\u0018詞=紩鴘_sX)㯅鿻Ố싹": 7.168252736947373E-20, + "ꛊ饤ﴏ袁(逊+~⽫얢鈮艬O힉7D筗S곯w操I斞᠈븘蓷x": [[[[ + -7.3136069426336952E18, + -2.13572396712722688E18, + { + "硢3㇩R:o칢行E<=\u0018ၬYuH!\u00044U%卝炼2>\u001eSi$⓷ꒈ'렢gᙫ番ꯒ㛹럥嶀澈v;葷鄕x蓎\\惩+稘UEᖸﳊ㊈壋N嫿⏾挎,袯苷ኢ\\x|3c": 7540762493381776411, + "?!*^ᢏ窯?\u0001ڔꙃw虜돳FgJ?&⨫*uo籤:?}ꃹ=ٴ惨瓜Z媊@ત戹㔏똩Ԛ耦Wt轁\\枒^\\ꩵ}}}ꀣD\\]6M_⌫)H豣:36섘㑜": { + ";홗ᰰU஋㙛`D왔ཿЃS회爁\u001b-㢈`봆?盂㛣듿ᦾ蒽_AD~EEຆ㊋(eNwk=Rɠ峭q\"5Ἠ婾^>'ls\n8QAK)- Q䲌mo펹L_칍樖庫9꩝쪹ᘹ䑖瀍aK ?*趤f뭓廝p=磕", + "哑z懅ᤏ-ꍹux쀭", + [ + true, + 3998739591332339511, + "ጻ㙙?᳸aK<\/囩U`B3袗ﱱ?\"/k鏔䍧2l@쿎VZ쨎/6ꃭ脥|B?31+on颼-ꮧ,O嫚m ࡭`KH葦:粘i]aSU쓙$쐂f+詛頖b", + [{"^<9<箝&絡;%i﫡2攑紴\\켉h쓙-柂䚝ven\u20f7浯-Ꮏ\r^훁䓚헬\u000e?\\ㅡֺJ떷VOt": [{ + "-௄卶k㘆혐஽y⎱㢬sS઄+^瞥h;ᾷj;抭\u0003밫f<\/5Ⱗ裏_朻%*[-撵䷮彈-芈": { + "㩩p3篊G|宮hz䑊o곥j^Co0": [ + 653239109285256503, + {"궲?|\":N1ۿ氃NZ#깩:쇡o8킗ࡊ[\"됸Po핇1(6鰏$膓}⽐*)渽J'DN<썙긘毦끲Ys칖": { + "2Pr?Xjㆠ?搮/?㓦柖馃5뚣Nᦼ|铢r衴㩖\"甝湗ܝ憍": "\"뾯i띇筝牻$珲/4ka $匝휴译zbAᩁꇸ瑅&뵲衯ꎀᆿ7@ꈋ'ᶨH@ᠴl+", + "7뢽뚐v?4^ꊥ_⪛.>pởr渲<\/⢕疻c\"g䇘vU剺dஔ鮥꒚(dv祴X⼹\\a8y5坆": true, + "o뼄B욞羁hr﷔폘뒚⿛U5pꪴfg!6\\\"爑쏍䢱W<ﶕ\\텣珇oI/BK뺡'谑♟[Ut븷亮g(\"t⡎有?ꬊ躺翁艩nl F⤿蠜": 1695826030502619742, + "ۊ깖>ࡹ햹^ⵕ쌾BnN〳2C䌕tʬ]찠?ݾ2饺蹳ぶꌭ訍\"◹ᬁD鯎4e滨T輀ﵣ੃3\u20f3킙D瘮g\\擦+泙ၧ 鬹ﯨַ肋7놷郟lP冝{ߒhড়r5,꓋": null, + "ΉN$y{}2\\N﹯ⱙK'8ɜͣwt,.钟廣䎘ꆚk媄_": null, + "䎥eᾆᝦ읉,Jުn岪㥐s搖謽䚔5t㯏㰳㱊ZhD䃭f絕s鋡篟a`Q鬃┦鸳n_靂(E4迠_觅뷝_宪D(NL疶hL追V熑%]v肫=惂!㇫5⬒\u001f喺4랪옑": { + "2a輍85먙R㮧㚪Sm}E2yꆣꫨrRym㐱膶ᔨ\\t綾A☰.焄뙗9<쫷챻䒵셴᭛䮜.<\/慌꽒9叻Ok䰊Z㥪幸k": [ + null, + true, + {"쌞쐍": { + "▟GL K2i뛱iQ\"̠.옛1X$}涺]靎懠ڦ늷?tf灟ݞゟ{": 1.227740268699265E-19, + "꒶]퓚%ฬK❅": [{ + "(ෛ@Ǯっ䧼䵤[aテൖvEnAdU렖뗈@볓yꈪ,mԴ|꟢캁(而첸죕CX4Y믅": "2⯩㳿ꢚ훀~迯?᪑\\啚;4X\u20c2襏B箹)俣eỻw䇄", + "75༂f詳䅫ꐧ鏿 }3\u20b5'∓䝱虀f菼Iq鈆﨤g퍩)BFa왢d0뮪痮M鋡nw∵謊;ꝧf美箈ḋ*\u001c`퇚퐋䳫$!V#N㹲抗ⱉ珎(V嵟鬒_b㳅\u0019": null, + "e_m@(i㜀3ꦗ䕯䭰Oc+-련0뭦⢹苿蟰ꂏSV䰭勢덥.ྈ爑Vd,ᕥ=퀍)vz뱊ꈊB_6듯\"?{㒲&㵞뵫疝돡믈%Qw限,?\r枮\"? N~癃ruࡗdn&": null, + "㉹&'Pfs䑜공j<\/?|8oc᧨L7\\pXᭁ 9᪘": -2.423073789014103E18, + "䝄瑄䢸穊f盈᥸,B뾧푗횵B1쟢f\u001f凄": "魖⚝2儉j꼂긾껢嗎0ࢇ纬xI4](੓`蕞;픬\fC\"斒\")2櫷I﹥迧", + "ퟯ詔x悝령+T?Bg⥄섅kOeQ큼㻴*{E靼6氿L缋\u001c둌๶-㥂2==-츫I즃㠐Lg踞ꙂEG貨鞠\"\u0014d'.缗gI-lIb䋱ᎂDy缦?": null, + "紝M㦁犿w浴詟棓쵫G:䜁?V2ힽ7N*n&㖊Nd-'ຊ?-樹DIv⊜)g䑜9뉂ㄹ푍阉~ꅐ쵃#R^\u000bB䌎䦾]p.䀳": [{"ϒ爛\"ꄱ︗竒G䃓-ま帳あ.j)qgu扐徣ਁZ鼗A9A鸦甈!k蔁喙:3T%&㠘+,䷞|챽v䚞문H<\/醯r셓㶾\\a볜卺zE䝷_죤ဵ뿰᎟CB": [ + 6233512720017661219, + null, + -1638543730522713294, + false, + -8901187771615024724, + [ + 3891351109509829590, + true, + false, + -1.03836679125188032E18, + { + "j랎:g曞ѕᘼ}链N", + -1.1103819473845426E-19, + true, + [ + true, + null, + -7.9091791735309888E17, + true, + {"}蔰鋈+ꐨ啵0?g*사%`J?*": [{ + "\"2wG?yn,癷BK\\龞䑞x?蠢": -3.7220345009853505E-19, + ";饹়❀)皋`噿焒j(3⿏w>偍5X薙婏聿3aFÆÝ": "2,ꓴg?_섦_>Y쪥션钺;=趘F~?D㨫\bX?㹤+>/믟kᠪ멅쬂Uzỵ]$珧`m雁瑊ඖ鯬cꙉ梢f묛bB", + "♽n$YjKiXX*GO贩鏃豮祴遞K醞眡}ꗨv嵎꼷0୸+M菋eH徸J꣆:⼐悥B켽迚㯃b諂\u000bjꠜ碱逮m8": [ + "푷᣺ﻯd8ﱖ嬇ភH鹎⡱᱅0g:果6$GQ췎{vᷧYy-脕x偹砡館⮸C蓼ꏚ=軄H犠G谖ES詤Z蠂3l봟hᅭ7䦹1GPQG癸숟~[#駥8zQ뛣J소obg,", + null, + 1513751096373485652, + null, + -6.851466660824754E-19, + {"䩂-⴮2ٰK솖풄꾚ႻP앳1H鷛wmR䗂皎칄?醜<\/&ࠧ㬍X濬䵈K`vJ륒Q/IC묛!;$vϑ": { + "@-ꚗxྐྵ@m瘬\u0010U絨ﮌ驐\\켑寛넆T=tQ㭤L연@脸삯e-:⩼u㎳VQ㋱襗ຓ<Ⅶ䌸cML3+\u001e_C)r\\9+Jn\\Pﺔ8蠱檾萅Pq鐳话T䄐I": -1.80683891195530061E18, + "ᷭዻU~ཷsgSJ`᪅'%㖔n5픆桪砳峣3獮枾䌷⊰呀": { + "Ş੉䓰邟自~X耤pl7间懑徛s첦5ਕXexh⬖鎥᐀nNr(J컗|ૃF\"Q겮葲놔엞^겄+㈆话〾희紐G'E?飕1f❼텬悚泬먐U睬훶Qs": false, + "(\u20dag8큽튣>^Y{뤋.袊䂓;_g]S\u202a꽬L;^'#땏bႌ?C緡<䝲䲝断ꏏ6\u001asD7IK5Wxo8\u0006p弊⼂ꯍ扵\u0003`뵂픋%ꄰ⫙됶l囏尛+䗅E쟇\\": [ + true, + { + "\n鱿aK㝡␒㼙2촹f;`쾏qIࡔG}㝷䐍瓰w늮*粅9뒪ㄊCj倡翑閳R渚MiUO~仨䜶RꙀA僈㉋⦋n{㖥0딿벑逦⥻0h薓쯴Ꝼ": [ + 5188716534221998369, + 2579413015347802508, + 9.010794400256652E-21, + -6.5327297761238093E17, + 1.11635352494065523E18, + -6656281618760253655, + { + "": ")?", + "TWKLꑙ裑꺔UE俸塑炌Ũ᜕-o\"徚#": {"M/癟6!oI51ni퐚=댡>xꍨ\u0004 ?": { + "皭": {"⢫䋖>u%w잼<䕏꘍P䋵$魋拝U䮎緧皇Y훂&|羋ꋕ잿cJ䨈跓齳5\u001a삱籷I꿾뤔S8㌷繖_Yឯ䲱B턼O歵F\\l醴o_欬6籏=D": [ + false, + true, + {"Mt|ꏞD|F궣MQ뵕T,띺k+?㍵i": [ + 7828094884540988137, + false, + { + "!༦鯠,&aﳑ>[euJꏽ綷搐B.h": -7648546591767075632, + "-n켧嘰{7挐毄Y,>❏螵煫乌pv醑Q嶚!|⌝責0왾덢ꏅ蛨S\\)竰'舓Q}A釡5#v": 3344849660672723988, + "8閪麁V=鈢1녈幬6棉⪮둌\u207d᚛驉ꛃ'r䆉惏ै|bἧﺢᒙ<=穊强s혧eꮿ慩⌡ \\槳W븧J檀C,ᘉ의0俯퀉M;筷ࣴ瓿{늊埂鄧_4揸Nn阼Jੵ˥(社": true, + "o뼀vw)4A뢵(a䵢)p姃뛸\u000fK#KiQp\u0005ꅍ芅쏅": null, + "砥$ꥸ┇耽u斮Gc{z빔깎밇\\숰\u001e괷各㶇쵿_ᴄ+h穢p촀Ნ䃬z䝁酳ӂ31xꔄ1_砚W렘G#2葊P ": [ + -3709692921720865059, + null, + [ + 6669892810652602379, + -135535375466621127, + "뎴iO}Z? 馢녱稹ᄾ䐩rSt帤넆&7i騏멗畖9誧鄜'w{Ͻ^2窭외b㑎粖i矪ꦨ탪跣)KEㆹ\u0015V8[W?⽉>'kc$䨘ᮛ뉻٬M5", + 1.10439588726055846E18, + false, + -4349729830749729097, + null, + [ + false, + "_蠢㠝^䟪/D녒㡋ỎC䒈판\u0006એq@O펢%;鹐쏌o戥~A[ꡉ濽ỳ&虃᩾荣唙藍茨Ig楡꒻M窓冉?", + true, + 2.17220752996421728E17, + -5079714907315156164, + -9.960375974658589E-20, + "ᾎ戞༒", + true, + false, + [[ + "ⶉᖌX⧕홇)g엃⹪x뚐癟\u0002", + -5185853871623955469, + { + "L㜤9ợㇶK鐰⋓V뽋˖!斫as|9"፬䆪?7胜&n薑~": -2.11545634977136992E17, + "O8뀩D}캖q萂6༣㏗䈓煮吽ਆᎼDᣘ폛;": false, + "YTᡅ^L㗎cbY$pᣞ縿#fh!ꘂb삵玊颟샞ဢ$䁗鼒몁~rkH^:닮먖츸륈⪺쒉砉?㙓扫㆕꣒`R䢱B酂?C뇞<5Iޚ讳騕S瞦z": null, + "\\RB?`mG댵鉡幐物䵎有5*e骄T㌓ᛪ琾駒Ku\u001a[柆jUq8⋈5鿋츿myﻗ?雍ux঴?": 5828963951918205428, + "n0晅:黯 xu씪^퓞cB㎊ᬍ⺘٤փ~B岚3㥕擄vᲂ~F?C䶖@$m~忔S왖㲚?챴⊟W#벌{'㰝I䝠縁s樘\\X뢻9핡I6菍ㄛ8쯶]wॽ0L\"q": null, + "x增줖j⦦t䏢᎙㛿Yf鼘~꫓恄4惊\u209c": "oOhbᤃ᛽z&Bi犑\\3B㩬劇䄑oŁ쨅孥멁ຖacA㖫借㞝vg싰샂㐜#譞⢤@k]鋰嘘䜾L熶塥_<\/⍾屈ﮊ_mY菹t뙺}Ox=w鮮4S1ꐩמּ'巑", + "㗓蟵ꂾe蠅匳(JP䗏෸\u0089耀왲": [{ + "ᤃ㵥韎뤽\r?挥O쯡⇔㞚3伖\u0005P⋪\"D궣QLn(⚘罩䩢Ŏv䤘尗뼤됛O淽鋋闚r崩a{4箙{煷m6〈": { + "l곺1L": { + "T'ਤ?砅|੬Km]䄩\"(࿶<\/6U爢䫈倔郴l2㴱^줣k'L浖L鰄Rp今鎗⒗C얨M훁㡧ΘX粜뫈N꤇輊㌻켑#㮮샶-䍗룲蠝癜㱐V>=\\I尬癤t=": 7648082845323511446, + "鋞EP:<\/_`ၧe混ㇹBd⯢㮂驋\\q碽饩跓྿ᴜ+j箿렏㗑yK毢宸p謹h䦹乕U媣\\炤": [[ + "3", + [ + true, + 3.4058271399411134E-20, + true, + "揀+憱f逮@먻BpW曉\u001a㣐⎊$n劈D枤㡞좾\u001aᛁ苔౩闝1B䷒Ṋ݋➐ꀞꐃ磍$t੤_:蘺⮼(#N", + 697483894874368636, + [ + "vᘯ锴)0訶}䳅⩚0O壱韈ߜ\u0018*U鍾䏖=䧉뽑单휻ID쿇嘗?ꌸῬ07", + -5.4858784319382006E18, + 7.5467775182251151E18, + -8911128589670029195, + -7531052386005780140, + null, + [ + null, + true, + [[{ + "1欯twG<\/Q:0怯押殃탷聫사<ỗꕧ蚨䡁nDꌕ\u001c녬~蓩鲃g儊>ꏡl㻿/⑷*챳6㻜W毤緛ﹺᨪ4\u0013뺚J髬e3쳸䘦伧?恪&{L掾p+꬜M䏊d娘6": { + "2p첼양棜h䜢﮶aQ*c扦v︥뮓kC寵횂S銩&ǝ{O*य़iH`U큅ࡓr䩕5ꄸ?`\\᧫?ᮼ?t〟崾훈k薐ì/iy꤃뵰z1<\/AQ#뿩8jJ1z@u䕥": 1.82135747285215155E18, + "ZdN &=d년ᅆ'쑏ⅉ:烋5&៏ᄂ汎来L㯄固{钧u\\㊏튚e摑&t嗄ꖄUb❌?m䴘熚9EW": [{ + "ଛ{i*a(": -8.0314147546006822E17, + "⫾ꃆY\u000e+W`௸ \"M뒶+\\뷐lKE}(NT킶Yj選篒쁶'jNQ硾(똡\\\"逌ⴍy? IRꜘ὞鄬﨧:M\\f⠋Cꚜ쫊ᚴNV^D䕗ㅖἔIao꿬C⍏8": [ + 287156137829026547, + { + "H丞N逕⯲": {"": { + "7-;枮阕梒9ᑄZ": [[[[ + null, + { + "": [[[[ + -7.365909561486078E-19, + 2948694324944243408, + null, + [ + true, + "荒\"并孷䂡쵼9o䀘F\u0002龬7⮹Wz%厖/*? a*R枈㌦됾g뒠䤈q딄㺿$쮸tᶎ릑弣^鏎<\/Y鷇驜L鿽<\/춋9Mᲆឨ^<\/庲3'l낢", + "c鮦\u001b두\\~?眾ಢu݆綑෪蘛轋◜gȃ<\/ⴃcpkDt誩܅\"Y", + [[ + null, + null, + [ + 3113744396744005402, + true, + "v(y", + { + "AQ幆h쾜O+꺷铀ꛉ練A蚗⼺螔j㌍3꽂楎䥯뎸먩?": null, + "蠗渗iz鱖w]擪E": 1.2927828494783804E-17, + "튷|䀭n*曎b✿~杤U]Gz鄭kW|㴚#㟗ഠ8u擨": [[ + true, + null, + null, + {"⾪壯톽g7?㥜ώQꑐ㦀恃㧽伓\\*᧰閖樧뢇赸N휶䎈pI氇镊maᬠ탷#X?A+kНM ༑᩟؝?5꧎鰜ṚY즫궔 =ঈ;ﳈ?*s|켦蜌wM笙莔": [ + null, + -3808207793125626469, + [ + -469910450345251234, + 7852761921290328872, + -2.7979740127017492E18, + 1.4458504352519893E-20, + true, + "㽙깹?먏䆢:䴎ۻg殠JBTU⇞}ꄹꗣi#I뵣鉍r혯~脀쏃#釯:场:䔁>䰮o'㼽HZ擓௧nd", + [ + 974441101787238751, + null, + -2.1647718292441327E-19, + 1.03602824249831488E18, + [ + null, + 1.0311977941822604E-17, + false, + true, + { + "": -3.7019778830816707E18, + "E峾恆茍6xLIm縂0n2视֯J-ᤜz+ᨣ跐mYD豍繹⹺䊓몓ﴀE(@詮(!Y膽#᎙2䟓섣A䈀㟎,囪QbK插wcG湎ꤧtG엝x⥏俎j'A一ᯥ뛙6ㅑ鬀": 8999803005418087004, + "よ殳\\zD⧅%Y泥簳Uꈩ*wRL{3#3FYHା[d岀䉯T稉駅䞘礄P:闈W怏ElB㤍喬赔bG䠼U଄Nw鰯闀楈ePsDꥷ꭬⊊": [ + 6.77723657904486E-20, + null, + [ + "ཚ_뷎꾑蹝q'㾱ꂓ钚蘞慵렜떆`ⴹ⎼櫯]J?[t9Ⓢ !컶躔I᮸uz>3a㠕i,錃L$氰텰@7녫W㸮?羧W뇧ꃞ,N鋮숪2ɼ콏┍䁲6", + "&y?뢶=킕올Za惻HZk>c\u20b58i?ꦶcfBv잉ET9j䡡", + "im珊Ճb칧校\\뼾쯀", + 9.555715121193197E-20, + true, + { + "<㫚v6腓㨭e1㕔&&V∌ᗈT奄5Lጥ>탤?튣瑦㳆ꉰ!(ᙪ㿬擇_n쌯IMΉ㕨␰櫈ᱷ5풔蟹&L.첽e鰷쯃劼﫭b#ﭶ퓀7뷄Wr㢈๧Tʴશ㶑澕鍍%": -1810142373373748101, + "fg晌o?߲ꗄ;>C>?=鑰監侯Kt굅": true, + "䫡蓺ꑷ]C蒹㦘\"1ః@呫\u0014NL䏾eg呮፳,r$裢k>/\\?ㄤᇰﻛ쉕1஥'Ċ\" \\_?쨔\"ʾr: 9S䘏禺ᪧꄂ㲄", + [[{ + "*硙^+E쌺I1䀖ju?:⦈Ꞓl๴竣迃xKC/饉:\fl\"XTFᄄ蟭,芢<\/骡軺띜hꏘ\u001f銿<棔햳▨(궆*=乥b8\\媦䷀뫝}닶ꇭ(Kej䤑M": [{ + "1Ꮼ?>옿I╅C<ގ?ꊌ冉SV5A㢊㶆z-๎玶绢2F뵨@㉌뀌o嶔f9-庒茪珓뷳4": null, + ";lᰳ": "CbB+肻a䄷苝*/볳+/4fq=㰁h6瘉샴4铢Y骐.⌖@哼猎㦞+'gꋸ㒕ߤ㞑(䶒跲ti⑴a硂#No볔", + "t?/jE幸YHT셵⩎K!Eq糦ꗣv刴w\"l$ο:=6:移": { + "z]鑪醊嫗J-Xm銌翁絨c里됏炙Ep㣋鏣똼嚌䀓GP﹖cmf4鹭T䅿꣭姧␸wy6ꦶ;S&(}ᎧKxᾂQ|t뻳k\"d6\"|Ml췆hwLt꼼4$&8Պ褵婶鯀9": {"嵃닢ᒯ'd᧫䳳#NXe3-붋鸿ଢ떓%dK\u0013䲎ꖍYV.裸R⍉rR3蟛\\:젯:南ĺLʆ넕>|텩鴷矔ꋅⒹ{t孶㓑4_": [ + true, + null, + [ + false, + "l怨콈lᏒ", + { + "0w䲏嬧-:`䉅쉇漧\\܂yㄨb%㽄j7ᦶ涶<": 3.7899452730383747E-19, + "ꯛTẀq纤q嶏V⿣?\"g}ი艹(쥯B T騠I=仵및X": {"KX6颠+&ᅃ^f畒y[": { + "H?뱜^?꤂-⦲1a㋞&ꍃ精Ii᤾챪咽쬘唂쫷<땡劈훫놡o㥂\\ KⴙD秼F氮[{'좴:례晰Iq+I쭥_T綺砸GO煝䟪ᚪ`↹l羉q쐼D꽁ᜅ훦: vUV": true, + "u^yﳍ0㱓#[y뜌앸ꊬL㷩?蕶蘾⻍KӼ": -7931695755102841701, + "䤬轉車>\u001c鴵惋\"$쯃྆⇻n뽀G氠S坪]ಲꨍ捇Qxኻ椕駔\\9ࣼ﫻읜磡煮뺪ᶚ볝l㕆t+sζ": [[[ + true, + false, + [ + null, + 3363739578828074923, + true, + { + "\"鸣詩 볰㑵gL㯦῅춝旫}ED辗ﮈI쀤-ꧤ|㠦Z\"娑ᕸ4爏騍㣐\"]쳝Af]茛⬻싦o蚁k䢯䩐菽3廇喑ޅ": 4.5017999150704666E17, + "TYႇ7ʠ值4챳唤~Zo&ݛ": false, + "`塄J袛㭆끺㳀N㺣`꽐嶥KﯝSVᶔ∲퀠獾N딂X\"ᤏhNﬨvI": {"\u20bb㭘I䖵䰼?sw䂷쇪](泒f\"~;꼪Fԝsᝦ": {"p,'ꉂ軿=A蚶?bƉ㏵䅰諬'LYKL6B깯⋩겦뎙(ᜭ\u0006噣d꾆㗼Z;䄝䚔cd<情@䞂3苼㸲U{)<6&ꩻ钛\u001au〷N숨囖愙j=BXW욕^x芜堏Ῑ爂뛷꒻t✘Q\b": [[ + "籛&ଃ䩹.ꃩ㦔\\C颫#暪&!勹ꇶ놽攺J堬镙~軌C'꾖䣹㮅岃ᙴ鵣", + 4.317829988264744E15, + 6.013585322002147E-20, + false, + true, + null, + null, + -3.084633632357326E-20, + false, + null, + { + "\"짫愔昻 X\"藣j\"\"먁ཅѻ㘤㬯0晲DU꟒㸃d벀윒l䦾c੻*3": null, + "谈Wm陧阦咟ฯ歖擓N喴㋐銭rCCnVࢥ^♼Ⅾ젲씗刊S༝+_t赔\\b䚍뉨ꬫ6펛cL䊘᜼<\/澤pF懽&H": [ + null, + { + "W\"HDUuΌ퀟M'P4࿰H똆ⰱﮯ<\/凐蘲\"C鴫ﭒж}ꭩ쥾t5yd诪ﮡ퍉ⴰ@?氐醳rj4I6Qt": 6.9090159359219891E17, + "絛ﳛ⺂": {"諰P㗮聦`ZQ?ꫦh*റcb⧱}埌茥h{棩렛툽o3钛5鮁l7Q榛6_g)ὄ\u0013kj뤬^爖eO4Ⱈ槞鉨ͺ订%qX0T썗嫷$?\\\"봅늆'%": [ + -2.348150870600346E-19, + [[ + true, + -6619392047819511778, + false, + [[ + -1.2929189982356161E-20, + 1.7417192219309838E-19, + {"?嵲2࿐2\u0001啑㷳c縯": [ + null, + [ + false, + true, + 2578060295690793218, + { + "?\"殃呎#㑑F": true, + "}F炊_殛oU헢兔Ꝉ,赭9703.B数gTz3⏬": { + "5&t3,햓Mݸᵣ㴵;꣫䩍↳#@뫷䠅+W-ࣇzᓃ鿕ಔ梭?T䮑ꥬ旴]u뫵막bB讍:왳둛lEh=숾鱠p咐$짏#?g⹷ᗊv㷵.斈u頻\u0018-G.": "뽙m-ouࣤ஫牷\"`Ksꕞ筼3HlȨvC堈\"I]㖡玎r먞#'W賜鴇k'c룼髋䆿飉㗆xg巤9;芔cጐ/ax䊨♢큓r吓㸫೼䢗da᩾\"]屣`", + ":M딪<䢥喠\u0013㖅x9蕐㑂XO]f*Q呰瞊吭VP@9,㨣 D\\穎vˤƩs㜂-曱唅L걬/롬j㈹EB8g<\/섩o渀\"u0y&룣": ">氍緩L/䕑돯Ꟙ蕞^aB뒣+0jK⪄瑨痜LXK^힦1qK{淚t츔X:Vm{2r獁B뾄H첚7氥?쉟䨗ꠂv팳圎踁齀\\", + "D彤5㢷Gꪻ[lㄆ@὜⓰絳[ଃ獽쮹☒[*0ꑚ㜳": 9022717159376231865, + "ҖaV銣tW+$魿\u20c3亜~뫡ᙰ禿쨽㏡fṼzE/h": "5臐㋇Ჯ쮺? 昨탰Wム밎#'\"崲钅U?幫뺀⍾@4kh>騧\\0ҾEV=爐͌U捀%ꉼ 㮋<{j]{R>:gԩL\u001c瀈锌ﯲﳡꚒ'⫿E4暍㌗뵉X\"H᝜", + "ᱚגּ;s醒}犍SἿ㦣&{T$jkB\\\tḮ앾䤹o<避(tW": "vb⯽䴪䮢@|)", + "⥒퐁껉%惀뗌+녣迺顀q條g⚯i⤭룐M琹j̈́⽜A": -8385214638503106917, + "逨ꊶZ<\/W⫟솪㎮ᘇb?ꠔi\"H㧺x෷韒Xꫨฟ|]窽\u001a熑}Agn?Mᶖa9韲4$3Ỵ^=쏍煤ፐ돷2䣃%鷠/eQ9頸쥎", + 2398360204813891033, + false, + 3.2658897259932633E-19, + null, + "?ꚃ8Nn㞷幵d䲳䱲뀙ꪛQ瑓鎴]䩋-鰾捡䳡??掊", + false, + -1309779089385483661, + "ᦲxu_/yecR.6芏.ᜇ過 ~", + -5658779764160586501, + "쒌:曠=l썜䢜wk#s蕚\"互㮉m䉤~0듐䋙#G;h숄옥顇෤勹(C7㢅雚㐯L⠅VV簅<", + null, + -4.664877097240962E18, + -4.1931322262828017E18, + { + ",": { + "v㮟麑䄠뤵g{M띮.\u001bzt뢜뵡0Ǥ龍떟Ᾰ怷ϓRT@Lꀌ樂U㏠⾕e扉|bJg(뵒㠶唺~ꂿ(땉x⻫싉쁊;%0鎻V(o\f,N鏊%nk郼螺": -1.73631993428376141E18, + "쟧摑繮Q@Rᕾ㭚㾣4隅待㓎3蒟": [ + 4971487283312058201, + 8973067552274458613, + { + "`a揙ᣗ\u0015iBo¸": 4.3236479112537999E18, + "HW&퉡ぁ圍Y?瑡Qy훍q!帰敏s舠㫸zꚗaS歲v`G株巷Jp6킼 (귶鍔⾏⡈>M汐㞍ቴ꙲dv@i㳓ᇆ?黍": [ + null, + 4997607199327183467, + "E㻎蠫ᐾ高䙟蘬洼旾﫠텛㇛?'M$㣒蔸=A_亀绉앭rN帮", + null, + [{ + "Eᑞ)8餧A5u&㗾q?": [ + -1.969987519306507E-19, + null, + [ + 3.42437673373841E-20, + true, + "e걷M墁\"割P␛퍧厀R䱜3ﻴO퓫r﹉⹊", + [ + -8164221302779285367, + [ + true, + null, + "爘y^-?蘞Ⲽꪓa␅ꍨ}I", + 1.4645984996724427E-19, + [{ + "tY좗⧑mrzﺝ㿥ⴖ᥷j諅\u0000q賋譁Ꞅ⮱S\nࡣB/큃굪3Zɑ复o<\/;롋": null, + "彟h浠_|V4䦭Dᙣ♞u쿻=삮㍦\u001e哀鬌": [{"6횣楠,qʎꗇ鎆빙]㱭R굋鈌%栲j分僅ペ䇰w폦p蛃N溈ꡐꏀ?@(GI뉬$ﮄ9誁ꓚ2e甸ڋ[䁺,\u0011\u001cࢃ=\\+衪䷨ᯕ鬸K": [[ + "ㅩ拏鈩勥\u000etgWVXs陂規p狵w퓼{뮵_i\u0002ퟑႢ⬐d6鋫F~챿搟\u0096䚼1ۼ칥0꣯儏=鋷牋ⅈꍞ龐", + -7283717290969427831, + true, + [ + 4911644391234541055, + { + "I鈒첽P릜朸W徨觘-Hᎄ퐟⓺>8kr1{겵䍃〛ᬡ̨O귑o䝕'쿡鉕p5": "fv粖RN瞖蛐a?q꤄\u001d⸥}'ꣴ犿ꦼ?뤋?鵆쥴덋䡫s矷̄?ඣ/;괱絢oWfV<\/\u202cC,㖦0䑾%n賹g&T;|lj_欂N4w", + "짨䠗;䌕u i+r๏0": [{"9䥁\\఩8\"馇z䇔<\/ႡY3e狚쐡\"ุ6ﰆZ遖c\"Ll:ꮾ疣<\/᭙O◌납୕湞9⡳Und㫜\u0018^4pj1;䧐儂䗷ୗ>@e톬": { + "a⑂F鋻Q螰'<퇽Q贝瀧{ᘪ,cP&~䮃Z?gI彃": [ + -1.69158726118025933E18, + [ + "궂z簽㔛㮨瘥⤜䛖Gℤ逆Y⪾j08Sn昞ꘔ캻禀鴚P謦b{ꓮmN靐Mᥙ5\"睏2냑I\u0011.L&=?6ᄠ뻷X鸌t刑\"#z)o꫚n쳟줋", + null, + 7517598198523963704, + "ኑQp襟`uᩄr方]*F48ꔵn俺ሙ9뇒", + null, + null, + 6645782462773449868, + 1219168146640438184, + null, + { + ")ယ넌竀Sd䰾zq⫣⏌ʥ\u0010ΐ' |磪&p牢蔑mV蘸૰짬꺵;K": [ + -7.539062290108008E-20, + [ + true, + false, + null, + true, + 6574577753576444630, + [[ + 1.2760162530699766E-19, + [ + null, + [ + "顊\\憎zXB,", + [{ + "㇆{CVC9-MN㜋ઘR눽#{h@ퟨ!鼚׼XOvXS\u0017ᝣ=cS+梽៲綆16s덽휐y屬?ᇳG2ᴭ\u00054쫖y룇nKcW̭炦s/鰘ᬽ?J|퓀髣n勌\u0010홠P>j": false, + "箴": [ + false, + "鍞j\"ꮾ*엇칬瘫xṬ⭽쩁䃳\"-⋵?ᦽ댎Ĝ": true, + "Pg帯佃籛n㔠⭹࠳뷏≻࿟3㞱!-쒾!}쭪䃕!籿n涻J5ਲ਼yvy;Rኂ%ᔡጀ裃;M⣼)쵂쑈": 1.80447711803435366E18, + "ꈑC⡂ᑆ㤉壂뎃Xub<\/쀆༈憓ق쨐ק\\": [ + 7706977185172797197, + {"": {"K╥踮砆NWࡆFy韣7ä밥{|紒︧䃀榫rᩛꦡTSy잺iH8}ퟴ,M?Ʂ勺ᴹ@T@~꾂=I㙕뾰_涀쑜嫴曣8IY?ҿo줫fऒ}\\S\"ᦨ뵼#nDX": { + "♘k6?଱癫d68?㽚乳䬳-V顷\u0005蝕?\u0018䞊V{邾zじl]雏k臤~ൖH뒐iꢥ]g?.G碄懺䔛pR$䅒X觨l봜A刊8R梒',}u邩퉕?;91Ea䈈믁G⊶芔h袪&廣㺄j;㡏綽\u001bN頸쳘橆": -2272208444812560733, + "拑Wﵚj鵼駳Oࣿ)#㾅顂N傓纝y僱栜'Bꐍ-!KF*ꭇK¦?䈴^:啤wG逭w᧯": "xᣱmYe1ۏ@霄F$ě꧘푫O䤕퀐Pq52憬ꀜ兴㑗ᡚ?L鷝ퟐ뭐zJꑙ}╆ᅨJB]\"袌㺲u8䯆f", + "꿽၅㔂긱Ǧ?SI": -1669030251960539193, + "쇝ɨ`!葎>瞺瘡驷錶❤ﻮ酜=": -6961311505642101651, + "?f7♄꫄Jᡔ훮e읇퍾፣䭴KhखT;Qty}O\\|뫁IῒNe(5惁ꥶㆷY9ﮡ\\ oy⭖-䆩婁m#x봉>Y鈕E疣s驇↙ᙰm<": {"퉻:dꂁ&efᅫ쫢[\"돈늖꺙|Ô剐1͖-K:ʚ᭕/;쏖㷛]I痐职4gZ4⍜kเꛘZ⥺\\Bʫᇩ鄨魢弞&幟ᓮ2̊盜", + -9006004849098116748, + -3118404930403695681, + { + "_彃Y艘-\"Xx㤩㳷瑃?%2䐡鵛o귵옔夘v*탋职&㳈챗|O钧": [ + false, + "daꧺdᗹ羞쯧H㍤鄳頳<型孒ン냆㹀f4㹰\u000f|C*ሟ鰠(O<ꨭ峹ipຠ*y೧4VQ蔔hV淬{?ᵌEfrI_", + "j;ꗣ밷邍副]ᗓ", + -4299029053086432759, + -5610837526958786727, + [ + null, + [ + -1.3958390678662759E-19, + { + "lh좈T_믝Y\"伨\u001cꔌG爔겕ꫳ晚踍⿻읐T䯎]~e#฽燇\"5hٔ嶰`泯r;ᗜ쮪Q):/t筑,榄&5懶뎫狝(": [{ + "2ፁⓛ]r3C攟וּ9賵s⛔6'ஂ|\"ⵈ鶆䐹禝3\"痰ࢤ霏䵩옆䌀?栕r7O簂Isd?K᫜`^讶}z8?z얰T:X倫⨎ꑹ": -6731128077618251511, + "|︦僰~m漿햭\\Y1'Vvخ굇ቍ챢c趖": [null] + }], + "虌魿閆5⛔煊뎰㞤ᗴꥰF䮥蘦䂪樳-K᝷-(^\u20dd_": 2.11318679791770592E17 + } + ] + ] + ]}, + "묗E䀳㧯᳀逞GMc\b墹㓄끖Ơ&U??펌鑍 媋k))ᄊ": null, + "묥7콽벼諌J_DɯﮪM殴䣏,煚ྼ`Y:씧<\/⩫%yf䦀!1Ჶk춎Q米W∠WC跉鬽*ᛱi㴕L꘻ꀏ쓪\"_g鿄'#t⽙?,Wg㥖|D鑆e⥏쪸僬h鯔咼ඡ;4TK聎졠嫞" + } + ] + ] + } + ] + ] + ]}} + } + ]} + }, + "뿋뀾淣截䔲踀&XJ펖꙯^Xb訅ꫥgᬐ>棟S\"혧騾밫겁7-": "擹8C憎W\"쵮yR뢩浗絆䠣簿9䏈引Wcy䤶孖ꯥ;퐌]輩䍐3@{叝 뽸0ᡈ쵡Ⲇ\u001dL匁꧐2F~ݕ㪂@W^靽L襒ᦘ~沦zZ棸!꒲栬R" + } + ] + ], + "Z:덃൛5Iz찇䅄駠㭧蓡K1": "e8᧤좱U%?ⵇ䯿鿝\u0013縮R∱骒EO\u000fg?幤@֗퉙vU`", + "䐃쪈埽້=Ij,쭗쓇చ": false + }]}} + ] + } + ]} + } + ] + ] + ], + "咰긖VM]᝼6䓑쇎琺etDҌ?㞏ꩄ퇫밉gj8蠃\"⩐5䛹1ࣚ㵪": "ക蹊?⎲⧘⾚̀I#\"䈈⦞돷`wo窭戕෱휾䃼)앷嵃꾞稧,Ⴆ윧9S?೗EMk3Მ3+e{⹔Te驨7䵒?타Ulg悳o43" + } + ], + "zQᤚ纂땺6#ٽ﹧v￿#ࠫ휊冟蹧텈ꃊʆ?&a䥯De潝|쿓pt瓞㭻啹^盚2Ꝋf醪,얏T窧\\Di䕎谄nn父ꋊE": -2914269627845628872, + "䉩跐|㨻ᷢ㝉B{蓧瞸`I!℄욃힕#ೲᙾ竛ᔺCjk췒늕貭词\u0017署?W딚%(pꍁ⤼띳^=on뺲l䆼bzrﳨ[&j狸䠠=ᜑꦦ\u2061յnj=牲攑)M\\龏": false, + "뎕y絬᫡⥮Ϙᯑ㌔/NF*˓.,QEzvK!Iwz?|쥾\"ꩻL꼗Bꔧ賴緜s뉣隤茛>ロ?(?^`>冺飒=噸泥⺭Ᲊ婓鎔븜z^坷裮êⓅ໗jM7ﶕ找\\O": 1.376745434746303E-19 + }, + "䐛r滖w㏤,|Nዜ": false + } + ]], + "@꿙?薕尬 gd晆(띄5躕ﻫS蔺4)떒錸瓍?~": 1665108992286702624, + "w믍nᏠ=`঺ᅥC>'從됐槷䤝眷螄㎻揰扰XᅧC贽uჍ낟jKD03T!lDV쀉Ӊy뢖,袛!终캨G?鉮Q)⑗1쾅庅O4ꁉH7?d\u0010蠈줘월ސ粯Q!낇껉6텝|{": null, + "~˷jg쿤촖쉯y": -5.5527605669177098E18, + "펅Wᶺzꐆと푭e?4j仪열[D<鈑皶婆䵽ehS?袪;HꍨM뗎ば[(嗏M3q퍟g4y╸鰧茀[Bi盤~﫝唎鋆彺⦊q?B4쉓癚O洙킋툈䶯_?ퟲ": null + } + ] + ]] + ]], + "꟱Ԕ㍤7曁聯ಃ錐V䷰?v㪃૦~K\"$%请|ꇹn\"k䫛㏨鲨\u2023䄢\u0004[︊VJ?䶟ាꮈ䗱=깘U빩": -4863152493797013264 + } + ]}]} + ] + }}} + ], + "쏷쐲۹퉃~aE唙a챑,9㮹gLHd'䔏|킗㍞䎥&KZYT맵7䥺Nⱳ同莞鿧w\\༌疣n/+ꎥU\"封랾○ퟙAJᭌ?9䛝$?驔9讐짘魡T֯c藳`虉C읇쐦T" + } + ], + "谶개gTR￐>ၵ͚dt晑䉇陏滺}9㉸P漄": -3350307268584339381 + }] + ] + ] + ]] + ] + ], + "0y꟭馋X뱔瑇:䌚￐廿jg-懲鸭䷭垤㒬茭u賚찶ಽ+\\mT땱\u20821殑㐄J쩩䭛ꬿNS潔*d\\X,壠뒦e殟%LxG9:摸": 3737064585881894882, + "풵O^-⧧ⅶvѪ8廸鉵㈉ר↝Q㿴뺟EႳvNM:磇>w/៻唎뷭୥!냹D䯙i뵱貁C#⼉NH6`柴ʗ#\\!2䂗Ⱨf?諳.P덈-返I꘶6?8ꐘ": -8934657287877777844, + "溎-蘍寃i诖ര\"汵\"\ftl,?d⼡쾪⺋h匱[,෩I8MҧF{k瓿PA'橸ꩯ綷퉲翓": null + } + ] + ], + "ោ係؁<元": 1.7926963090826924E-18 + }}] + } + ] + ]]}] + }] + ] + ] + ] + ], + "ጩV<\"ڸsOᤘ": 2.0527167903723048E-19 + }] + ]} + ] + ]], + "∳㙰3젴p᧗䱙?`yZA8Ez0,^ᙛ4_0븢\u001ft:~䎼s.bb룦明yNP8弆C偯;⪾짍'蕴뮛": -6976654157771105701, + "큵ꦀ\\㇑:nv+뒤燻䀪ﴣ﷍9ᚈ኷K㚊誦撪䚛,ꮪxሲ쳊\u0005HSf?asg昱dqꬌVꙇ㼺'k*'㈈": -5.937042203633044E-20 + } + ] + }], + "?}\u20e0],s嶳菋@#2u쒴sQS䩗=ꥮ;烌,|ꘔ䘆": "ᅩ영N璠kZ먕眻?2ቲ芋眑D륟渂⸑ﴃIRE]啗`K'" + }}, + "쨀jmV賂ﰊ姐䂦玞㬙ᏪM᪟Վ씜~`uOn*ॠ8\u000ef6??\\@/?9見d筜ﳋB|S䝬葫㽁o": true + }, + "즛ꄤ酳艚␂㺘봿㎨iG৕ࡿ?1\"䘓您\u001fSኝ⺿溏zៀ뻤B\u0019?윐a䳵᭱䉺膷d:<\/": 3935553551038864272 + } + ] + ]} + ]] + ]] + ]} + } + ] + } + ]]}}, + "᥺3h↛!ꋰy\"攜(ெl䪕oUkc1A㘞ᡲ촾ᣫ<\/䒌E㛝潨i{v?W౾H\\RჅpz蝬R脾;v:碽✘↯삞鷱o㸧瑠jcmK7㶧뾥찲n": true, + "ⶸ?x䊺⬝-䰅≁!e쩆2ꎿ准G踌XXᩯ1߁}0?.헀Z馟;稄\baDꟹ{-寪⚈ꉷ鮸_L7ƽᾚ<\u001bጨA䧆송뇵⨔\\礍뗔d设룱㶉cq{HyぱR㥽吢ſtp": -7985372423148569301, + "緫#콮IB6<\/=5Eh礹\t8럭@饹韠r㰛斣$甝LV췐a갵'请o0g:^": "䔨(.", + "띳℡圤pン௄ĝ倧訜B쁟G䙔\"Sb⓮;$$▏S1J뢙SF|赡g*\"Vu䲌y": "䪈&틐),\\kT鬜1풥;뷴'Zေ䩹@J鞽NぼM?坥eWb6榀ƩZڮ淽⺞삳煳xჿ絯8eⶍ羷V}ჿ쎱䄫R뱃9Z>'\u20f1ⓕ䏜齮" + } + ] + ]]] + }} + } + ] + ]}, + "펮b.h粔폯2npX詫g錰鷇㇒<쐙S値bBi@?镬矉`剔}c2壧ଭfhY깨R()痩⺃a\\⍔?M&ﯟ<劜꺄멊ᄟA\"_=": null + }, + "~潹Rqn榢㆓aR鬨侅?䜑亡V_翅㭔(䓷w劸ၳDp䀅<\/ﰎ鶊m䵱팱긽ꆘ긓准D3掱;o:_ќ)껚콥8곤d矦8nP倥ꃸI": null, + "뾎/Q㣩㫸벯➡㠦◕挮a鶧⋓偼\u00001뱓fm覞n?㛅\"": 2.8515592202045408E17 + }], + ",": -5426918750465854828, + "2櫫@0柡g䢻/gꆑ6演&D稒肩Y?艘/놘p{f투`飷ᒉ챻돎<늛䘍ﴡ줰쫄": false, + "8(鸑嵀⵹ퟡ<9㣎Tߗ┘d슒ل蘯&㠦뮮eࠍk砝g 엻": false, + "d-\u208b?0ﳮ嵙'(J`蔿d^踅⤔榥\\J⵲v7": 6.8002426206715341E17, + "ཎ耰큓ꐕ㱷\u0013y=詽I\"盈xm{0쾽倻䉚ષso#鰑/8㸴짯%ꀄ떸b츟*\\鲷礬ZQ兩?np㋄椂榨kc᡹醅3": false, + "싊j20": false + }]] + ]], + "俛\u0017n緽Tu뫉蜍鼟烬.ꭠIⰓ\"Ἀ᜾uC쎆J@古%ꛍm뻨ᾀ画蛐휃T:錖㑸ዚ9죡$": true + } + ] + ], + "㍵⇘ꦖ辈s}㱮慀밒s`\"㞟j:`i픻Z섫^諎0Ok{켿歁෣胰a2﨤[탳뚬쎼嫭뉮m": 409440660915023105, + "w墄#*ᢄ峠밮jLa`ㆪ꺊漓Lで끎!Agk'ꁛ뢃㯐岬D#㒦": false, + "ଦPGI䕺L몥罭ꃑ궩﮶#⮈ᢓӢ䚬p7웼臧%~S菠␌힀6&t䳙y㪘냏\\*;鉏ᅧ鿵'嗕pa\"oL쇿꬈Cg": "㶽1灸D⟸䴅ᆤ뉎﷛渤csx 䝔цꬃ锚捬?ຽ+x~꘩uI࡞\u0007栲5呚ẓem?袝\")=㥴䨃pac!/揎Y", + "ᷱo\\||뎂몷r篙|#X䦜I#딌媸픕叞RD斳X4t⯩夬=[뭲r=绥jh뷱츝⪘%]⚋܈㖴スH텹m(WO曝劉0~K3c柢Ր㏉着逳~": false, + "煽_qb[첑\\륌wE❽ZtCNﭝ+餌ᕜOꛭ": "{ﳾ쉌&s惧ᭁⵆ3䢫;䨞팑꒪흘褀࢖Q䠿V5뭀䎂澻%받u5텸oA⮥U㎦;B䳌wz䕙$ឿ\\௅婺돵⪾퐆\\`Kyौꋟ._\u0006L챯l뇠Hi䧈偒5", + "艊佁ࣃ롇䱠爬!*;⨣捎慓q靓|儑ᨋL+迥=6㒺딉6弄3辅J-㕎뛄듘SG㆛(\noAzQꝱ䰩X*ぢO퀌%펠낌mo틮a^<\/F&_눊ᾉ㨦ы4\"8H": 2974648459619059400, + "鬙@뎣䫳ၮ끡?){y?5K;TA*k溱䫜J汃ꂯ싔썍\u001dA}룖(<\/^,": false, + "몏@QꋦFꊩᒐ뎶lXl垨4^郣|ꮇ;䝴ᝓ}쵲z珖": null + } + ]]]], + ":_=닧弗D䙋暨鏛. 㱻붘䂍J儒&ZK/녩䪜r囁⽯D喠죥7⹌䪥c\u001a\u2076￞妈朹oLk菮F౟覛쐧㮏7T;}蛙2{9\"崓bB<\/⡷룀;즮鿹)丒툃୤뷠5W⊢嶜(fb뭳갣": "E{响1WM" + }}, + "䘨tjJ驳豨?y輊M*᳑梵瞻઻ofQG瑮e": 2.222802939724948E-19, + "䮴=❑➶T෋w䞜\"垦ꃼUt\u001dx;B$뵣䙶E↌艣ᡥ!᧟;䱀[䔯k쬃`੍8饙른熏'2_'袻tGf蒭J땟as꯳╖&啒zWࡇᒫYSᏬ\u0014ℑ첥鈤|cG~Pᓮ\">\"": "ႆl\f7V儊㦬nHꄬꨧC{쐢~C⮃⛓嶦vꄎ1w鰠嘩뿠魄&\"_qMⵖ釔녮ꝇ 㝚{糍J哋 cv?-jkﻯྌ鹑L舟r", + "龧葆yB✱H盋夔ﶉ?n*0(": "ꧣኆ㢓氥qZZ酒ຜ)鮢樛)X䣆gTSґG텞k.J圬疝롫쯭z L:\\ྤ@w炋塜쿖ᾳy뢀䶃뱝N䥨㚔勇겁#p", + "도畎Q娡\"@S/뼋:䵏!P衅촚fVHQs✜ᐫi㻑殡B䜇%믚k*U#濨낄~": "ꍟዕ쳸ꍈ敋&l妏\u0005憡멗瘌uPgᅪm<\/To쯬锩h뒓k" + } + ] + }], + "墥홞r绚<\/⸹ⰃB}<躅\\Y;๑@䔸>韫䜲뱀X뗩鿥쩗SI%ﴞ㳕䛇?<\/\u00018x\\&侂9鋙a[LR㋭W胕)⡿8㞙0JF,}?허d1cDMᐃ␛鄝ⱕ%X)!XQ": "ⳍꗳ=橇a;3t⦾꼑仈ူaᚯ⯋ꕃAs鴷N⍕_䎃ꙎAz\u0016䯷\\<࿫>8q{}キ?ᣰ}'0ᴕ펓B┦lF#趤厃T?㕊#撹圂䆲" + }, + "܋닐龫論c웑": false, + "ㇿ/q\"6-co髨휝C큦#\u001b4~?3䐹E삇<<": 7.600917488140322E-20, + "䁝E6?㣖ꃁ间t祗*鑠{ḣV(浾h逇큞=W?ૉ?nꇽ8ꅉຉj으쮺@Ꚅ㰤u]Oyr": "v≁᫸_*όAඤԆl)ۓᦇQ}폠z༏q滚", + "ソ᥊/넺I": true + }]] + ] + ] + ] + ]] + }, + "䭑Ik攑\u0002QV烄:芩.麑㟴㘨≕": true, + "坄꿕C쇻풉~崍%碼\\8\"䬦꣙": null, + "欌L圬䅘Y8c(♺2?ON}o椳s宥2䉀eJ%闹r冁O^K諭%凞⺉⡻,掜?$ꥉ?略焕찳㯊艼誜4?\"﯎<゛XፈINT:詓 +": -1.0750456770694562E-19, + "獒àc뜭싼ﺳ뎤K`]p隨LtE": null, + "甙8䵊神EIꩤ鐯ᢀ,ﵮU䝑u疒ử驺䚿≚ഋ梶秓F`覤譐#짾蔀묊4<媍쬦靪_Yzgcࡶ4k紥`kc[Lﮗ簐*I瀑[⾰L殽鑥_mGȠ<\/|囹灠g桰iri": true, + "챓ꖙꟻ좝菇ou,嗠0\\jK핻뜠qwQ?ഩ㼕3Y彦b\u009bJ榶N棨f?됦鏖綃6鳵M[OE봨u햏.Ꮁ癜蟳뽲ꩌ뻾rM豈R嗀羫 uDꎚ%": null + }, + "V傜2<": 7175127699521359521 + }], + "铫aG切<\/\"ী⊆e<^g࢛)D顝nאַ饼\u008c猪繩嵿ﱚCꡬ㻊g엺A엦\u000f暿_f꿤볝㦕桦`蒦䎔j甬%岝rj 糏": "䚢偎눴Au<4箞7礦Iﱔ坠eȧ䪸u䵁p|逹$嗫쨘ꖾ﷐!胠z寓팢^㨔|u8Nሇe텔ꅦ抷]،鹎㳁#༔繁 ", + "낂乕ꃻ볨ϱ-ꇋ㖍fs⿫)zꜦ/K?솞♞ꑌ宭hJ᤭瑥Fu": false, + "쟰ぜ魛G\u0003u?`㾕ℾ㣭5螠烶這趩ꖢ:@咕ꐶx뒘느m䰨b痃렐0鳊喵熬딃$摉_~7*ⱦ녯1錾GKhJ惎秴6'H妈Tᧅ窹㺒疄矤铟wላ": null, + "쯆q4!3錕㲏ⵆ㇛꘷Z瑩뭆\\◪NH\u001d\\㽰U~㯶<\"쑣낞3ᵤ'峉eꢬ;鬹o꣒木X*長PXᘱu\"䠹n惞": null, + "ᅸ祊\"&ꥴCjࢼ﴿?䡉`U效5殼㮞V昽ꏪ#ﺸ\\&t6x꠹盥꣰a[\u001aꪍSpe鎿蠹": -1.1564713893659811E-19 + } + ]] + ] + ] + ], + "羵䥳H,6ⱎ겾|@t\"#햊1|稃 섭)띜=뻔ꡜ???櫎~*ῡ꫌/繣ﻠq": null + } + ]} + ]}, + "츤": false + }}, + "s": 3.7339341963399598E18 + } + ], + "N,I?1+㢓|ࣱ嶃쩥V2\u0012(4EE虪朶$|w颇v步": "~읢~_,Mzr㐫YB溓E淚\"ⅹ䈔ᏺ抙 b,nt5V㐒J檶ꏨ⻔?", + "Q껑ꡡ}$넎qH煔惍/ez^!ẳF댙䝌馻剁8": "梲;yt钰$i冄}AL%a j뜐奷걳뚾d꿽*ሬuDY3?뮟鼯뮟w㍪틱V", + "o{Q/K O胟㍏zUdꀐm&⨺J舕⾏魸訟㌥[T籨櫉唐킝 aṭ뱫촙莛>碶覆⧬짙쭰ׯdAiH໥벤퐥_恸[ 0e:죃TC弼荎뵁DA:w唵ꣁ": null, + "὏樎䵮軧|?౗aWH쩃1 ꅭsu": null + } + ] + }, + "勂\\&m鰈J釮=Ⲽ鳋+䂡郑": null, + "殣b綊倶5㥗惢⳷萢ᑀ䬄镧M^ﱴ3⣢翣n櫻1㨵}ኯ뗙顖Z.Q➷ꮨ뗇\u0004": "ꔙ䁼>n^[GीA䨟AM琢ᒊS쨲w?d㶣젊嘶纝麓+愣a%気ྞSc됓ᔘ:8bM7Xd8㶑臌]Ꙥ0ꐭ쒙䫣挵C薽Dfⵃ떼᷸", + "?紡.셪_෨j\u0013Ox┠$Xᶨ-ᅇo薹-}軫;y毝㪜K㣁?.EV쮱4둽⛻䤜'2盡\u001f60(|e쐰㼎ᦀ㒧-$l@ﻑ坳\u0003䭱响巗WFo5c㧆T턁Y맸♤(": -2.50917882560589088E17 + }} + ], + "侸\\릩.᳠뎠狣살cs项䭩畳H1s瀉븇19?.w骴崖㤊h痠볭㞳㞳䁮Ql怠㦵": "@䟴-=7f", + "鹟1x௢+d ;vi䭴FSDS\u0004hꎹ㚍?⒍⦏ў6u,扩@됷Su)Pag휛TᒗV痩!瞏釀ꖞ蘥&ೞ蘐ꭰꞇᝎ": "ah懱Ժ&\u20f7䵅♎඀䞧鿪굛ౕ湚粎蚵ᯋ幌YOE)५襦㊝Y*^\"R+ඈ咷蝶9ꥂ榨艦멎헦閝돶v좛咊E)K㓷ྭr", + "搆q쮦4綱켙셁.f4<\/g<籽늷?#蚴픘:fF\u00051㹉뀭.ᰖ풎f֦Hv蔎㧤.!䭽=鞽]음H:?\"-4": 8.740133984938656E-20 + }]} + } + ], + "tVKn딩꘥⊾蹓᤹{\u0003lR꼽ᄲQFᅏ傅ﱋ猢⤊ᔁ,E㓒秤nTතv`♛I\u0000]꫔ṞD\"麵c踝杰X&濿또꣹깳౥葂鿎\\aꡨ?": 3900062609292104525 + } + ], + "ਉ샒⊩Lu@S䧰^g": -1.1487677090371648E18, + "⎢k⑊꬗yᏫ7^err糎Dt\u000bJ礯확ㆍ沑サꋽe赔㝢^J\u0004笲㿋idra剰-᪉C錇/Ĝ䂾ညS지?~콮gR敉⬹'䧭": 1901472137232418266, + "灗k䶥:?촽贍쓉꓈㒸g獘[뵎\\胕?\u0014_榙p.j稶,$`糉妋0>Fᡰly㘽$?": "]ꙛO赎&#㠃돱剳\"<◆>0誉齐_|z|裵씪>ᐌ㼍\"Z[琕}O?G뚇諦cs⠜撺5cu痑U圲\u001c?鴴計l춥/╓哼䄗茏ꮅ뫈댽A돌롖뤫V窗讬sHd&\nOi;_u" + } + ], + "Uﺗ\\Y\\梷䄬~\u0002": null, + "k\"Y磓ᗔ휎@U冈<\/w컑)[": false, + "曏J蝷⌻덦\u001f㙳s꥓⍟邫P늮쥄c∬ྡྷ舆렮칤Z趣5콡넛A쳨\\뀙骫(棻.*&輛LiIfi{@EA婳KᬰTXT": -4.3088230431977587E17 + }]} + ] + ], + "곃㲧<\/dఓꂟs其ࡧ&N葶=?c㠤Ჴ'횠숄臼#\u001a~": false + } + ] + ]}] + }] + }} + ], + "2f`⽰E쵟>J笂裭!〛觬囀ۺ쟰#桊l鹛ⲋ|RA_Vx፭gE됓h﵀mfỐ|?juTU档[d⢼⺻p濚7E峿": 5613688852456817133 + }, + "濘끶g忮7㏵殬W팕Q曁 뫰)惃廊5%-蹚zYZ樭ﴷQ锘쯤崫gg": true, + "絥ᇑ⦏쒓븣爚H.㗊߄o蘵貆ꂚ(쎔O᥉ﮓ]姨Wꁓ!RMA|o퉢THx轮7M껁U즨'i뾘舯o": "跥f꜃?" + }} + ], + "鷰鹮K-9k;ﰰ?_ݦѷ-ꅣ䩨Zꥱ\"mꠟ屎/콑Y╘2&鸞脇㏢ꀇ࠺ⰼ拾喭틮L꽩bt俸墶 [l/웄\"꾦\u20d3iও-&+\u000fQ+໱뵞": -1.296494662286671E-19 + }, + "HX੹/⨇୕붷Uﮘ旧\\쾜͔3l鄈磣糂̖䟎Eᐳw橖b῀_딕hu葰窳闹вU颵|染H죶.fP䗮:j䫢\\b뎖i燕ꜚG⮠W-≚뉗l趕": "ଊ칭Oa᡺$IV㷧L\u0019脴셀붿餲햪$迳向쐯켂PqfT\" ?I屉鴼쿕@硙z^鏕㊵M}㚛T젣쓌-W⩐-g%⺵<뮱~빅╴瑿浂脬\u0005왦燲4Ⴭb|D堧 <\/oEQh", + "䘶#㥘੐캔f巋ἡAJ䢚쭈ࣨ뫒*mᇊK,ࣺAꑱ\u000bR<\/A\"1a6鵌㯀bh곿w(\"$ꘁ*rಐ趣.d࿩k/抶면䒎9W⊃9": "漩b挋Sw藎\u0000", + "畀e㨼mK꙼HglKb,\"'䤜": null + }]}] + ] + ] + }] + ]} + ] + ]} + ], + "歙>駿ꣂ숰Q`J΋方樛(d鱾뼣(뫖턭\u20f9lচ9歌8o]8윶l얶?镖G摄탗6폋폵+g:䱫홊<멀뀿/س|ꭺs걐跶稚W々c㫣⎖": "㣮蔊깚Cꓔ舊|XRf遻㆚︆'쾉췝\\&言", + "殭\"cށɨꝙ䞘:嬮e潽Y펪㳅/\"O@ࠗ겴]췖YǞ(t>R\"N?梳LD恭=n氯T豰2R諸#N}*灧4}㶊G䍣b얚": null, + "襞<\/啧 B|싞W瓇)6簭鼡艆lN쩝`|펭佡\\間邝[z릶&쭟愱ꅅ\\T᰽1鯯偐栈4̸s윜R7⒝/똽?치X": "⏊躖Cﱰ2Qẫ脐&இ?%냝悊", + ",鰧偵셣싹xᎹ힨᯳EṬH㹖9": -4604276727380542356 + } + } + ]]]], + "웺㚑xs}q䭵䪠馯8?LB犯zK'os䚛HZ\"L?셎s^㿧㴘Cv2": null + }] + ] + ] + ], + "Kd2Kv+|z": 7367845130646124107, + "ᦂⶨ?ᝢ 祂些ഷ牢㋇操\"腭䙾㖪\\(y4cE뽺ㆷ쫺ᔖ%zfۻ$ў1柦,㶢9r漢": -3.133230960444846E-20, + "琘M焀q%㢟f鸯O⣏蓑맕鯊$O噷|)z褫^㢦⠮ꚯ꫞`毕1qꢚ{ĭ䎀বώT\"뱘3G൴?^^of": null + } + ], + "a8V᯺?:ﺃ/8ꉿBq|9啓댚;*i2": null, + "cpT瀇H珰Ừpೃi鎪Rr␣숬-鹸ҩ䠚z脚цGoN8入y%趌I┽2ឪЀiJNcN)槣/▟6S숆牟\"箑X僛G殱娇葱T%杻:J諹昰qV쨰": 8331037591040855245 + }], + "G5ᩜ䄗巢껳": true + } + }, + "Ồ巢ゕ@_譙A`碫鄐㡥砄㠓(^K": "?܃B혢▦@犑ὺD~T⧁|醁;o=J牌9냚⢽㨘{4觍蚔9#$∺\u0016p囅\\3Xk阖⪚\"UzA穕롬✎➁㭒춺C㣌ဉ\"2瓑员ᅽꝶ뫍}꽚ꞇ鶂舟彺]ꍽJC蝧銉", + "␆Ě膝\"b-퉐ACR言J謈53~V튥x䜢?ꃽɄY뮩ꚜ": "K/↾e萃}]Bs⾿q룅鷦-膋?m+死^魊镲6", + "粡霦c枋AHퟁo礼Ke?qWcA趸㡔ꂏ?\u000e춂8iতᦜ婪\u0015㢼nﵿꍻ!ᐴ関\u001d5j㨻gfῩUK5Ju丝tかTI'?㓏t>⼟o a>i}ᰗ;뤕ܝ": false, + "ꄮ匴껢ꂰ涽+䜨B蛹H䛓-k蕞fu7kL谖,'涃V~챳逋穞cT\"vQ쓕ObaCRQ㓡Ⲯ?轭⫦輢墳?vA餽=h䮇킵n폲퉅喙?\"'1疬V嬗Qd灗'Lự": "6v!s믁㭟㣯獃!磸餠ቂh0C뿯봗F鷭gꖶ~コkK<ᦈTt\\跓w㭣횋钘ᆹ듡䑚W䟾X'ꅔ4FL勉Vܴ邨y)2'〚쭉⽵-鞣E,Q.?块", + "?(˧쩯@崟吋歄K": null + }, + "Gc럃녧>?2DYI鴿\\륨)澔0ᔬlx'觔7젘⤡縷螩%Sv׫묈/]↱&S h\u0006歋ᑛxi̘}ひY蔯_醨鯘煑橾8?䵎쨋z儬ꁏ*@츾:": null + } + } + } + ] + ] + ]} + }, + "HO츧G": 3.694949578823609E17, + "QC\u0012(翻曇Tf㷟bGBJ옉53\\嚇ᛎD/\u001b夾၉4\"핀@祎)쫆yD\"i먎Vn㿿V1W᨝䶀": -6150931500380982286, + "Z㓮P翸鍱鉼K䋞꘺튿⭁Y": -7704503411315138850, + "]모开ꬖP븣c霤<[3aΠ\"黁䖖䰑뮋ꤦ秽∼㑷冹T+YUt\"싳F↭䖏&鋌": -2.7231911483181824E18, + "tꎖ": -4.9517948741799555E-19, + "䋘즊.⬅IꬃۣQ챢ꄑ黐|f?C⾺|兕읯sC鬸섾整腨솷V": "旆柩l쪦sᖸMy㦅울썉瘗㎜檵9ꍂ駓ૉᚿ/u3씅徐拉[Z䞸ࡗ1ꆱ&Q풘?ǂ8\u0011BCDY2볨;鸏": null, + "幫 n煥s쁇펇 왊-$C\"衝:\u0014㣯舼.3뙗Yl⋇\"K迎멎[꽵s}9鉳UK8쐥\"掄㹖h㙈!얄સ?Ꜳ봺R伕UTD媚I䜘W鏨蔮": -4.150842714188901E-17, + "ﺯ^㄄\b죵@fྉkf颡팋Ꞧ{/Pm0V둳⻿/落韒ꊔᚬ@5螺G\\咸a谆⊪ቧ慷绖?财(鷇u錝F=r၍橢ឳn:^iᴵtD볠覅N赴": null + }] + }] + } + ] + ]} + ]}, + "謯?w厓奰T李헗聝ឍ貖o⪇弒L!캶$ᆅ": -4299324168507841322, + "뺊奉_垐浸延몏孄Z舰2i$q붿좾껇d▵餏\"v暜Ҭ섁m￴g>": -1.60911932510533427E18 + } + ] + } + ] + ]], + "퉝꺔㠦楶Pꅱ": 7517896876489142899, + "": false + } + ]}, + "是u&I狻餼|谖j\"7c됮sסּ-踳鉷`䣷쉄_A艣鳞凃*m⯾☦椿q㎭N溔铉tlㆈ^": 1.93547720203604352E18, + "kⲨ\\%vr#\u000bⒺY\\t<\/3﬌R訤='﹠8蝤Ꞵ렴曔r": false + } + ]}, + "阨{c?C\u001d~K?鎌Ԭ8烫#뙣P초遗t㭱E­돒䆺}甗[R*1!\\~h㕅᰺@<9JꏏષI䳖栭6綘걹ᅩM\"▯是∔v鬽顭⋊譬": "운ﶁK敂(欖C취پ℄爦賾" + } + }} + }], + "鷨赼鸙+\\䭣t圙ڹx᜾ČN<\/踘\"S_맶a鷺漇T彚⎲i㈥LT-xA캔$\u001cUH=a0츺l릦": "溣㣂0濕=鉵氬駘>Pꌢpb솇쬤h힊줎獪㪬CrQ矠a&脍꼬爼M茴/΅\u0017弝轼y#Ꞡc6둴=?R崏뷠麖w?" + }, + "閕ᘜ]CT)䵞l9z'xZF{:ؐI/躅匽졁:䟇AGF૸\u001cퟗ9)駬慟ꡒꆒRS״툋A<>\u0010\"ꂔ炃7g덚E৏bꅰ輤]o㱏_뷕ܘ暂\"u": "芢+U^+㢩^鱆8*1鈶鮀\u0002뺰9⬳ꪮlL䃣괟,G8\u20a8DF㉪錖0ㄤ瓶8Nଷd?眡GLc陓\\_죌V쁰ल二?c띦捱 \u0019JC\u0011b⤉zẒT볕\"绣蘨뚋cꡉkI\u001e鳴", + "ꃣI'{6u^㡃#཰Kq4逹y൒䧠䵮!㱙/n??{L풓ZET㙠퍿X2᩟綳跠葿㚙w཮x캽扳B唕S|尾}촕%N?o䪨": null, + "ⰴFjෟ셈[\u0018辷px?椯\\1<ﲻ栘ᣁ봢憠뉴p": -5263694954586507640 + } + ] + ]] + ]} + ]}] + ] + ], + "?#癘82禩鋆ꊝty?&": -1.9419029518535086E-19 + } + ] + ] + ]} + ] + ] + ], + "훊榲.|῕戄&.㚏Zꛦ2\"䢥ሆ⤢fV_摕婔?≍Fji冀탆꜕i㏬_ẑKᅢ꫄蔻XWc|饡Siẘ^㲦?羡2ぴ1縁ᙅ?쐉Ou": false + }]] + ]}}}, + "慂뗄卓蓔ᐓ匐嚖/颹蘯/翻ㆼL?뇊,텵<\\獷ごCボ": null + }, + "p溉ᑟi짣z:䒤棇r^٫%G9缑r砌롧.물农g?0׼ሩ4ƸO㣥㯄쩞ጩ": null, + "껎繥YxK\"F젷쨹뤤1wq轫o?鱑뜀瘊?뎃h灑\\ꛣ}K峐^ኖ⤐林ꉓhy": null + } + ], + "᱀n肓ㄛ\"堻2>m殮'1橌%Ꞵ군=Ӳ鯨9耛<\/n據0u彘8㬇៩f᏿诙]嚊": "䋯쪦S럶匏ㅛ#)O`ሀX_鐪渲⛀㨻宅闩➈ꢙஶDR⪍" + }, + "tA썓龇 ⋥bj왎录r땽✒롰;羋^\\?툳*┎?썀ma䵳넅U䳆૘〹䆀LQ0\b疀U~u$M}(鵸g⳾i抦뛹?䤈땚검.鹆?ꩡtⶥGĒ;!ቹHS峻B츪켏f5≺": 2366175040075384032, + "전pJjleb]ួ": -7.5418493141528422E18, + "n.鎖ጲ\n?,$䪘": true + }, + "欈Ar㉣螵᪚茩?O)": null + }, + "쫸M#x}D秱欐K=侫们丐.KꕾxẠ\u001e㿯䣛F܍캗qq8꟞ṢFD훎⵳簕꭛^鳜\u205c٫~⑟~冫ऊ2쫰<\/戲윱o<\"": true + }, + "㷝聥/T뱂\u0010锕|内䞇x侁≦㭖:M?iM᣿IJe煜dG࣯尃⚩gPt*辂.{磼럾䝪@a\\袛?}ᓺB珼": true + } + } + ]]}]}}, + "tn\"6ꫤ샾䄄;銞^%VBPwu묪`Y僑N.↺Ws?3C⤻9唩S䠮ᐴm;sᇷ냞඘B/;툥B?lB∤)G+O9m裢0kC햪䪤": -4.5941249382502277E18, + "ᚔt'\\愫?鵀@\\びꂕP큠<<]煹G-b!S?\nꖽ鼫,ݛ&頺y踦?E揆릱H}햧캡b@手.p탻>췽㣬ꒅ`qe佭P>ᓂ&?u}毚ᜉ蟶頳졪ᎏzl2wO": -2.53561440423275936E17 + }]} + } + ] + ]], + "潈촒⿂叡": 5495738871964062986 + } + ]] + } + ] + ]} + ]] + ]] + ]} + ] + ]}, + "ႁq킍蓅R`謈蟐ᦏ儂槐僻ﹶ9婌櫞釈~\"%匹躾ɢ뤥>࢟瀴愅?殕节/냔O✬H鲽엢?ᮈੁ⋧d␽㫐zCe*": 2.15062231586689536E17, + "㶵Ui曚珰鋪ᾼ臧P{䍏䷪쨑̟A뼿T渠誈䏚D1!잶<\/㡍7?)2l≣穷᛾稝{:;㡹nemיּ訊`G": null, + "䀕\"飕辭p圁f#뫆䶷뛮;⛴ᩍ3灚덏ᰝ쎓⦷詵%᜖Մfs⇫(\u001e~P|ﭗCⲾផv湟W첋(텪બT<บSꏉ੗⋲X婵i ӵ⇮?L䬇|ꈏ?졸": 1.548341247351782E-19 + } + ] + }, + "t;:N\u0015q鐦Rt缆{ꮐC?஛㷱敪\\+鲊㉫㓪몗릙竏(氵kYS": "XᰂT?൮ô", + "碕飦幑|+ 㚦鏶`镥ꁩ B<\/加륙": -4314053432419755959, + "秌孳(p!G?V傫%8ሽ8w;5鲗㦙LI檸\u2098": "zG N볞䆭鎍흘\\ONK3횙<\/樚立圌Q튅k쩎Ff쁋aׂJK銆ઘ즐狩6༥✙䩜篥CzP(聻駇HHퟲ讃%,ά{렍p而刲vy䦅ክ^톺M楒鍢㹳]Mdg2>䤉洞", + "踛M젧>忔芿㌜Zk": 2215369545966507819, + "씐A`$槭頰퍻^U覒\bG毲aᣴU;8!팲f꜇E⸃_卵{嫏羃X쀳C7뗮m(嚼u N܁谟D劯9]#": true, + "ﻩ!뵸-筚P᭛}ἰ履lPh?౮ⶹꆛ穉뎃g萑㑓溢CX뾇G㖬A錟]RKaꄘ]Yo+@䘁's섎襠$^홰}F": null + }, + "粘ꪒ4HXᕘ蹵.$區\r\u001d묁77pPc^y笲Q<\/ꖶ 訍䃍ᨕG?*": 1.73773035935040224E17 + }, + "婅拳?bkU;#D矠❴vVN쩆t㜷A풃갮娪a%鮏絪3dAv룒#tm쑬⌛qYwc4|L8KZ;xU⓭㳔밆拓EZ7襨eD|隰ऌ䧼u9Ԣ+]贴P荿": 2.9628516456987075E18 + }]}}] + ]} + }} + ]}] + ], + "|g翉F*湹̶\u0005⏐1脉̀eI쩓ᖂ㫱0碞l䴨ꑅ㵽7AtἈ턧yq䳥塑:z:遀ᄐX눔擉)`N3昛oQ셖y-ڨ⾶恢ꈵq^<\/": null, + "菹\\랓G^璬x৴뭸ゆUS겧﮷Bꮤ ┉銜᯻0%N7}~f洋坄Xꔼ<\/4妟Vꄟ9:౟곡t킅冩䧉笭裟炂4봋ⱳ叺怊t+怯涗\"0㖈Hq": false, + "졬믟'ﺇফ圪쓬멤m邸QLব䗁愍4jvs翙 ྍ꧀艳H-|": null, + "컮襱⣱뗠 R毪/鹙꾀%헳8&": -5770986448525107020 + } + ], + "B䔚bꐻ뙏姓展槰T-똌鷺tc灿᫽^㓟䏀o3o$꘭趙萬I顩)뇭Ἑ䓝\f@{ᣨ`x3蔛": null + } + ] + ] + }], + "⦖扚vWꃱ꥙㾠壢輓{-⎳鹷贏璿䜑bG倛⋐磎c皇皩7a~ﳫU╣Q࠭ꎉS摅姽OW.홌ೞ.": null, + "蚪eVlH献r}ᮏ믠ﰩꔄ@瑄ⲱ": null, + "퀭$JWoꩢg역쁍䖔㑺h&ୢtXX愰㱇?㾫I_6 OaB瑈q裿": null, + "꽦ﲼLyr纛Zdu珍B絟쬴糔?㕂짹䏵e": "ḱ\u2009cX9멀i䶛簆㳀k" + } + ]]]], + "(_ꏮg່澮?ᩑyM<艷\u001aꪽ\\庼뙭Z맷㰩Vm\\lY筺]3㋲2㌩㄀Eਟ䝵⨄쐨ᔟgङHn鐖⤇놋瓇Q탚單oY\"♆臾jHᶈ征ቄ??uㇰA?#1侓": null + }, + "觓^~ሢ&iI띆g륎ḱ캀.ᓡꀮ胙鈉": 1.0664523593012836E-19, + "y詭Gbᔶऽs댁U:杜⤎ϲ쁗⮼D醄诿q뙰I#즧v蔎xHᵿt᡽[**?崮耖p缫쿃L菝,봬ꤦC쯵#=X1瞻@OZc鱗CQTx": null + } + ] + }}], + "剘紁\u0004\\Xn⊠6,တױ;嵣崇}讃iႽ)d1\\䔓": null + }, + "脨z\"{X,1u찜<'k&@?1}Yn$\u0015Rd輲ーa쮂굄+B$l": true, + "諳>*쭮괐䵟Ґ+<箁}빀䅱⡔檏臒hIH脟ꩪC핝ଗP좕\"0i<\/C褻D۞恗+^5?'ꂱ䚫^7}㡠cq6\\쨪ꔞꥢ?纖䫀氮蒫侲빦敶q{A煲G": -6880961710038544266 + }}] + }, + "5s⨲JvಽῶꭂᄢI.a৊": null, + "?1q꽏쿻ꛋDR%U娝>DgN乭G": -1.2105047302732358E-19 + } + ] + ]}, + "qZz`撋뙹둣j碇쁏\\ꆥ\u0018@藴疰Wz)O{F䶛l᷂绘訥$]뮍夻䢋䩇萿獰樧猵⣭j萶q)$꬚⵷0馢W:Ⱍ!Qoe": -1666634370862219540, + "t": "=wp|~碎Q鬳Ӎ\\l-<\/^ﳊhn퐖}䍔t碵ḛ혷?靻䊗", + "邙쇡㯇%#=,E4勃驆V繚q[Y댻XV㡸[逹ᰏ葢B@u=JS5?bLRn얮㍉⏅ﰳ?a6[&큟!藈": 1.2722786745736667E-19 + }, + "X블땨4{ph鵋ꉯ웸 5p簂䦭s_E徔濧d稝~No穔噕뽲)뉈c5M윅>⚋[岦䲟懷恁?鎐꓆ฬ爋獠䜔s{\u001bm鐚儸煛%bﯿXT>ꗘ@8G": 1157841540507770724, + "媤娪Q杸\u0011SAyᡈ쿯": true, + "灚^ಸ%걁<\/蛯?\"祴坓\\\\'흍": -3.4614808555942579E18, + "釴U:O湛㴑䀣렑縓\ta)(j:숾却䗌gCiB뽬Oyuq輥厁/7)?今hY︺Q": null + } + ] + ]]]}] + ], + "I笔趠Ph!<ཛྷ㸞诘X$畉F\u0005笷菟.Esr릙!W☆䲖뗷莾뒭U\"䀸犜Uo3Gꯌx4r蔇᡹㧪쨢準<䂀%ࡡꟼ瑍8炝Xs0䀝销?fi쥱ꆝલBB": -8571484181158525797, + "L⦁o#J|\"⽩-㱢d㌛8d\\㶤傩儻E[Y熯)r噤὘勇 }": "e(濨쓌K䧚僒㘍蠤Vᛸ\"络QJL2,嬓왍伢㋒䴿考澰@(㏾`kX$끑эE斡,蜍&~y", + "vj.|统圪ᵮPL?2oŶ`밧\"勃+0ue%⿥绬췈체$6:qa렐Q;~晘3㙘鹑": true, + "ශؙ4獄⶿c︋i⚅:ん閝Ⳙ苆籦kw{䙞셕pC췃ꍬ␜꟯ꚓ酄b힝hwk꭭M鬋8B耳쑘WQ\\偙ac'唀x᪌\u2048*h짎#ፇ鮠뾏ឿ뀌": false, + "⎀jꄒ牺3Ⓝ컴~?親ꕽぼܓ喏瘘!@<튋㐌꿱⩦{a?Yv%⪧笯Uܱ栅E搚i뚬:ꄃx7䙳ꦋ&䓹vq☶I䁘ᾘ涜\\썉뺌Lr%Bc㍜3?ꝭ砿裞]": null, + "⭤뙓z(㡂%亳K䌽꫿AԾ岺㦦㼴輞낚Vꦴw냟鬓㹈뽈+o3譻K1잞": 2091209026076965894, + "ㇲ\t⋇轑ꠤ룫X긒\"zoY읇희wj梐쐑l侸`e%s": -9.9240075473576563E17, + "啸ꮑ㉰!ᚓ}銏": -4.0694813896301194E18, + ">]囋੽EK뇜>_ꀣ緳碖{쐐裔[<ನ\"䇅\"5L?#xTwv#罐\u0005래t应\\N?빗;": "v쮽瞭p뭃" + } + ]], + "斴槾?Z翁\"~慍弞ﻆ=꜡o5鐋dw\"?K蠡i샾ogDﲰ_C*⬟iㇷ4nય蟏[㟉U꽌娛苸 ঢ়操贻洞펻)쿗૊許X⨪VY츚Z䍾㶭~튃ᵦ<\/E臭tve猑x嚢": null, + "锡⛩<\/칥ꈙᬙ蝀&Ꚑ籬■865?_>L詏쿨䈌浿弥爫̫lj&zx<\/C쉾?覯n?": null, + "꾳鑤/꼩d=ᘈn挫ᑩ䰬ZC": "3錢爋6Ƹ䴗v⪿Wr益G韠[\u0010屗9쁡钁u?殢c䳀蓃樄욂NAq赟c튒瘁렶Aૡɚ捍" + } + ] + ] + ]} + ] + ] + }]]]}} + ]}], + "Ej䗳U<\/Q=灒샎䞦,堰頠@褙g_\u0003ꤾfⶽ?퇋!łB〙ד3CC䌴鈌U:뭔咎(Qો臃䡬荋BO7㢝䟸\"Yb": 2.36010731779814E-20, + "逸'0岔j\u000e눘먷翌C츊秦=ꭣ棭ှ;鳸=麱$XP⩉駚橄A\\좱⛌jqv䰞3Ь踌v㳆¹gT┌gvLB賖烡m?@E঳i": null + }, + "曺v찘ׁ?&绫O័": 9107241066550187880 + } + ] + ], + "(e屄\u0019昜훕琖b蓘ᬄ0/۲묇Z蘮ဏ⨏蛘胯뢃@㘉8ሪWᨮ⦬ᅳ䅴HI၇쨳z囕陻엣1赳o": true, + ",b刈Z,ၠ晐T솝ŕB⩆ou'퐼≃绗雗d譊": null, + "a唥KB\"ﳝ肕$u\n^⅄P䟼냉䞸⩪u윗瀱ꔨ#yşs꒬=1|ﲤ爢`t౐튼쳫_Az(Ṋ擬㦷좕耈6": 2099309172767331582, + "?㴸U<\/䢔ꯡ阽扆㐤q鐋?f㔫wM嬙-;UV죫嚔픞G&\"Cᗍ䪏풊Q": "VM7疹+陕枡툩窲}翡䖶8欞čsT뮐}璤:jﺋ鎴}HfA൝⧻Zd#Qu茅J髒皣Y-︴[?-~쉜v딏璮㹚䅊﩯<-#\u000e걀h\u0004u抱﵊㼃U<㱷⊱IC進" + }, + "숌dee節鏽邺p넱蹓+e罕U": true + } + ], + "b⧴룏??ᔠ3ぱ>%郿劃翐ꏬꠛW瞳᫏누躨狀ໄy੽\"ីuS=㨞馸k乆E": "トz݈^9R䬑<ﮛGRꨳ\u000fTT泠纷꽀MRᴱ纊:㠭볮?%N56%鈕1䗍䜁a䲗j陇=뿻偂衋࿘ᓸ?ᕵZ+<\/}H耢b䀁z^f$&㝒LkꢳI脚뙛u": 5.694374481577558E-20 + }] + } + ]], + "obj": {"key": "wrong value"}, + "퓲꽪m{㶩/뇿#⼢&᭙硞㪔E嚉c樱㬇1a綑᝖DḾ䝩": null + } +} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/data/webapp.json b/src/comm/ros_bridge/rapidjson/bin/data/webapp.json new file mode 100644 index 000000000..ee7b0f8ba --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/data/webapp.json @@ -0,0 +1,88 @@ +{"web-app": { + "servlet": [ + { + "servlet-name": "cofaxCDS", + "servlet-class": "org.cofax.cds.CDSServlet", + "init-param": { + "configGlossary:installationAt": "Philadelphia, PA", + "configGlossary:adminEmail": "ksm@pobox.com", + "configGlossary:poweredBy": "Cofax", + "configGlossary:poweredByIcon": "/images/cofax.gif", + "configGlossary:staticPath": "/content/static", + "templateProcessorClass": "org.cofax.WysiwygTemplate", + "templateLoaderClass": "org.cofax.FilesTemplateLoader", + "templatePath": "templates", + "templateOverridePath": "", + "defaultListTemplate": "listTemplate.htm", + "defaultFileTemplate": "articleTemplate.htm", + "useJSP": false, + "jspListTemplate": "listTemplate.jsp", + "jspFileTemplate": "articleTemplate.jsp", + "cachePackageTagsTrack": 200, + "cachePackageTagsStore": 200, + "cachePackageTagsRefresh": 60, + "cacheTemplatesTrack": 100, + "cacheTemplatesStore": 50, + "cacheTemplatesRefresh": 15, + "cachePagesTrack": 200, + "cachePagesStore": 100, + "cachePagesRefresh": 10, + "cachePagesDirtyRead": 10, + "searchEngineListTemplate": "forSearchEnginesList.htm", + "searchEngineFileTemplate": "forSearchEngines.htm", + "searchEngineRobotsDb": "WEB-INF/robots.db", + "useDataStore": true, + "dataStoreClass": "org.cofax.SqlDataStore", + "redirectionClass": "org.cofax.SqlRedirection", + "dataStoreName": "cofax", + "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver", + "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon", + "dataStoreUser": "sa", + "dataStorePassword": "dataStoreTestQuery", + "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';", + "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log", + "dataStoreInitConns": 10, + "dataStoreMaxConns": 100, + "dataStoreConnUsageLimit": 100, + "dataStoreLogLevel": "debug", + "maxUrlLength": 500}}, + { + "servlet-name": "cofaxEmail", + "servlet-class": "org.cofax.cds.EmailServlet", + "init-param": { + "mailHost": "mail1", + "mailHostOverride": "mail2"}}, + { + "servlet-name": "cofaxAdmin", + "servlet-class": "org.cofax.cds.AdminServlet"}, + + { + "servlet-name": "fileServlet", + "servlet-class": "org.cofax.cds.FileServlet"}, + { + "servlet-name": "cofaxTools", + "servlet-class": "org.cofax.cms.CofaxToolsServlet", + "init-param": { + "templatePath": "toolstemplates/", + "log": 1, + "logLocation": "/usr/local/tomcat/logs/CofaxTools.log", + "logMaxSize": "", + "dataLog": 1, + "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log", + "dataLogMaxSize": "", + "removePageCache": "/content/admin/remove?cache=pages&id=", + "removeTemplateCache": "/content/admin/remove?cache=templates&id=", + "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder", + "lookInContext": 1, + "adminGroupID": 4, + "betaServer": true}}], + "servlet-mapping": { + "cofaxCDS": "/", + "cofaxEmail": "/cofaxutil/aemail/*", + "cofaxAdmin": "/admin/*", + "fileServlet": "/static/*", + "cofaxTools": "/tools/*"}, + + "taglib": { + "taglib-uri": "cofax.tld", + "taglib-location": "/WEB-INF/tlds/cofax.tld"}}} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/data/widget.json b/src/comm/ros_bridge/rapidjson/bin/data/widget.json new file mode 100644 index 000000000..32690e8b7 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/data/widget.json @@ -0,0 +1,26 @@ +{"widget": { + "debug": "on", + "window": { + "title": "Sample Konfabulator Widget", + "name": "main_window", + "width": 500, + "height": 500 + }, + "image": { + "src": "Images/Sun.png", + "name": "sun1", + "hOffset": 250, + "vOffset": 250, + "alignment": "center" + }, + "text": { + "data": "Click Here", + "size": 36, + "style": "bold", + "name": "text1", + "hOffset": 250, + "vOffset": 100, + "alignment": "center", + "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" + } +}} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/encodings/utf16be.json b/src/comm/ros_bridge/rapidjson/bin/encodings/utf16be.json new file mode 100644 index 0000000000000000000000000000000000000000..e46dbfb9ddc489f4e26450bd86626a3a55235533 GIT binary patch literal 368 zcmZRmX5eMuV&G&@Vn}7k1Cmxi?8%_Okj#(>gf%3?5(;N+7l+2{!x4;thftTA|Lu+w1DjQa+a2Au{y z26YCJ222LAKvq6bep0}8gA{{6plGzgWHfWKfqn#=vth=jDGUn76?U%KS;L^P%ksDj tgTf&Rph(BjEytz+eXFqc$MzYUk1!}4b-BuN@&J(bI_d(HQ38iSEdbokSsefX literal 0 HcmV?d00001 diff --git a/src/comm/ros_bridge/rapidjson/bin/encodings/utf16bebom.json b/src/comm/ros_bridge/rapidjson/bin/encodings/utf16bebom.json new file mode 100644 index 0000000000000000000000000000000000000000..0a23ae205cb3354e828cd3c0f3fce322b9618815 GIT binary patch literal 370 zcmezOpP`z8mw}6clR=3gl_3vES^=>qg91Y`Ln4r`02EDRC;`&x3^_nnF%T+%Wm152 zCRiqgAs?u!7^qqu%+FvbWher(a)IJ{K=X9qc2qHBFz7OPfK4cY*p?*N@Ha%xkGptx zNpk~_A8)|+zSXm?7%<_~SBzbsze?X~|6nwISwNe>eyTiZkZ-WY;HAM%gGn>)8&n!} z8uS>{8AKW|8N>ov`9S$e0ox5y3<80o(FT*z%*h7&5p2$e8JngsC>&SVxn^e#gTgM$ v<1P#eha`X^9Y?nun*#K$!rC9(XKX&gpm5aXD$B_OK-%l53s6Q090s)jyQo_l literal 0 HcmV?d00001 diff --git a/src/comm/ros_bridge/rapidjson/bin/encodings/utf16le.json b/src/comm/ros_bridge/rapidjson/bin/encodings/utf16le.json new file mode 100644 index 0000000000000000000000000000000000000000..92d504530cda3c0f6c775907f544e5b60fb9dcf8 GIT binary patch literal 368 zcmbSxg4F^cCaKr{cf5FW4VdUl!0Nh@TEt<{PXrcxkZHV3NW88I=Z|20aFK z29X9#2C+a^zQMuDNe0^kQVartqR|GEf#S&aX9N8RF=xhxDVr1+6ppXiS+i4t!E%?& xaRmm6LkbKX$G04va!d~xDnHiF*nVWQ0)xv@ma7L&Dlm8*bpgsKfy1Dd0RZ`SSsefX literal 0 HcmV?d00001 diff --git a/src/comm/ros_bridge/rapidjson/bin/encodings/utf16lebom.json b/src/comm/ros_bridge/rapidjson/bin/encodings/utf16lebom.json new file mode 100644 index 0000000000000000000000000000000000000000..eaba00132cdfbc222ddce1333d0268821d68db0d GIT binary patch literal 370 zcmezWubP3Efs28YL5U%iArDAe0kJ280z)!GB9N~D6is9(0n+IVIY3r15GsIWQh;Grs9GJ&&tNEJC<3!`f#P~V^K{^LR54^Q=rVYKO(=odCYbcMK`w;bZ+CHX z2~PvB-}ZpjeOG2N8Q{`aj6a&*cuJz%K(SUY3;k~;6rk2xc0Q&JsNLlrc^6f7n8&gAUj3}6Drz~2LKuH!Wb zU>X*{+G;|O#P&>r<5?(rtSy6U+2gzxD1M*ez78uT+9G%7w}WSHh2MK@pxN67-QbyA z+jZ?pb{nskcE6>eMyaoc5$;LZL#rjGW`9;XI+xDgq_86KmebEWmC-NN9QR8N{?l)c zy56azcKQ(yzh!s zTJ0ZbEYF#HCz&Y76i>eIJ@-BDGT%sF-;&m$1}dQf8ejqz;(L31c5wzU1|#6_0XWz3 z3Is3-b6{;bCWvEu#=-G46g<`z!L{shUK13)PjO#`r6O&fyYpMYGdIKUJ=W0dZGlek zOs?&^_Qbo5)=Jx-(m=h`Q^g3kr0k$o6H~J{EghUnCofW17JEzS=bcLEmuQUoCHnvA zH$z?TR8%{8kB8qfJcD=0z@e0S<4nRH?86oe0{eu+U=3g1Pri2!d6%#coI3MtL=>AX_ow;2pdo4ZLhWc;i-Xenk@RsURdrTA&o@;vuVo;bH;gPdZ;rmcDc$?A zz_(<_3;2c-9K%;A6_5vT2s@Ai_a6iMT<3b{`{q1y2%I|#Cs1ymd3NzTruPZ2q|@u@ z&4V}gDoI-qkk@r5W${^We2U~g_U#KbuhH8&_H!wPMd|q_%E=P1{*)fxBfAgVKG%45 J@*ixY{{az1SsefX literal 0 HcmV?d00001 diff --git a/src/comm/ros_bridge/rapidjson/bin/encodings/utf32lebom.json b/src/comm/ros_bridge/rapidjson/bin/encodings/utf32lebom.json new file mode 100644 index 0000000000000000000000000000000000000000..d3db39bf732c7055cb6053c23947c89d6859b2e9 GIT binary patch literal 740 zcmb7?yDNop9EU&2;&KL?NpDgXWMw`B2A5bQ1CHD&m*KdjER@cG;myB*66$nVkV|%E zv;V;2@_c&Vw@!vrXL$PFZ}0E@{gE~#rJx$Bpb;ivG1fa{*^LZf0>;4c0Gw-k6#|%o zd9ZIKCWvjrdPUUiCvOv@ujfy{nBYpdOMLS+RLBko64Ej)ECVgM3$O2OJCnq z-1|Puw`9jN_=Ex+!bd1&k^67}+b|67KMMA_&h^gs%^BnXIClh&pwvEd?BaJU-Y2|} zjxVD(4_?@-AZ>h0U MT;tivf3SuA2hZtS8UO$Q literal 0 HcmV?d00001 diff --git a/src/comm/ros_bridge/rapidjson/bin/encodings/utf8.json b/src/comm/ros_bridge/rapidjson/bin/encodings/utf8.json new file mode 100644 index 000000000..c500c943f --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/encodings/utf8.json @@ -0,0 +1,7 @@ +{ + "en":"I can eat glass and it doesn't hurt me.", + "zh-Hant":"我能吞下玻璃而不傷身體。", + "zh-Hans":"我能吞下玻璃而不伤身体。", + "ja":"私はガラスを食べられます。それは私を傷つけません。", + "ko":"나는 유리를 먹을 수 있어요. 그래도 아프지 않아요" +} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/encodings/utf8bom.json b/src/comm/ros_bridge/rapidjson/bin/encodings/utf8bom.json new file mode 100644 index 000000000..b9839fe2f --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/encodings/utf8bom.json @@ -0,0 +1,7 @@ +{ + "en":"I can eat glass and it doesn't hurt me.", + "zh-Hant":"我能吞下玻璃而不傷身體。", + "zh-Hans":"我能吞下玻璃而不伤身体。", + "ja":"私はガラスを食べられます。それは私を傷つけません。", + "ko":"나는 유리를 먹을 수 있어요. 그래도 아프지 않아요" +} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail1.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail1.json new file mode 100644 index 000000000..6216b865f --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail1.json @@ -0,0 +1 @@ +"A JSON payload should be an object or array, not a string." \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail10.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail10.json new file mode 100644 index 000000000..5d8c0047b --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail10.json @@ -0,0 +1 @@ +{"Extra value after close": true} "misplaced quoted value" \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail11.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail11.json new file mode 100644 index 000000000..76eb95b45 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail11.json @@ -0,0 +1 @@ +{"Illegal expression": 1 + 2} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail12.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail12.json new file mode 100644 index 000000000..77580a452 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail12.json @@ -0,0 +1 @@ +{"Illegal invocation": alert()} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail13.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail13.json new file mode 100644 index 000000000..379406b59 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail13.json @@ -0,0 +1 @@ +{"Numbers cannot have leading zeroes": 013} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail14.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail14.json new file mode 100644 index 000000000..0ed366b38 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail14.json @@ -0,0 +1 @@ +{"Numbers cannot be hex": 0x14} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail15.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail15.json new file mode 100644 index 000000000..fc8376b60 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail15.json @@ -0,0 +1 @@ +["Illegal backslash escape: \x15"] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail16.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail16.json new file mode 100644 index 000000000..3fe21d4b5 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail16.json @@ -0,0 +1 @@ +[\naked] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail17.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail17.json new file mode 100644 index 000000000..62b9214ae --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail17.json @@ -0,0 +1 @@ +["Illegal backslash escape: \017"] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail18.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail18.json new file mode 100644 index 000000000..edac92716 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail18.json @@ -0,0 +1 @@ +[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail19.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail19.json new file mode 100644 index 000000000..3b9c46fa9 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail19.json @@ -0,0 +1 @@ +{"Missing colon" null} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail2.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail2.json new file mode 100644 index 000000000..6b7c11e5a --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail2.json @@ -0,0 +1 @@ +["Unclosed array" \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail20.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail20.json new file mode 100644 index 000000000..27c1af3e7 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail20.json @@ -0,0 +1 @@ +{"Double colon":: null} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail21.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail21.json new file mode 100644 index 000000000..62474573b --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail21.json @@ -0,0 +1 @@ +{"Comma instead of colon", null} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail22.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail22.json new file mode 100644 index 000000000..a7752581b --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail22.json @@ -0,0 +1 @@ +["Colon instead of comma": false] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail23.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail23.json new file mode 100644 index 000000000..494add1ca --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail23.json @@ -0,0 +1 @@ +["Bad value", truth] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail24.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail24.json new file mode 100644 index 000000000..caff239bf --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail24.json @@ -0,0 +1 @@ +['single quote'] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail25.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail25.json new file mode 100644 index 000000000..8b7ad23e0 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail25.json @@ -0,0 +1 @@ +[" tab character in string "] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail26.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail26.json new file mode 100644 index 000000000..845d26a6a --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail26.json @@ -0,0 +1 @@ +["tab\ character\ in\ string\ "] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail27.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail27.json new file mode 100644 index 000000000..6b01a2ca4 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail27.json @@ -0,0 +1,2 @@ +["line +break"] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail28.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail28.json new file mode 100644 index 000000000..621a0101c --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail28.json @@ -0,0 +1,2 @@ +["line\ +break"] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail29.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail29.json new file mode 100644 index 000000000..47ec421bb --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail29.json @@ -0,0 +1 @@ +[0e] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail3.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail3.json new file mode 100644 index 000000000..168c81eb7 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail3.json @@ -0,0 +1 @@ +{unquoted_key: "keys must be quoted"} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail30.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail30.json new file mode 100644 index 000000000..8ab0bc4b8 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail30.json @@ -0,0 +1 @@ +[0e+] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail31.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail31.json new file mode 100644 index 000000000..1cce602b5 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail31.json @@ -0,0 +1 @@ +[0e+-1] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail32.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail32.json new file mode 100644 index 000000000..45cba7396 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail32.json @@ -0,0 +1 @@ +{"Comma instead if closing brace": true, \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail33.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail33.json new file mode 100644 index 000000000..ca5eb19dc --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail33.json @@ -0,0 +1 @@ +["mismatch"} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail4.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail4.json new file mode 100644 index 000000000..9de168bf3 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail4.json @@ -0,0 +1 @@ +["extra comma",] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail5.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail5.json new file mode 100644 index 000000000..ddf3ce3d2 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail5.json @@ -0,0 +1 @@ +["double extra comma",,] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail6.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail6.json new file mode 100644 index 000000000..ed91580e1 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail6.json @@ -0,0 +1 @@ +[ , "<-- missing value"] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail7.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail7.json new file mode 100644 index 000000000..8a96af3e4 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail7.json @@ -0,0 +1 @@ +["Comma after the close"], \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail8.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail8.json new file mode 100644 index 000000000..b28479c6e --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail8.json @@ -0,0 +1 @@ +["Extra close"]] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail9.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail9.json new file mode 100644 index 000000000..5815574f3 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/fail9.json @@ -0,0 +1 @@ +{"Extra comma": true,} \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/pass1.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/pass1.json new file mode 100644 index 000000000..70e268543 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/pass1.json @@ -0,0 +1,58 @@ +[ + "JSON Test Pattern pass1", + {"object with 1 member":["array with 1 element"]}, + {}, + [], + -42, + true, + false, + null, + { + "integer": 1234567890, + "real": -9876.543210, + "e": 0.123456789e-12, + "E": 1.234567890E+34, + "": 23456789012E66, + "zero": 0, + "one": 1, + "space": " ", + "quote": "\"", + "backslash": "\\", + "controls": "\b\f\n\r\t", + "slash": "/ & \/", + "alpha": "abcdefghijklmnopqrstuvwyz", + "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", + "digit": "0123456789", + "0123456789": "digit", + "special": "`1~!@#$%^&*()_+-={':[,]}|;.?", + "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", + "true": true, + "false": false, + "null": null, + "array":[ ], + "object":{ }, + "address": "50 St. James Street", + "url": "http://www.JSON.org/", + "comment": "// /* */": " ", + " s p a c e d " :[1,2 , 3 + +, + +4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], + "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", + "quotes": "" \u0022 %22 0x22 034 "", + "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" +: "A key can be any string" + }, + 0.5 ,98.6 +, +99.44 +, + +1066, +1e1, +0.1e1, +1e-1, +1e00,2e+00,2e-00 +,"rosebud"] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/pass2.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/pass2.json new file mode 100644 index 000000000..d3c63c7ad --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/pass2.json @@ -0,0 +1 @@ +[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/pass3.json b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/pass3.json new file mode 100644 index 000000000..4528d51f1 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/pass3.json @@ -0,0 +1,6 @@ +{ + "JSON Test Pattern pass3": { + "The outermost value": "must be an object or array.", + "In this test": "It is an object." + } +} diff --git a/src/comm/ros_bridge/rapidjson/bin/jsonchecker/readme.txt b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/readme.txt new file mode 100644 index 000000000..321d89d99 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/jsonchecker/readme.txt @@ -0,0 +1,3 @@ +Test suite from http://json.org/JSON_checker/. + +If the JSON_checker is working correctly, it must accept all of the pass*.json files and reject all of the fail*.json files. diff --git a/src/comm/ros_bridge/rapidjson/bin/types/booleans.json b/src/comm/ros_bridge/rapidjson/bin/types/booleans.json new file mode 100644 index 000000000..2dcbb5fe8 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/types/booleans.json @@ -0,0 +1,102 @@ +[ + true, + true, + false, + false, + true, + true, + true, + false, + false, + true, + false, + false, + true, + false, + false, + false, + true, + false, + false, + true, + true, + false, + true, + true, + true, + false, + false, + false, + true, + false, + true, + false, + false, + true, + true, + true, + true, + true, + true, + false, + false, + true, + false, + false, + false, + true, + true, + false, + true, + true, + false, + true, + false, + true, + true, + true, + false, + false, + false, + true, + false, + false, + false, + true, + true, + false, + true, + true, + true, + true, + true, + true, + true, + true, + false, + false, + false, + false, + false, + true, + true, + true, + true, + true, + true, + true, + false, + false, + false, + true, + false, + false, + false, + true, + true, + true, + false, + false, + true, + false +] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/types/floats.json b/src/comm/ros_bridge/rapidjson/bin/types/floats.json new file mode 100644 index 000000000..12b94a11d --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/types/floats.json @@ -0,0 +1,102 @@ +[ + 135.747111636, + 123.377054008, + 140.527504552, + -72.299143906, + -23.851678949, + 73.586193519, + -158.299382442, + 177.477876032, + 32.268518982, + -139.560009969, + 115.203105183, + -106.025823607, + 167.224138231, + 103.378383732, + -97.498486285, + 18.184723416, + 69.137075711, + 33.849002681, + -120.185228215, + -20.841408615, + -172.659492727, + -2.691464061, + 22.426164066, + -98.416909437, + -31.603082708, + -85.072296561, + 108.620987395, + -43.127078238, + -126.473562057, + -158.595489097, + -57.890678254, + -13.254016573, + -85.024504709, + 171.663552644, + -146.495558248, + -10.606748276, + -118.786969354, + 153.352057804, + -45.215545083, + 37.038725288, + 106.344071897, + -64.607402031, + 85.148030911, + 28.897784566, + 39.51082061, + 20.450382102, + -113.174943618, + 71.60785784, + -168.202648062, + -157.338200017, + 10.879588527, + -114.261694831, + -5.622927072, + -173.330830616, + -29.47002003, + -39.829034201, + 50.031545162, + 82.815735508, + -119.188760828, + -48.455928081, + 163.964263034, + 46.30378861, + -26.248889762, + -47.354615322, + 155.388677633, + -166.710356904, + 42.987233558, + 144.275297374, + 37.394383186, + -122.550388725, + 177.469945914, + 101.104677413, + 109.429869885, + -104.919625624, + 147.522756541, + -81.294703727, + 122.744731363, + 81.803603684, + 26.321556167, + 147.045441354, + 147.256895816, + -174.211095908, + 52.518769316, + -78.58250334, + -173.356685435, + -107.728209264, + -69.982325771, + -113.776095893, + -35.785267074, + -105.748545976, + -30.206523864, + -76.185311723, + -126.400112781, + -26.864958639, + 56.840053629, + 93.781553535, + -116.002949803, + -46.617140948, + 176.846840093, + -144.24821335 +] diff --git a/src/comm/ros_bridge/rapidjson/bin/types/guids.json b/src/comm/ros_bridge/rapidjson/bin/types/guids.json new file mode 100644 index 000000000..9d7f5dbc8 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/types/guids.json @@ -0,0 +1,102 @@ +[ + "d35bf0d4-8d8f-4e17-a5c3-ad9bfd675266", + "db402774-eeb6-463b-9986-c458c44d8b5a", + "2a2e4101-b5f2-40b8-8750-e03f01661e60", + "76787cfa-f4eb-4d62-aaad-e1d588d00ad5", + "fd73894b-b500-4a7c-888c-06b5bd9cec65", + "cce1862a-cf31-4ef2-9e23-f1d23b4e6163", + "00a98bb0-2b6e-4368-8512-71c21aa87db7", + "ab9a8d69-cec7-4550-bd35-3ed678e22782", + "f18b48e1-5114-4fbe-9652-579e8d66950e", + "4efe3baa-7ac5-4d6a-a839-6b9cfe825764", + "b4aec119-5b0a-434c-b388-109816c482a5", + "e0ef0cbb-127a-4a28-9831-5741b4295275", + "d50286a5-cb7b-4c9e-be99-f214439bae8c", + "a981094c-f1ac-42ed-a9fa-86404c7210ff", + "2a34ee57-5815-4829-b77b-eeebaa8fe340", + "a0530d44-48f8-4eff-b9ea-8810c4308351", + "c6f91509-83e1-4ea1-9680-e667fbfd56ee", + "cab11402-dcdd-4454-b190-6da124947395", + "283d159c-2b18-4856-b4c7-5059252eaa15", + "146157c6-72a8-4051-9991-cb6ea6743d81", + "aef6f269-7306-4bd2-83f7-6d5605b5dc9a", + "37fe6027-d638-4017-80a9-e7b0567b278e", + "5003d731-33fb-4159-af61-d76348a44079", + "e0e06979-5f80-4713-9fe0-8a4d60dc89f8", + "7e85bdc3-0345-4cb6-9398-ccab06e79976", + "f2ebf5af-6568-4ffe-a46d-403863fd4b66", + "e0b5bb1c-b4dd-4535-9a9e-3c73f1167d46", + "c852d20b-6bcb-4b12-bd57-308296c64c5a", + "7ac3ae82-1818-49cd-a8a4-5ac77dfafd46", + "138004a9-76e2-4ad7-bd42-e74dabdbb803", + "ab25b5be-96be-45b0-b765-947b40ec36a6", + "08404734-fd57-499e-a4cf-71e9ec782ede", + "8dfdeb16-248b-4a21-bf89-2e22b11a4101", + "a0e44ef0-3b09-41e8-ad5d-ed8e6a1a2a67", + "a7981e49-188d-414a-9779-b1ad91e599d1", + "329186c0-bf27-4208-baf7-c0a0a5a2d5b7", + "cb5f3381-d33e-4b30-b1a9-f482623cad33", + "15031262-ca73-4e3c-bd0a-fcf89bdf0caf", + "6d7333d1-2e8c-4d78-bfde-5be47e70eb13", + "acaa160c-670a-4e8f-ac45-49416e77d5f9", + "228f87eb-cde4-4106-808b-2dbf3c7b6d2e", + "2ff830a3-5445-4d8e-b161-bddd30666697", + "f488bedd-ff6e-4108-b9a7-07f6da62f476", + "2e12b846-0a34-478e-adf7-a438493803e6", + "6686b8ef-7446-4d86-bd8c-df24119e3bfe", + "e474a5c5-5793-4d41-b4ab-5423acc56ef1", + "ac046573-e718-44dc-a0dc-9037eeaba6a9", + "6b0e9099-cf53-4d5a-8a71-977528628fcf", + "d51a3f22-0ff9-4087-ba9b-fcee2a2d8ade", + "bdc01286-3511-4d22-bfb8-76d01203d366", + "ca44eb84-17ff-4f27-8f1e-1bd25f4e8725", + "4e9a8c2f-be0b-4913-92d2-c801b9a50d04", + "7685d231-dadd-4041-9165-898397438ab7", + "86f0bf26-d66a-44d8-99f5-d6768addae3b", + "2ca1167c-72ba-45a0-aa42-faf033db0d0b", + "199a1182-ea55-49ff-ba51-71c29cdd0aac", + "be6a4dd2-c821-4aa0-8b83-d64d6644b5b2", + "4c5f4781-7f80-4daa-9c20-76b183000514", + "513b31bd-54fb-4d12-a427-42a7c13ff8e1", + "8e211bcb-d76c-4012-83ad-74dd7d23b687", + "44d5807e-0501-4f66-8779-e244d4fdca0a", + "db8cd555-0563-4b7b-b00c-eada300a7065", + "cb14d0c9-46cc-4797-bd3a-752b05629f07", + "4f68b3ef-ac9b-47a0-b6d7-57f398a5c6a5", + "77221aae-1bcf-471c-be45-7f31f733f9d6", + "42a7cac8-9e80-4c45-8c71-511d863c98ea", + "f9018d22-b82c-468c-bdb5-8864d5964801", + "75f4e9b8-62a2-4f21-ad8a-e19eff0419bc", + "9b7385c8-8653-4184-951c-b0ac1b36b42e", + "571018aa-ffbf-4b42-a16d-07b57a7f5f0e", + "35de4a2f-6bf1-45aa-b820-2a27ea833e44", + "0b8edb20-3bb4-4cb4-b089-31957466dbab", + "97da4778-9a7b-4140-a545-968148c81fb7", + "969f326c-8f2a-47c5-b41c-d9c2f06c9b9d", + "ae211037-8b53-4b17-bfc8-c06fc7774409", + "12c5c3c4-0bd5-45d3-bc1d-d04a3c65d3e6", + "ec02024f-ce43-4dd3-8169-a59f7baee043", + "5b6afe77-ce48-47ca-90a0-25cd10ca5ffd", + "2e3a61d4-6b8f-4d2f-ba86-878b4012efd8", + "19a88a67-a5d3-4647-898f-1cde07bce040", + "6db6f420-b5c8-48b9-bbb2-8864fe6fed65", + "5a45dbde-7b53-4f6b-b864-e3b63be3708a", + "c878321b-8a02-4239-9981-15760c2e7d15", + "4e36687f-8bf6-4b12-b496-3a8e382d067e", + "a59a63cd-43c0-4c6e-b208-6dbca86f8176", + "303308c4-2e4a-45b5-8bf3-3e66e9ad05a1", + "8b58fdf1-43a6-4c98-9547-6361b50791af", + "a3563591-72ed-42b5-8e41-bac1d76d70cf", + "38db8c78-3739-4f6e-8313-de4138082114", + "86615bea-7e73-4daf-95da-ae6b9eee1bbb", + "35d38e3e-076e-40dd-9aa8-05be2603bd59", + "9f84c62d-b454-4ba3-8c19-a01878985cdc", + "6721bbae-d765-4a06-8289-6fe46a1bf943", + "0837796f-d0dd-4e50-9b7c-1983e6cc7c48", + "021eb7d7-e869-49b9-80c3-9dd16ce2d981", + "819c56f8-e040-475d-aad5-c6d5e98b20aa", + "3a61ef02-735e-4229-937d-b3777a3f4e1f", + "79dfab84-12e6-4ec8-bfc8-460ae71e4eca", + "a106fabf-e149-476c-8053-b62388b6eb57", + "9a3900a5-bfb4-4de0-baa5-253a8bd0b634" +] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/types/integers.json b/src/comm/ros_bridge/rapidjson/bin/types/integers.json new file mode 100644 index 000000000..5dd05e097 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/types/integers.json @@ -0,0 +1,102 @@ +[ + 8125686, + 8958709, + 5976222, + 1889524, + 7968493, + 1357486, + 118415, + 7081097, + 4635968, + 7555332, + 2270233, + 3428352, + 8699968, + 2087333, + 7861337, + 7554440, + 2017031, + 7981692, + 6060687, + 1877715, + 3297474, + 8373177, + 6158629, + 7853641, + 3004441, + 9650406, + 2695251, + 1180761, + 4988426, + 6043805, + 8063373, + 6103218, + 2848339, + 8188690, + 9235573, + 5949816, + 6116081, + 6471138, + 3354531, + 4787414, + 9660600, + 942529, + 7278535, + 7967399, + 554292, + 1436493, + 267319, + 2606657, + 7900601, + 4276634, + 7996757, + 8544466, + 7266469, + 3301373, + 4005350, + 6437652, + 7717672, + 7126292, + 8588394, + 2127902, + 7410190, + 1517806, + 4583602, + 3123440, + 7747613, + 5029464, + 9834390, + 3087227, + 4913822, + 7550487, + 4518144, + 5862588, + 1778599, + 9493290, + 5588455, + 3638706, + 7394293, + 4294719, + 3837830, + 6381878, + 7175866, + 8575492, + 1415229, + 1453733, + 6972404, + 9782571, + 4234063, + 7117418, + 7293130, + 8057071, + 9345285, + 7626648, + 3358911, + 4574537, + 9371826, + 7627107, + 6154093, + 5392367, + 5398105, + 6956377 +] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/types/mixed.json b/src/comm/ros_bridge/rapidjson/bin/types/mixed.json new file mode 100644 index 000000000..43e9a1d7b --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/types/mixed.json @@ -0,0 +1,592 @@ +[ + { + "favoriteFruit": "banana", + "greeting": "Hello, Kim! You have 10 unread messages.", + "friends": [ + { + "name": "Higgins Rodriquez", + "id": 0 + }, + { + "name": "James Floyd", + "id": 1 + }, + { + "name": "Gay Stewart", + "id": 2 + } + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "tags": [ + "pariatur", + "ad", + "eiusmod", + "sit", + "et", + "velit", + "culpa" + ], + "longitude": -57.919246, + "latitude": -36.022812, + "registered": "Friday, March 21, 2014 9:13 PM", + "about": "Laborum nulla aliquip ullamco proident excepteur est officia ipsum. Eiusmod exercitation minim ex do labore reprehenderit aliqua minim qui excepteur reprehenderit cupidatat. Sint enim exercitation duis id consequat nisi enim magna. Commodo aliqua id ipsum sit magna enim. Veniam officia in labore fugiat veniam ea laboris ex veniam duis.\r\n", + "address": "323 Pulaski Street, Ronco, North Carolina, 7701", + "phone": "+1 (919) 438-2678", + "email": "kim.griffith@cipromox.biz", + "company": "CIPROMOX", + "name": { + "last": "Griffith", + "first": "Kim" + }, + "eyeColor": "green", + "age": 26, + "picture": "http://placehold.it/32x32", + "balance": "$1,283.55", + "isActive": false, + "guid": "10ab0392-c5e2-48a3-9473-aa725bad892d", + "index": 0, + "_id": "551b91198238a0bcf9a41133" + }, + { + "favoriteFruit": "banana", + "greeting": "Hello, Skinner! You have 9 unread messages.", + "friends": [ + { + "name": "Rhonda Justice", + "id": 0 + }, + { + "name": "Audra Castaneda", + "id": 1 + }, + { + "name": "Vicky Chavez", + "id": 2 + } + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "tags": [ + "dolore", + "enim", + "sit", + "non", + "exercitation", + "fugiat", + "adipisicing" + ], + "longitude": -60.291407, + "latitude": -84.619318, + "registered": "Friday, February 7, 2014 3:17 AM", + "about": "Consectetur eiusmod laboris dolore est ullamco nulla in velit quis esse Lorem. Amet aliqua sunt aute occaecat veniam officia in duis proident aliqua cupidatat mollit. Sint eu qui anim duis ut anim duis eu cillum. Cillum nostrud adipisicing tempor Lorem commodo sit in ad qui non et irure qui. Labore eu aliquip id duis eiusmod veniam.\r\n", + "address": "347 Autumn Avenue, Fidelis, Puerto Rico, 543", + "phone": "+1 (889) 457-2319", + "email": "skinner.maddox@moltonic.co.uk", + "company": "MOLTONIC", + "name": { + "last": "Maddox", + "first": "Skinner" + }, + "eyeColor": "green", + "age": 22, + "picture": "http://placehold.it/32x32", + "balance": "$3,553.10", + "isActive": false, + "guid": "cfbc2fb6-2641-4388-b06d-ec0212cfac1e", + "index": 1, + "_id": "551b91197e0abe92d6642700" + }, + { + "favoriteFruit": "strawberry", + "greeting": "Hello, Reynolds! You have 5 unread messages.", + "friends": [ + { + "name": "Brady Valdez", + "id": 0 + }, + { + "name": "Boyer Golden", + "id": 1 + }, + { + "name": "Gladys Knapp", + "id": 2 + } + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "tags": [ + "commodo", + "eiusmod", + "cupidatat", + "et", + "occaecat", + "proident", + "Lorem" + ], + "longitude": 140.866287, + "latitude": 1.401032, + "registered": "Monday, October 20, 2014 8:01 AM", + "about": "Deserunt elit consequat ea dolor pariatur aute consectetur et nulla ipsum ad. Laboris occaecat ipsum ad duis et esse ea ut voluptate. Ex magna consequat pariatur amet. Quis excepteur non mollit dolore cillum dolor ex esse veniam esse deserunt non occaecat veniam. Sit amet proident proident amet. Nisi est id ut ut adipisicing esse fugiat non dolor aute.\r\n", + "address": "872 Montague Terrace, Haena, Montana, 3106", + "phone": "+1 (974) 410-2655", + "email": "reynolds.sanford@combot.biz", + "company": "COMBOT", + "name": { + "last": "Sanford", + "first": "Reynolds" + }, + "eyeColor": "green", + "age": 21, + "picture": "http://placehold.it/32x32", + "balance": "$3,664.47", + "isActive": true, + "guid": "f9933a9c-c41a-412f-a18d-e727c569870b", + "index": 2, + "_id": "551b91197f170b65413a06e3" + }, + { + "favoriteFruit": "banana", + "greeting": "Hello, Neva! You have 7 unread messages.", + "friends": [ + { + "name": "Clara Cotton", + "id": 0 + }, + { + "name": "Ray Gates", + "id": 1 + }, + { + "name": "Jacobs Reese", + "id": 2 + } + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "tags": [ + "magna", + "labore", + "incididunt", + "velit", + "ea", + "et", + "eiusmod" + ], + "longitude": -133.058479, + "latitude": 87.803677, + "registered": "Friday, May 9, 2014 5:41 PM", + "about": "Do duis occaecat ut officia occaecat officia nostrud reprehenderit ex excepteur aute anim in reprehenderit. Cupidatat nulla eiusmod nulla non minim veniam aute nulla deserunt adipisicing consectetur veniam. Sit consequat ex laboris aliqua labore consectetur tempor proident consequat est. Fugiat quis esse culpa aliquip. Excepteur laborum aliquip sunt eu cupidatat magna eiusmod amet nisi labore aliquip. Ut consectetur esse aliquip exercitation nulla ex occaecat elit do ex eiusmod deserunt. Ex eu voluptate minim deserunt fugiat minim est occaecat ad Lorem nisi.\r\n", + "address": "480 Eagle Street, Fostoria, Oklahoma, 2614", + "phone": "+1 (983) 439-3000", + "email": "neva.barker@pushcart.us", + "company": "PUSHCART", + "name": { + "last": "Barker", + "first": "Neva" + }, + "eyeColor": "brown", + "age": 36, + "picture": "http://placehold.it/32x32", + "balance": "$3,182.24", + "isActive": true, + "guid": "52489849-78e1-4b27-8b86-e3e5ab2b7dc8", + "index": 3, + "_id": "551b9119a13061c083c878d5" + }, + { + "favoriteFruit": "banana", + "greeting": "Hello, Rodgers! You have 6 unread messages.", + "friends": [ + { + "name": "Marguerite Conway", + "id": 0 + }, + { + "name": "Margarita Cunningham", + "id": 1 + }, + { + "name": "Carmela Gallagher", + "id": 2 + } + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "tags": [ + "ipsum", + "magna", + "amet", + "elit", + "sit", + "occaecat", + "elit" + ], + "longitude": -125.436981, + "latitude": 19.868524, + "registered": "Tuesday, July 8, 2014 8:09 PM", + "about": "In cillum esse tempor do magna id ad excepteur ex nostrud mollit deserunt aliqua. Minim aliqua commodo commodo consectetur exercitation nulla nisi dolore aliqua in. Incididunt deserunt mollit nostrud excepteur. Ipsum fugiat anim deserunt Lorem aliquip nisi consequat eu minim in ex duis.\r\n", + "address": "989 Varanda Place, Duryea, Palau, 3972", + "phone": "+1 (968) 578-2974", + "email": "rodgers.conner@frenex.net", + "company": "FRENEX", + "name": { + "last": "Conner", + "first": "Rodgers" + }, + "eyeColor": "blue", + "age": 23, + "picture": "http://placehold.it/32x32", + "balance": "$1,665.17", + "isActive": true, + "guid": "ed3b2374-5afe-4fca-9325-8a7bbc9f81a0", + "index": 4, + "_id": "551b91197bcedb1b56a241ce" + }, + { + "favoriteFruit": "strawberry", + "greeting": "Hello, Mari! You have 10 unread messages.", + "friends": [ + { + "name": "Irwin Boyd", + "id": 0 + }, + { + "name": "Dejesus Flores", + "id": 1 + }, + { + "name": "Lane Mcmahon", + "id": 2 + } + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "tags": [ + "esse", + "aliquip", + "excepteur", + "dolor", + "ex", + "commodo", + "anim" + ], + "longitude": -17.038176, + "latitude": 17.154663, + "registered": "Sunday, April 6, 2014 4:46 AM", + "about": "Excepteur veniam occaecat sint nulla magna in in officia elit. Eiusmod qui dolor fugiat tempor in minim esse officia minim consequat. Lorem ullamco labore proident ipsum id pariatur fugiat consectetur anim cupidatat qui proident non ipsum.\r\n", + "address": "563 Hendrickson Street, Westwood, South Dakota, 4959", + "phone": "+1 (980) 434-3976", + "email": "mari.fleming@beadzza.org", + "company": "BEADZZA", + "name": { + "last": "Fleming", + "first": "Mari" + }, + "eyeColor": "blue", + "age": 21, + "picture": "http://placehold.it/32x32", + "balance": "$1,948.04", + "isActive": true, + "guid": "6bd02166-3b1f-4ed8-84c9-ed96cbf12abc", + "index": 5, + "_id": "551b9119b359ff6d24846f77" + }, + { + "favoriteFruit": "strawberry", + "greeting": "Hello, Maxine! You have 7 unread messages.", + "friends": [ + { + "name": "Sullivan Stark", + "id": 0 + }, + { + "name": "Underwood Mclaughlin", + "id": 1 + }, + { + "name": "Kristy Carlson", + "id": 2 + } + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "tags": [ + "commodo", + "ipsum", + "quis", + "non", + "est", + "mollit", + "exercitation" + ], + "longitude": -105.40635, + "latitude": 37.197993, + "registered": "Tuesday, January 20, 2015 12:30 AM", + "about": "Proident ullamco Lorem est consequat consectetur non eiusmod esse nostrud pariatur eiusmod enim exercitation eiusmod. Consequat duis elit elit minim ullamco et dolor eu minim do tempor esse consequat excepteur. Mollit dolor do voluptate nostrud quis anim cillum velit tempor eiusmod adipisicing tempor do culpa. Eu magna dolor sit amet nisi do laborum dolore nisi. Deserunt ipsum et deserunt non nisi.\r\n", + "address": "252 Boulevard Court, Brenton, Tennessee, 9444", + "phone": "+1 (950) 466-3377", + "email": "maxine.moreno@zentia.tv", + "company": "ZENTIA", + "name": { + "last": "Moreno", + "first": "Maxine" + }, + "eyeColor": "brown", + "age": 24, + "picture": "http://placehold.it/32x32", + "balance": "$1,200.24", + "isActive": false, + "guid": "ce307a37-ca1f-43f5-b637-dca2605712be", + "index": 6, + "_id": "551b91195a6164b2e35f6dc8" + }, + { + "favoriteFruit": "strawberry", + "greeting": "Hello, Helga! You have 5 unread messages.", + "friends": [ + { + "name": "Alicia Vance", + "id": 0 + }, + { + "name": "Vinson Phelps", + "id": 1 + }, + { + "name": "Francisca Kelley", + "id": 2 + } + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "tags": [ + "nostrud", + "eiusmod", + "dolore", + "officia", + "sint", + "non", + "qui" + ], + "longitude": -7.275151, + "latitude": 75.54202, + "registered": "Wednesday, October 1, 2014 6:35 PM", + "about": "Quis duis ullamco velit qui. Consectetur non adipisicing id magna anim. Deserunt est officia qui esse. Et do pariatur incididunt anim ad mollit non. Et eiusmod sunt fugiat elit mollit ad excepteur anim nisi laboris eiusmod aliquip aliquip.\r\n", + "address": "981 Bush Street, Beaulieu, Vermont, 3775", + "phone": "+1 (956) 506-3807", + "email": "helga.burch@synkgen.name", + "company": "SYNKGEN", + "name": { + "last": "Burch", + "first": "Helga" + }, + "eyeColor": "blue", + "age": 22, + "picture": "http://placehold.it/32x32", + "balance": "$3,827.89", + "isActive": false, + "guid": "ff5dfea0-1052-4ef2-8b66-4dc1aad0a4fb", + "index": 7, + "_id": "551b911946be8358ae40e90e" + }, + { + "favoriteFruit": "banana", + "greeting": "Hello, Shaw! You have 5 unread messages.", + "friends": [ + { + "name": "Christian Cardenas", + "id": 0 + }, + { + "name": "Cohen Pennington", + "id": 1 + }, + { + "name": "Mary Lindsay", + "id": 2 + } + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "tags": [ + "occaecat", + "ut", + "occaecat", + "magna", + "exercitation", + "incididunt", + "irure" + ], + "longitude": -89.102972, + "latitude": 89.489596, + "registered": "Thursday, August 21, 2014 5:00 PM", + "about": "Amet cupidatat quis velit aute Lorem consequat pariatur mollit deserunt et sint culpa excepteur duis. Enim proident duis qui ex tempor sunt nostrud occaecat. Officia sit veniam mollit eiusmod minim do aute eiusmod fugiat qui anim adipisicing in laboris. Do tempor reprehenderit sunt laborum esse irure dolor ad consectetur aute sit id ipsum. Commodo et voluptate anim consequat do. Minim laborum ad veniam ad minim incididunt excepteur excepteur aliqua.\r\n", + "address": "237 Pierrepont Street, Herbster, New York, 3490", + "phone": "+1 (976) 455-2880", + "email": "shaw.zamora@shadease.me", + "company": "SHADEASE", + "name": { + "last": "Zamora", + "first": "Shaw" + }, + "eyeColor": "blue", + "age": 38, + "picture": "http://placehold.it/32x32", + "balance": "$3,440.82", + "isActive": false, + "guid": "ac5fdb0e-e1fb-427e-881d-da461be0d1ca", + "index": 8, + "_id": "551b9119af0077bc28a2de25" + }, + { + "favoriteFruit": "apple", + "greeting": "Hello, Melissa! You have 5 unread messages.", + "friends": [ + { + "name": "Marion Villarreal", + "id": 0 + }, + { + "name": "Kate Rose", + "id": 1 + }, + { + "name": "Hines Simon", + "id": 2 + } + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "tags": [ + "amet", + "veniam", + "mollit", + "ad", + "cupidatat", + "deserunt", + "Lorem" + ], + "longitude": -52.735052, + "latitude": 16.258838, + "registered": "Wednesday, April 16, 2014 7:56 PM", + "about": "Aute ut culpa eiusmod tempor duis dolor tempor incididunt. Nisi non proident excepteur eiusmod incididunt nisi minim irure sit. In veniam commodo deserunt proident reprehenderit et consectetur ullamco quis nulla cupidatat.\r\n", + "address": "642 Halsey Street, Blandburg, Kansas, 6761", + "phone": "+1 (941) 539-3851", + "email": "melissa.vaughn@memora.io", + "company": "MEMORA", + "name": { + "last": "Vaughn", + "first": "Melissa" + }, + "eyeColor": "brown", + "age": 24, + "picture": "http://placehold.it/32x32", + "balance": "$2,399.44", + "isActive": true, + "guid": "1769f022-a7f1-4a69-bf4c-f5a5ebeab2d1", + "index": 9, + "_id": "551b9119b607c09c7ffc3b8a" + } +] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/types/nulls.json b/src/comm/ros_bridge/rapidjson/bin/types/nulls.json new file mode 100644 index 000000000..7a636ec87 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/types/nulls.json @@ -0,0 +1,102 @@ +[ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null +] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/types/paragraphs.json b/src/comm/ros_bridge/rapidjson/bin/types/paragraphs.json new file mode 100644 index 000000000..8ab3e1c56 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/types/paragraphs.json @@ -0,0 +1,102 @@ +[ + "Commodo ullamco cupidatat nisi sit proident ex. Cillum pariatur occaecat in officia do commodo nisi cillum tempor minim. Ad dolor ut et aliquip fugiat eu officia cupidatat occaecat consectetur eiusmod veniam enim officia.\r\n", + "Adipisicing cillum laborum nisi irure. Cillum dolor proident duis nulla qui mollit dolore reprehenderit mollit. Irure nulla dolor ipsum irure nulla quis laboris do.\r\n", + "Est adipisicing consectetur incididunt in. Occaecat ea magna ex consequat irure sit laborum cillum officia magna sunt do exercitation aliquip. Laboris id aute in dolore reprehenderit voluptate non deserunt laborum.\r\n", + "Consectetur eu aute est est occaecat adipisicing sint enim dolor eu. Tempor amet id non mollit eu consectetur cillum duis. Eu labore velit nulla ipsum commodo consequat aliquip. Cupidatat commodo dolore mollit enim sit excepteur nisi duis laboris deserunt esse.\r\n", + "Incididunt ullamco est fugiat enim fugiat. Do sit mollit anim ad excepteur eu laboris exercitation officia labore nulla ut. Voluptate non voluptate cillum sit et voluptate anim duis velit consequat aliquip dolor. Elit et et esse laboris consectetur officia eiusmod aliquip nisi est. Qui labore dolore ad dolor.\r\n", + "Anim adipisicing est irure proident sit officia ullamco voluptate sunt consectetur duis mollit excepteur veniam. Nostrud ut duis aute exercitation officia et quis elit commodo elit tempor aute aliquip enim. Est officia non cillum consequat voluptate ipsum sit voluptate nulla id.\r\n", + "Ipsum enim consectetur aliquip nulla commodo ut ex aliqua elit duis do. Officia et sunt aliqua dolor minim voluptate veniam esse elit enim. Adipisicing reprehenderit duis ex magna non in fugiat sunt ipsum nostrud fugiat aliquip. Labore voluptate id officia voluptate eu. Magna do nostrud excepteur sunt aliqua adipisicing qui.\r\n", + "Est occaecat non non cupidatat laborum qui. Veniam sit est voluptate labore sit irure consectetur fugiat. Anim enim enim fugiat exercitation anim ad proident esse in aliqua. Laboris ut aute culpa ullamco.\r\n", + "Sit et aliquip cupidatat deserunt eiusmod sint aliquip occaecat nostrud aliqua elit commodo ut magna. Amet sit est deserunt id duis in officia pariatur cupidatat ex. Mollit duis est consequat nulla aute velit ipsum sit consectetur pariatur ut non ex ipsum. Tempor esse velit pariatur reprehenderit et nostrud commodo laborum mollit labore.\r\n", + "Aliquip irure quis esse aliquip. Ex non deserunt culpa aliqua ad anim occaecat ad. Lorem consectetur mollit eu consectetur est non nisi non ipsum. Qui veniam ullamco officia est ut excepteur. Nulla elit dolore cupidatat aliqua enim Lorem elit consequat eiusmod non aliqua eu in. Pariatur in culpa labore sint ipsum consectetur occaecat ad ex ipsum laboris aliquip officia. Non officia eiusmod nisi officia id id laboris deserunt sunt enim magna mollit sit.\r\n", + "Mollit velit laboris laborum nulla aliquip consequat Lorem non incididunt irure. Eu voluptate sint do consectetur tempor sit Lorem in. Laborum eiusmod nisi Lorem ipsum dolore do aute laborum occaecat aute sunt. Sit laborum in ea do ipsum officia irure cillum irure nisi laboris. Ad anim deserunt excepteur ea veniam eiusmod culpa velit veniam. Commodo incididunt ea Lorem eu enim esse nisi incididunt mollit.\r\n", + "Velit proident sunt aute dolore reprehenderit culpa. Pariatur reprehenderit commodo ad ea voluptate anim nulla ipsum eu irure fugiat aliqua et. Adipisicing incididunt anim excepteur voluptate minim qui culpa. Sunt veniam enim reprehenderit magna magna. Sit ad amet deserunt ut aute dolore ad minim.\r\n", + "Esse ullamco sunt mollit mollit. Eu enim dolore laboris cupidatat. Cupidatat adipisicing non aute exercitation fugiat. Non ut cillum labore fugiat aliquip ex duis quis consectetur ut nisi Lorem amet qui. Proident veniam amet qui reprehenderit duis qui. Nisi culpa sit occaecat ullamco occaecat laborum fugiat ut. Non duis deserunt culpa duis.\r\n", + "Id ipsum eiusmod laboris non est ipsum deserunt labore duis reprehenderit deserunt. Sint tempor fugiat eiusmod nostrud in ut laborum esse in nostrud sit deserunt nostrud reprehenderit. Cupidatat aliqua qui anim consequat eu quis consequat consequat elit ipsum pariatur. Cupidatat in dolore velit quis. Exercitation cillum ullamco ex consectetur commodo tempor incididunt exercitation labore ad dolore. Minim incididunt consequat adipisicing esse eu eu voluptate.\r\n", + "Anim sint eiusmod nisi anim do deserunt voluptate ut cillum eiusmod esse ex reprehenderit laborum. Dolore nulla excepteur duis excepteur. Magna nisi nostrud duis non commodo velit esse ipsum Lorem incididunt. Nulla enim consequat ad aliqua. Incididunt irure culpa nostrud ea aute ex sit non ad esse.\r\n", + "Ullamco nostrud cupidatat adipisicing anim fugiat mollit eu. Et ut eu in nulla consequat. Sunt do pariatur culpa non est.\r\n", + "Pariatur incididunt reprehenderit non qui excepteur cillum exercitation nisi occaecat ad. Lorem aliquip laborum commodo reprehenderit sint. Laboris qui ut veniam magna quis et et ullamco voluptate. Tempor reprehenderit deserunt consequat nisi. Esse duis sint in tempor. Amet aute cupidatat in sint et.\r\n", + "Est officia nisi dolore consequat irure et excepteur. Sit qui elit tempor magna qui cillum anim amet proident exercitation proident. Eu cupidatat laborum consectetur duis ullamco irure nulla. Adipisicing culpa non reprehenderit anim aute.\r\n", + "Eu est laborum culpa velit dolore non sunt. Tempor magna veniam ea sit non qui Lorem qui exercitation aliqua aliqua et excepteur eiusmod. Culpa aute anim proident culpa adipisicing duis tempor elit aliquip elit nulla laboris esse dolore. Sit adipisicing non dolor eiusmod occaecat cupidatat.\r\n", + "Culpa velit eu esse sunt. Laborum irure aliqua reprehenderit velit ipsum fugiat officia dolor ut aute officia deserunt. Ipsum sit quis fugiat nostrud aliqua cupidatat ex pariatur et. Cillum proident est irure nisi dolor aliqua deserunt esse occaecat velit dolor.\r\n", + "Exercitation nulla officia sit eiusmod cillum eu incididunt officia exercitation qui Lorem deserunt. Voluptate Lorem minim commodo laborum esse in duis excepteur do duis aliquip nisi voluptate consectetur. Amet tempor officia enim ex esse minim reprehenderit.\r\n", + "Laboris sint deserunt ad aute incididunt. Anim officia sunt elit qui laborum labore commodo irure non. Mollit adipisicing ullamco do aute nulla eu laborum et quis sint aute adipisicing amet. Aliqua officia irure nostrud duis ex.\r\n", + "Eiusmod ipsum aliqua reprehenderit esse est non aute id veniam eiusmod. Elit consequat ad sit tempor elit eu incididunt quis irure ad. Eu incididunt veniam consequat Lorem nostrud cillum officia ea consequat ad cillum. Non nisi irure cupidatat incididunt pariatur incididunt. Duis velit officia ad cillum qui. Aliquip consequat sint aute nisi cillum. Officia commodo nisi incididunt laborum nisi voluptate aliquip Lorem cupidatat anim consequat sit laboris.\r\n", + "Veniam cupidatat et incididunt mollit do ex voluptate veniam nostrud labore esse. Eiusmod irure sint fugiat esse. Aute irure consectetur ut mollit nulla sint esse. Lorem ut quis ex proident nostrud mollit nostrud ea duis duis in magna anim consectetur.\r\n", + "Irure culpa esse qui do dolor fugiat veniam ad. Elit commodo aute elit magna incididunt tempor pariatur velit irure pariatur cillum et ea ad. Ad consequat ea et ad minim ut sunt qui commodo voluptate. Laboris est aliquip anim reprehenderit eu officia et exercitation. Occaecat laboris cupidatat Lorem ullamco in nostrud commodo ipsum in quis esse ex.\r\n", + "Incididunt officia quis voluptate eiusmod esse nisi ipsum quis commodo. Eiusmod dolore tempor occaecat sit exercitation aliqua minim consequat minim mollit qui ad nisi. Aute quis irure adipisicing veniam nisi nisi velit deserunt incididunt anim nostrud.\r\n", + "Voluptate exercitation exercitation id minim excepteur excepteur mollit. Fugiat aute proident nulla ullamco ea. Nisi ea culpa duis dolore veniam anim tempor officia in dolore exercitation exercitation. Dolore quis cillum adipisicing sunt do nulla esse proident ad sint.\r\n", + "Laborum ut mollit sint commodo nulla laborum deserunt Lorem magna commodo mollit tempor deserunt ut. Qui aliquip commodo ea id. Consectetur dolor fugiat dolor excepteur eiusmod. Eu excepteur ex aute ex ex elit ex esse officia cillum exercitation. Duis ut labore ea nostrud excepteur. Reprehenderit labore aute sunt nisi quis Lorem officia. Ad aliquip cupidatat voluptate exercitation voluptate ad irure magna quis.\r\n", + "Tempor velit veniam sit labore elit minim do elit cillum eiusmod sunt excepteur nisi. Aliquip est deserunt excepteur duis fugiat incididunt veniam fugiat. Pariatur sit irure labore et minim non. Cillum quis aute anim sint laboris laboris ullamco exercitation nostrud. Nulla pariatur id laborum minim nisi est adipisicing irure.\r\n", + "Irure exercitation laboris nostrud in do consectetur ad. Magna aliqua Lorem culpa exercitation sint do culpa incididunt mollit eu exercitation. Elit tempor Lorem dolore enim deserunt. Anim et ullamco sint ullamco mollit cillum officia et. Proident incididunt laboris aliquip laborum sint veniam deserunt eu consequat deserunt voluptate laboris. Anim Lorem non laborum exercitation voluptate. Cupidatat reprehenderit culpa Lorem fugiat enim minim consectetur tempor quis ad reprehenderit laboris irure.\r\n", + "Deserunt elit mollit nostrud occaecat labore reprehenderit laboris ex. Esse reprehenderit adipisicing cillum minim in esse aliquip excepteur ex et nisi cillum quis. Cillum labore ut ex sunt. Occaecat proident et mollit magna consequat irure esse. Dolor do enim esse nisi ad.\r\n", + "Pariatur est anim cillum minim elit magna adipisicing quis tempor proident nisi laboris incididunt cupidatat. Nulla est adipisicing sit adipisicing id nostrud amet qui consequat eiusmod tempor voluptate ad. Adipisicing non magna sit occaecat magna mollit ad ex nulla velit ea pariatur. Irure labore ad ea exercitation ex cillum.\r\n", + "Lorem fugiat eu eu cillum nulla tempor sint. Lorem id officia nulla velit labore ut duis ad tempor non. Excepteur quis aute adipisicing nisi nisi consectetur aliquip enim Lorem id ullamco cillum sint voluptate. Qui aliquip incididunt tempor aliqua voluptate labore reprehenderit. Veniam eiusmod elit occaecat voluptate tempor culpa consectetur ea ut exercitation eiusmod exercitation qui.\r\n", + "Aliqua esse pariatur nulla veniam velit ea. Aliquip consectetur tempor ex magna sit aliquip exercitation veniam. Dolor ullamco minim commodo pariatur. Et amet reprehenderit dolore proident elit tempor eiusmod eu incididunt enim ullamco. Adipisicing id officia incididunt esse dolor sunt cupidatat do deserunt mollit do non. Magna ut officia fugiat adipisicing quis ea cillum laborum dolore ad nostrud magna minim est. Dolor voluptate officia proident enim ea deserunt eu voluptate dolore proident laborum officia ea.\r\n", + "Culpa aute consequat esse fugiat cupidatat minim voluptate voluptate eiusmod irure anim elit. Do eiusmod culpa laboris consequat incididunt minim nostrud eiusmod commodo velit ea ullamco proident. Culpa pariatur magna ut mollit nisi. Ea officia do magna deserunt minim nisi tempor ea deserunt veniam cillum exercitation esse.\r\n", + "Anim ullamco nostrud commodo Lorem. Do sunt laborum exercitation proident proident magna. Lorem officia laborum laborum dolor sunt duis commodo Lorem. Officia aute adipisicing ea cupidatat ea dolore. Aliquip adipisicing pariatur consectetur aliqua sit amet officia reprehenderit laborum culpa. Occaecat Lorem eu nisi do Lorem occaecat enim eiusmod laboris id quis. Ad mollit adipisicing sunt adipisicing esse.\r\n", + "Laborum quis sit adipisicing cupidatat. Veniam Lorem eiusmod esse esse sint nisi labore elit et. Deserunt aliqua mollit ut commodo aliqua non incididunt ipsum reprehenderit consectetur. Eiusmod nulla minim laboris Lorem ea Lorem aute tempor pariatur in sit. Incididunt culpa ut do irure amet irure cupidatat est anim anim culpa occaecat. Est velit consectetur eiusmod veniam reprehenderit officia sunt occaecat eiusmod ut sunt occaecat amet.\r\n", + "Elit minim aute fugiat nulla ex quis. Labore fugiat sint nostrud amet quis culpa excepteur in. Consectetur exercitation cupidatat laborum sit. Aute nisi eu aliqua est deserunt eiusmod commodo dolor id. Mollit laborum esse sint ipsum voluptate reprehenderit velit et. Veniam aliquip enim in veniam Lorem voluptate quis deserunt consequat qui commodo ut excepteur aute.\r\n", + "Dolore deserunt veniam aute nisi labore sunt et voluptate irure nisi anim ea. Magna nisi quis anim mollit nisi est dolor do ex aliquip elit aliquip ipsum minim. Dolore est officia nostrud eiusmod ex laborum ea amet est. Officia culpa non est et tempor consectetur exercitation tempor eiusmod enim. Ea tempor laboris qui amet ex nisi culpa dolore consectetur incididunt sunt sunt. Lorem aliquip incididunt magna do et ullamco ex elit aliqua eiusmod qui. Commodo amet dolor sint incididunt ex veniam non Lorem fugiat.\r\n", + "Officia culpa enim voluptate dolore commodo. Minim commodo aliqua minim ex sint excepteur cupidatat adipisicing eu irure. Anim magna deserunt anim Lorem non.\r\n", + "Cupidatat aliquip nulla excepteur sunt cupidatat cupidatat laborum cupidatat exercitation. Laboris minim ex cupidatat culpa elit. Amet enim reprehenderit aliqua laborum est tempor exercitation cupidatat ex dolore do. Do incididunt labore fugiat commodo consectetur nisi incididunt irure sit culpa sit. Elit aute occaecat qui excepteur velit proident cillum qui aliqua ex do ex. Dolore irure ex excepteur veniam id proident mollit Lorem.\r\n", + "Ad commodo cillum duis deserunt elit officia consectetur veniam eiusmod. Reprehenderit et veniam ad commodo reprehenderit magna elit laboris sunt non quis. Adipisicing dolor aute proident ea magna sunt et proident in consectetur.\r\n", + "Veniam exercitation esse esse veniam est nisi. Minim velit incididunt sint aute dolor anim. Fugiat cupidatat id ad nisi in voluptate dolor culpa eiusmod magna eiusmod amet id. Duis aliquip labore et ex amet amet aliquip laborum eiusmod ipsum. Quis qui ut duis duis. Minim in voluptate reprehenderit aliqua.\r\n", + "Elit ut pariatur dolor veniam ipsum consequat. Voluptate Lorem mollit et esse dolore mollit Lorem ad. Elit nostrud eu Lorem labore mollit minim cupidatat officia quis minim dolore incididunt. In cillum aute cillum ut.\r\n", + "Commodo laborum deserunt ut cupidatat pariatur ullamco in esse anim exercitation cillum duis. Consectetur incididunt sit esse Lorem in aute. Eiusmod mollit Lorem consequat minim reprehenderit laborum enim excepteur irure nisi elit. Laborum esse proident aute aute proident adipisicing laborum. Pariatur tempor duis incididunt qui velit pariatur ut officia ea mollit labore dolore. Cillum pariatur minim ullamco sunt incididunt culpa id ullamco exercitation consectetur. Ea exercitation consequat reprehenderit ut ullamco velit eu ad velit magna excepteur eiusmod.\r\n", + "Eu deserunt magna laboris laborum laborum in consequat dolore. Officia proident consectetur proident do occaecat minim pariatur officia ipsum sit non velit officia cillum. Laborum excepteur labore eu minim eiusmod. Sit anim dolore cillum ad do minim culpa sit est ad.\r\n", + "Cupidatat dolor nostrud Lorem sint consequat quis. Quis labore sint incididunt officia tempor. Fugiat nostrud in elit reprehenderit dolor. Nisi sit enim officia minim est adipisicing nulla aute labore nulla nostrud cupidatat est. Deserunt dolore qui irure Lorem esse voluptate velit qui nostrud.\r\n", + "Fugiat Lorem amet nulla nisi qui amet laboris enim cillum. Dolore occaecat exercitation id labore velit do commodo ut cupidatat laborum velit fugiat mollit. Ut et aliqua pariatur occaecat. Lorem occaecat dolore quis esse enim cupidatat exercitation ut tempor sit laboris fugiat adipisicing. Est tempor ex irure consectetur ipsum magna labore. Lorem non quis qui minim nisi magna amet aliquip ex cillum fugiat tempor.\r\n", + "Aliquip eiusmod laborum ipsum deserunt velit esse do magna excepteur consectetur exercitation sit. Minim ullamco reprehenderit commodo nostrud exercitation id irure ex qui ullamco sit esse laboris. Nulla cillum non minim qui cillum nisi aute proident. Dolor anim culpa elit quis excepteur aliqua eiusmod. Elit ea est excepteur consectetur sunt eiusmod enim id commodo irure amet et pariatur laboris. Voluptate magna ad magna dolore cillum cillum irure laboris ipsum officia id Lorem veniam.\r\n", + "Esse sunt elit est aliquip cupidatat commodo deserunt. Deserunt pariatur ipsum qui ad esse esse magna qui cillum laborum. Exercitation veniam pariatur elit amet enim.\r\n", + "Esse quis in id elit nulla occaecat incididunt. Et amet Lorem mollit in veniam do. Velit mollit Lorem consequat commodo Lorem aliquip cupidatat. Minim consequat nostrud nulla in nostrud.\r\n", + "Cillum nulla et eu est nostrud quis elit cupidatat dolor enim excepteur exercitation nisi voluptate. Nulla dolore non ex velit et qui tempor proident id deserunt nisi eu. Tempor ad Lorem ipsum reprehenderit in anim. Anim dolore ullamco enim deserunt quis ex id exercitation velit. Magna exercitation fugiat mollit pariatur ipsum ex consectetur nostrud. Id dolore officia nostrud excepteur laborum. Magna incididunt elit ipsum pariatur adipisicing enim duis est qui commodo velit aute.\r\n", + "Quis esse ex qui nisi dolor. Ullamco laborum dolor esse laboris eiusmod ea magna laboris ea esse ut. Dolore ipsum pariatur veniam sint mollit. Lorem ea proident fugiat ullamco ut nisi culpa eu exercitation exercitation aliquip veniam laborum consectetur.\r\n", + "Pariatur veniam laboris sit aliquip pariatur tempor aute sunt id et ut. Laboris excepteur eiusmod nisi qui quis elit enim ut cupidatat. Et et laborum in fugiat veniam consectetur ipsum laboris duis excepteur ullamco aliqua dolor Lorem. Aliqua ex amet sint anim cupidatat nisi ipsum anim et sunt deserunt. Occaecat culpa ut tempor cillum pariatur ex tempor.\r\n", + "Dolor deserunt eiusmod magna do officia voluptate excepteur est cupidatat. Veniam qui cupidatat amet anim est qui consectetur sit commodo commodo ea ad. Enim ad adipisicing qui nostrud. Non nulla esse ullamco nulla et ex.\r\n", + "Id ullamco ea consectetur est incididunt deserunt et esse. Elit nostrud voluptate eiusmod ut. Excepteur adipisicing qui cupidatat consequat labore id. Qui dolor aliqua do dolore do cupidatat labore ex consectetur ea sit cillum. Sint veniam eiusmod in consectetur consequat fugiat et mollit ut fugiat esse dolor adipisicing.\r\n", + "Ea magna proident labore duis pariatur. Esse cillum aliquip dolor duis fugiat ea ex officia ea irure. Sint elit nisi pariatur sunt nostrud exercitation ullamco culpa magna do.\r\n", + "Minim aliqua voluptate dolor consequat sint tempor deserunt amet magna excepteur. Irure do voluptate magna velit. Nostrud in reprehenderit magna officia nostrud. Cupidatat nulla irure laboris non fugiat ex ex est cupidatat excepteur officia aute velit duis. Sit voluptate id ea exercitation deserunt culpa voluptate nostrud est adipisicing incididunt. Amet proident laborum commodo magna ipsum quis.\r\n", + "Ipsum consectetur consectetur excepteur tempor eiusmod ea fugiat aute velit magna in officia sunt. Sit ut sunt dolore cupidatat dolor adipisicing. Veniam nisi adipisicing esse reprehenderit amet aliqua voluptate ex commodo occaecat est voluptate mollit sunt. Pariatur aliqua qui qui in dolor. Fugiat reprehenderit sit nostrud do sint esse. Tempor sit irure adipisicing ea pariatur duis est sit est incididunt laboris quis do. Et voluptate anim minim aliquip excepteur consequat nisi anim pariatur aliquip ut ipsum dolor magna.\r\n", + "Cillum sit labore excepteur magna id aliqua exercitation consequat laborum Lorem id pariatur nostrud. Lorem qui est labore sint cupidatat sint excepteur nulla in eu aliqua et. Adipisicing velit do enim occaecat laboris quis excepteur ipsum dolor occaecat Lorem dolore id exercitation.\r\n", + "Incididunt in laborum reprehenderit eiusmod irure ex. Elit duis consequat minim magna. Esse consectetur aliquip cillum excepteur excepteur fugiat. Sint tempor consequat minim reprehenderit consectetur adipisicing dolor id Lorem elit non. Occaecat esse quis mollit ea et sint aute fugiat qui tempor. Adipisicing tempor duis non dolore irure elit deserunt qui do.\r\n", + "Labore fugiat eiusmod sint laborum sit duis occaecat. Magna in laborum non cillum excepteur nostrud sit proident pariatur voluptate voluptate adipisicing exercitation occaecat. Ad non dolor aute ex sint do do minim exercitation veniam laborum irure magna ea. Magna do non quis sit consequat Lorem aliquip.\r\n", + "Velit anim do laborum laboris laborum Lorem. Sunt do Lorem amet ipsum est sint velit sit do voluptate mollit veniam enim. Commodo do deserunt in pariatur ut elit sint elit deserunt ea. Ad dolor anim consequat aliquip ut mollit nostrud tempor sunt mollit elit. Reprehenderit laboris labore excepteur occaecat veniam adipisicing cupidatat esse. Ad enim aliquip ea minim excepteur magna. Sint velit veniam pariatur qui dolor est adipisicing ex laboris.\r\n", + "Ea cupidatat ex nulla in sunt est sit dolor enim ad. Eu tempor consequat cupidatat consequat ex incididunt sint culpa. Est Lorem Lorem non cupidatat sunt ut aliqua non nostrud do ullamco. Reprehenderit ad ad nulla nostrud do nulla in. Ipsum adipisicing commodo mollit ipsum exercitation. Aliqua ea anim anim est elit. Ea incididunt consequat minim ad sunt eu cillum.\r\n", + "Tempor quis excepteur eiusmod cupidatat ipsum occaecat id et occaecat. Eiusmod magna aliquip excepteur id amet elit. Ullamco dolore amet anim dolor enim ea magna magna elit. Occaecat magna pariatur in deserunt consectetur officia aliquip ullamco ex aute anim. Minim laborum eu sit elit officia esse do irure pariatur tempor et reprehenderit ullamco labore.\r\n", + "Sit tempor eu minim dolore velit pariatur magna duis reprehenderit ea nulla in. Amet est do consectetur commodo do adipisicing adipisicing in amet. Cillum id ut commodo do pariatur duis aliqua nisi sint ad irure officia reprehenderit. Mollit labore id enim fugiat ullamco irure mollit cupidatat. Quis nisi amet labore eu dolor occaecat commodo aliqua laboris deserunt excepteur deserunt officia. Aliqua non ut sit ad. Laborum veniam ad velit minim dolore ea id magna dolor qui in.\r\n", + "Dolore nostrud ipsum aliqua pariatur id reprehenderit enim ad eiusmod qui. Deserunt anim commodo pariatur excepteur velit eu irure nulla ex labore ipsum aliqua minim aute. Id consequat amet tempor aliquip ex elit adipisicing est do. Eu enim Lorem consectetur minim id irure nulla culpa. Consectetur do consequat aute tempor anim. Qui ad non elit dolor est adipisicing nisi amet cillum sunt quis anim laboris incididunt. Incididunt proident adipisicing labore Lorem.\r\n", + "Et reprehenderit ea officia veniam. Aliquip ullamco consequat elit nisi magna mollit id elit. Amet amet sint velit labore ad nisi. Consectetur tempor id dolor aliqua esse deserunt amet. Qui laborum enim proident voluptate aute eu aute aute sit sit incididunt eu. Sunt ullamco nisi nostrud labore commodo non consectetur quis do duis minim irure. Tempor sint dolor sint aliquip dolore nostrud fugiat.\r\n", + "Aute ullamco quis nisi ut excepteur nostrud duis elit. Veniam ex ad incididunt veniam voluptate. Commodo dolore ullamco sit sint adipisicing proident amet aute duis deserunt.\r\n", + "Labore velit eu cillum nisi. Laboris do cupidatat et non duis cillum. Ullamco dolor tempor cupidatat voluptate laborum ullamco ea duis.\r\n", + "Deserunt consequat aliqua duis aliquip nostrud nostrud dolore nisi. Culpa do sint laborum consectetur ipsum quis laborum laborum pariatur eiusmod. Consectetur laboris ad ad ut quis. Ullamco laboris qui velit id laborum voluptate qui aute nostrud aliquip ea.\r\n", + "Ad cillum anim ex est consectetur mollit id in. Non enim aliquip consequat qui deserunt commodo cillum ad laborum fugiat. Dolor deserunt amet laborum tempor adipisicing voluptate dolor pariatur dolor cillum. Eu mollit ex sunt officia veniam qui est sunt proident. Non aliqua qui elit eu cupidatat ex enim ex proident. Lorem sit minim ullamco officia cupidatat duis minim. Exercitation laborum deserunt voluptate culpa tempor quis nulla id pariatur.\r\n", + "Nostrud quis consectetur ut aliqua excepteur elit consectetur occaecat. Occaecat voluptate Lorem pariatur consequat ullamco fugiat minim. Anim voluptate eu eu cillum tempor dolore aliquip aliqua. Fugiat incididunt ut tempor amet minim. Voluptate nostrud minim pariatur non excepteur ullamco.\r\n", + "Dolore nulla velit officia exercitation irure laboris incididunt anim in laborum in fugiat ut proident. Fugiat aute id consequat fugiat officia ut. Labore sint amet proident amet sint nisi laboris amet id ullamco culpa quis consequat proident. Magna do fugiat veniam dolore elit irure minim. Esse ullamco excepteur labore tempor labore fugiat dolore nisi cupidatat irure dolor pariatur. Magna excepteur laboris nisi eiusmod sit pariatur mollit.\r\n", + "In enim aliquip officia ea ad exercitation cillum culpa occaecat dolore Lorem. Irure cillum commodo adipisicing sunt pariatur ea duis fugiat exercitation laboris culpa ullamco aute. Ut voluptate exercitation qui dolor. Irure et duis elit consequat deserunt proident.\r\n", + "Officia ea Lorem sunt culpa id et tempor excepteur enim deserunt proident. Dolore aliquip dolor laboris cillum proident velit. Et culpa occaecat exercitation cupidatat irure sint adipisicing excepteur pariatur incididunt ad occaecat. Qui proident ipsum cillum minim. Quis ut culpa irure aliqua minim fugiat. In voluptate cupidatat fugiat est laborum dolor esse in pariatur voluptate.\r\n", + "Voluptate enim ipsum officia aute ea adipisicing nisi ut ex do aliquip amet. Reprehenderit enim voluptate tempor ex adipisicing culpa. Culpa occaecat voluptate dolor mollit ipsum exercitation labore et tempor sit ea consectetur aliqua. Elit elit sit minim ea ea commodo do tempor cupidatat irure dolore. Occaecat esse adipisicing anim eiusmod commodo fugiat mollit amet. Incididunt tempor tempor qui occaecat cupidatat in.\r\n", + "Ut qui anim velit enim aliquip do ut nulla labore. Mollit ut commodo ut eiusmod consectetur laboris aliqua qui voluptate culpa fugiat incididunt elit. Lorem ullamco esse elit elit. Labore amet incididunt ea nulla aliquip eiusmod. Sit nulla est voluptate officia ipsum aute aute cillum tempor deserunt. Laboris commodo eiusmod labore sunt aute excepteur ea consectetur reprehenderit veniam nisi. Culpa nisi sint sunt sint tempor laboris dolore cupidatat.\r\n", + "Duis cillum qui nisi duis amet velit ad cillum ut elit aute sint ad. Amet laboris pariatur excepteur ipsum Lorem aliqua veniam Lorem quis mollit cupidatat aliqua exercitation. Pariatur ex ullamco sit commodo cillum eiusmod ut proident elit cillum. Commodo ut ipsum excepteur occaecat sint elit consequat ex dolor adipisicing consectetur id ut ad. Velit sit eiusmod est esse tempor incididunt consectetur eiusmod duis commodo veniam.\r\n", + "Ut sunt qui officia anim laboris exercitation Lorem quis laborum do eiusmod officia. Enim consectetur occaecat fugiat cillum cillum. Dolore dolore nostrud in commodo fugiat mollit consequat occaecat non et et elit ullamco. Sit voluptate minim ut est culpa velit nulla fugiat reprehenderit eu aliquip adipisicing labore. Sit minim minim do dolor dolor. Lorem Lorem labore exercitation magna veniam eiusmod do.\r\n", + "Fugiat dolor adipisicing quis aliquip aute dolore. Qui proident anim elit veniam ex aliquip eiusmod ipsum sunt pariatur est. Non fugiat duis do est officia adipisicing.\r\n", + "Nulla deserunt do laboris cupidatat veniam do consectetur ipsum elit veniam in mollit eu. Ea in consequat cupidatat laboris sint fugiat irure. In commodo esse reprehenderit deserunt minim velit ullamco enim eu cupidatat tempor ex. Ullamco in non id culpa amet occaecat culpa nostrud id. Non occaecat culpa magna incididunt.\r\n", + "Enim laboris ex mollit reprehenderit eiusmod exercitation magna. Exercitation Lorem ex mollit non non culpa labore enim. Adipisicing labore dolore incididunt do amet aliquip excepteur ad et nostrud officia aute veniam voluptate. Fugiat enim eiusmod Lorem esse. Minim ullamco commodo consequat ex commodo aliqua eu nulla eu. Veniam non enim nulla ut Lorem nostrud minim sint duis.\r\n", + "Enim duis consectetur in ullamco cillum veniam nulla amet. Exercitation nisi sunt sunt duis in culpa nisi magna ex id ipsum laboris reprehenderit qui. Officia pariatur qui ex fugiat veniam et sunt sit nostrud. Veniam ullamco tempor fugiat minim Lorem proident velit in eiusmod elit. Enim minim excepteur aute aliquip ex magna commodo dolore qui et labore. Proident eu aliquip cillum dolor. Nostrud ipsum ut irure consequat fugiat nulla proident occaecat laborum.\r\n", + "Amet duis eiusmod sunt adipisicing esse ex nostrud consectetur voluptate cillum. Ipsum occaecat sit et anim velit irure ea incididunt cupidatat ullamco in nisi quis. Esse officia ipsum commodo qui quis qui do. Commodo aliquip amet aute sit sit ut cupidatat elit nostrud.\r\n", + "Laboris laboris sit mollit cillum nulla deserunt commodo culpa est commodo anim id anim sit. Officia id consectetur velit incididunt est dolor sunt ipsum magna aliqua consectetur. Eiusmod pariatur minim deserunt cupidatat veniam Lorem aliquip sunt proident eu Lorem sit dolor fugiat. Proident qui ut ex in incididunt nulla nulla dolor ex laboris ea ad.\r\n", + "Ex incididunt enim labore nulla cupidatat elit. Quis ut incididunt incididunt non irure commodo do mollit cillum anim excepteur. Qui consequat laborum dolore elit tempor aute ut nulla pariatur eu ullamco veniam. Nisi non velit labore in commodo excepteur culpa nulla tempor cillum. Ipsum qui sit sint reprehenderit ut labore incididunt dolor aliquip sunt. Reprehenderit occaecat tempor nisi laborum.\r\n", + "Lorem officia ullamco eu occaecat in magna eiusmod consectetur nisi aliqua mollit esse. Ullamco ex aute nostrud pariatur do enim cillum sint do fugiat nostrud culpa tempor. Do aliquip excepteur nostrud culpa eu pariatur eiusmod cillum excepteur do. Est sunt non quis cillum voluptate ex.\r\n", + "Deserunt consectetur tempor irure mollit qui tempor et. Labore enim eu irure laboris in. Nisi in tempor ex occaecat amet cupidatat laboris occaecat amet minim ut magna incididunt id. Consequat cillum laborum commodo mollit. Et magna culpa sunt dolore consequat laboris et sit. Deserunt qui voluptate excepteur dolor. Eu qui amet est proident.\r\n", + "Eu elit minim eiusmod occaecat eu nostrud dolor qui ut elit. Sunt dolore proident ea eu do eiusmod fugiat incididunt pariatur duis amet Lorem nisi ut. Adipisicing quis veniam cupidatat Lorem sint culpa sunt veniam sint. Excepteur eu exercitation est magna pariatur veniam dolore qui fugiat labore proident eiusmod cillum. Commodo reprehenderit elit proident duis sint magna.\r\n", + "Ut aliquip pariatur deserunt nostrud commodo ad proident est exercitation. Sit minim do ea enim sint officia nisi incididunt laborum. Ex amet duis commodo fugiat. Ut aute tempor deserunt irure occaecat aliquip voluptate cillum aute elit qui nostrud.\r\n", + "Irure et quis consectetur sit est do sunt aliquip eu. Cupidatat pariatur consequat dolore consectetur. Adipisicing magna velit mollit occaecat do id. Nisi pariatur cupidatat cillum incididunt excepteur consectetur excepteur do laborum deserunt irure pariatur cillum.\r\n", + "Adipisicing esse incididunt cillum est irure consequat irure ad aute voluptate. Incididunt do occaecat nostrud do ipsum pariatur Lorem qui laboris et pariatur. Est exercitation dolor culpa ad velit ut et.\r\n", + "Sit eiusmod id enim ad ex dolor pariatur do. Ullamco occaecat quis dolor minim non elit labore amet est. Commodo velit eu nulla eiusmod ullamco. Incididunt anim pariatur aute eiusmod veniam tempor enim officia elit id. Elit Lorem est commodo dolore nostrud. Labore et consectetur do exercitation veniam laboris incididunt aliqua proident dolore ea officia cupidatat. Velit laboris aliquip deserunt labore commodo.\r\n", + "Proident nostrud labore eu nostrud. Excepteur ut in velit labore ea proident labore ea sint cillum. Incididunt ipsum consectetur officia irure sit pariatur veniam id velit officia mollit. Adipisicing magna voluptate velit excepteur enim consectetur incididunt voluptate tempor occaecat fugiat velit excepteur labore. Do do incididunt qui nisi voluptate enim. Laboris aute sit voluptate cillum pariatur minim excepteur ullamco mollit deserunt.\r\n", + "Excepteur laborum adipisicing nisi elit fugiat tempor. Elit laboris qui enim labore duis. Proident tempor in consectetur proident excepteur do ex laboris sit.\r\n", + "Dolore do ea incididunt do duis dolore eu labore nisi cupidatat voluptate amet incididunt minim. Nulla pariatur mollit cupidatat adipisicing nulla et. Dolor aliquip in ex magna excepteur. Nulla consequat minim consequat ullamco dolor laboris ullamco eu reprehenderit duis nostrud pariatur.\r\n", + "Id nisi labore duis qui. Incididunt laboris tempor aute do sit. Occaecat excepteur est mollit ea in mollit ullamco est amet reprehenderit.\r\n", + "Aute labore ipsum velit non voluptate eiusmod et reprehenderit cupidatat occaecat. Lorem tempor tempor consectetur exercitation qui nostrud sunt cillum quis ut non dolore. Reprehenderit consequat reprehenderit laborum qui pariatur anim et officia est cupidatat enim velit velit.\r\n", + "Commodo ex et fugiat cupidatat non adipisicing commodo. Minim ad dolore fugiat mollit cupidatat aliqua sunt dolor sit. Labore esse labore velit aute enim. Nulla duis incididunt est aliquip consectetur elit qui incididunt minim minim labore amet sit cillum.\r\n" +] \ No newline at end of file diff --git a/src/comm/ros_bridge/rapidjson/bin/types/readme.txt b/src/comm/ros_bridge/rapidjson/bin/types/readme.txt new file mode 100644 index 000000000..da1dae675 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/bin/types/readme.txt @@ -0,0 +1 @@ +Test data obtained from https://github.com/xpol/lua-rapidjson/tree/master/performance diff --git a/src/comm/ros_bridge/rapidjson/contrib/natvis/LICENSE b/src/comm/ros_bridge/rapidjson/contrib/natvis/LICENSE new file mode 100644 index 000000000..f57da96cf --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/contrib/natvis/LICENSE @@ -0,0 +1,45 @@ +The MIT License (MIT) + +Copyright (c) 2017 Bart Muzzin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Derived from: + +The MIT License (MIT) + +Copyright (c) 2015 mojmir svoboda + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/comm/ros_bridge/rapidjson/contrib/natvis/README.md b/src/comm/ros_bridge/rapidjson/contrib/natvis/README.md new file mode 100644 index 000000000..9685c7f7c --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/contrib/natvis/README.md @@ -0,0 +1,7 @@ +# rapidjson.natvis + +This file can be used as a [Visual Studio Visualizer](https://docs.microsoft.com/en-gb/visualstudio/debugger/create-custom-views-of-native-objects) to aid in visualizing rapidjson structures within the Visual Studio debugger. Natvis visualizers are supported in Visual Studio 2012 and later. To install, copy the file into this directory: + +`%USERPROFILE%\Documents\Visual Studio 2012\Visualizers` + +Each version of Visual Studio has a similar directory, it must be copied into each directory to be used with that particular version. In Visual Studio 2015 and later, this can be done without restarting Visual Studio (a new debugging session must be started). diff --git a/src/comm/ros_bridge/rapidjson/contrib/natvis/rapidjson.natvis b/src/comm/ros_bridge/rapidjson/contrib/natvis/rapidjson.natvis new file mode 100644 index 000000000..a804b7bf6 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/contrib/natvis/rapidjson.natvis @@ -0,0 +1,38 @@ + + + + + null + true + false + {data_.ss.str} + {(const char*)((size_t)data_.s.str & 0x0000FFFFFFFFFFFF)} + {data_.n.i.i} + {data_.n.u.u} + {data_.n.i64} + {data_.n.u64} + {data_.n.d} + Object members={data_.o.size} + Array members={data_.a.size} + + data_.o.size + data_.o.capacity + + data_.o.size + + (rapidjson::GenericMember<$T1,$T2>*)(((size_t)data_.o.members) & 0x0000FFFFFFFFFFFF) + + + data_.a.size + data_.a.capacity + + data_.a.size + + (rapidjson::GenericValue<$T1,$T2>*)(((size_t)data_.a.elements) & 0x0000FFFFFFFFFFFF) + + + + + + + diff --git a/src/comm/ros_bridge/rapidjson/doc/CMakeLists.txt b/src/comm/ros_bridge/rapidjson/doc/CMakeLists.txt new file mode 100644 index 000000000..c5345ba69 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/doc/CMakeLists.txt @@ -0,0 +1,27 @@ +find_package(Doxygen) + +IF(NOT DOXYGEN_FOUND) + MESSAGE(STATUS "No Doxygen found. Documentation won't be built") +ELSE() + file(GLOB SOURCES ${CMAKE_CURRENT_LIST_DIR}/../include/*) + file(GLOB MARKDOWN_DOC ${CMAKE_CURRENT_LIST_DIR}/../doc/*.md) + list(APPEND MARKDOWN_DOC ${CMAKE_CURRENT_LIST_DIR}/../readme.md) + + CONFIGURE_FILE(Doxyfile.in Doxyfile @ONLY) + CONFIGURE_FILE(Doxyfile.zh-cn.in Doxyfile.zh-cn @ONLY) + + file(GLOB DOXYFILES ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile*) + + add_custom_command(OUTPUT html + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.zh-cn + COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/html + DEPENDS ${MARKDOWN_DOC} ${SOURCES} ${DOXYFILES} + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../ + ) + + add_custom_target(doc ALL DEPENDS html) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html + DESTINATION ${DOC_INSTALL_DIR} + COMPONENT doc) +ENDIF() diff --git a/src/comm/ros_bridge/rapidjson/doc/Doxyfile.in b/src/comm/ros_bridge/rapidjson/doc/Doxyfile.in new file mode 100644 index 000000000..6e79f9371 --- /dev/null +++ b/src/comm/ros_bridge/rapidjson/doc/Doxyfile.in @@ -0,0 +1,2369 @@ +# Doxyfile 1.8.7 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = RapidJSON + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "A fast JSON parser/generator for C++ with both SAX/DOM style API" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = YES + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = $(RAPIDJSON_SECTIONS) + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = readme.md \ + CHANGELOG.md \ + include/rapidjson/rapidjson.h \ + include/ \ + doc/features.md \ + doc/tutorial.md \ + doc/pointer.md \ + doc/stream.md \ + doc/encoding.md \ + doc/dom.md \ + doc/sax.md \ + doc/schema.md \ + doc/performance.md \ + doc/internals.md \ + doc/faq.md + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.inc \ + *.md + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = ./include/rapidjson/msinttypes/ + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = internal + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = ./doc + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = readme.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# compiled with the --with-libclang option. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = NO + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = ./doc/misc/header.html + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = ./doc/misc/footer.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = ./doc/misc/doxygenextra.css + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = YES + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /