pax_global_header00006660000000000000000000000064131535616260014522gustar00rootroot0000000000000052 comment=3a7de454959dca5d07eeca62d01f81560d61c378 measurement-kit-0.7.1/000077500000000000000000000000001315356162600146415ustar00rootroot00000000000000measurement-kit-0.7.1/.clang-format000066400000000000000000000001051315356162600172100ustar00rootroot00000000000000--- BasedOnStyle: LLVM IndentWidth: 4 ContinuationIndentWidth: 6 --- measurement-kit-0.7.1/.gitignore000066400000000000000000000055271315356162600166420ustar00rootroot00000000000000*.a *.app *.dll *.dylib *.dylib.* *.exe *.gcda *.gcno *.gcov *.ko *.la *.lib *.lo *.log *.o *.o-* *.out *.pyc *.so *.so.* *.swp *.trs .DS_Store .deps .dirstamp .idea .libs .vagrant /*.njson /GeoIP.dat /GeoIPASNum.dat /GeoLiteCity.dat /build/android/jni/conf /build/android/jni/spec /citizenlab-test-lists.*.csv /example/common/fapply /example/common/fcompose /example/dns/ping /example/dns/query /example/http/request /example/libevent/discard /example/libevent/listen /example/mlabns/query /example/net/connect /example/net/transport /example/nettests/multithread /example/nettests/simple /example/ooni/oonireport /example/ooni/ooniresources /example/ooni/oorchestrate /include.am /include/measurement_kit/*.hpp /include/measurement_kit/common/git_version.hpp /maxmind-geoip.*.dat* /measurement_kit /test-driver /test/common/continuation /test/common/delegate /test/common/encoding /test/common/error /test/common/error_or /test/common/every /test/common/fapply /test/common/fcar /test/common/fcdr /test/common/fcompose /test/common/fmap /test/common/freverse /test/common/json /test/common/locked /test/common/logger /test/common/maybe /test/common/parallel /test/common/range /test/common/sandbox /test/common/settings /test/common/utils /test/common/var /test/common/version /test/common/worker /test/dns/ping /test/dns/query /test/dns/query_class /test/dns/query_type /test/dns/system_resolver /test/http/headers /test/http/parse_url /test/http/request /test/http/response_parser /test/libevent/connection /test/libevent/dns_error /test/libevent/poller /test/mlabns/mlabns /test/ndt/measure_speed /test/ndt/messages /test/ndt/protocol /test/ndt/run /test/ndt/test_c2s /test/ndt/test_meta /test/ndt/test_s2c /test/net/buffer /test/net/builtin_ca_bundle /test/net/connect /test/net/emitter /test/net/evbuffer /test/net/libssl /test/net/socks5 /test/net/transport /test/net/utils /test/nettests/dash /test/nettests/dns_injection /test/nettests/http_header_field_manipulation /test/nettests/http_invalid_request_line /test/nettests/meek_fronted_requests /test/nettests/multi_ndt /test/nettests/ndt /test/nettests/runnable /test/nettests/runner /test/nettests/tcp_connect /test/nettests/utils /test/nettests/web_connectivity /test/ooni/bouncer /test/ooni/collector_client /test/ooni/orchestrate /test/ooni/resources /test/ooni/templates /test/ooni/utils /test/report/entry /test/report/file_reporter /test/report/report /test/traceroute/android /tmp /tor-bridges.tor-bridges-ip-port.csv Makefile Makefile.in __venv__ aclocal.m4 autom4te.cache/ builtin/ compile config.guess config.h config.h.in config.h.in~ config.log config.status config.sub configure depcomp install-sh libtool ltmain.sh m4/*.m4 missing node_modules/ orchestrator_dummy.json orchestrator_secrets.json orchestrator_secrets_*.json site src/libmeasurement_kit/ext/Catch/ src/libmeasurement_kit/ext/http-parser/ stamp-h1 third_party/ xx measurement-kit-0.7.1/.gitlab-ci.yml000066400000000000000000000003471315356162600173010ustar00rootroot00000000000000valgrind-gcc: image: ubuntu:yakkety script: ./build/ci/gitlab valgrind-gcc only: - master - stable valgrind-clang: image: ubuntu:yakkety script: ./build/ci/gitlab valgrind-clang only: - master - stable measurement-kit-0.7.1/.travis.yml000066400000000000000000000006361315356162600167570ustar00rootroot00000000000000language: cpp script: - ./build/ci/travis matrix: include: - sudo: required env: DOCKER_SPEC=valgrind-clang pkg_make_flags="V=0 -j3" services: - docker - sudo: required env: DOCKER_SPEC=valgrind-gcc pkg_make_flags="V=0 -j3" services: - docker - sudo: required env: DOCKER_SPEC=coveralls pkg_make_flags="V=0 -j3" services: - docker measurement-kit-0.7.1/AUTHORS000066400000000000000000000003311315356162600157060ustar00rootroot00000000000000Main authors: Simone Basso Arturo Filastò Contributors (in alphabetical order): Davide Allavena Carmine D'Amico Leonid Evdokimov Joe Landers Antonio Langiu Lorenzo Primiterra Alessandro Quaranta measurement-kit-0.7.1/BUGS000066400000000000000000000010521315356162600153220ustar00rootroot000000000000001. As find out in commit 08c5d97550527, the python generator gen_python should implement the get_foo() methods in a different way. In fact, if the object to return has been passed to the constructor as a parameter, they should return this object, instead of calling the wrapper function. [FIXED] 2. The Connection module, when receiving the EOF, closes the connection, even if there is still something to write. This file is now historical. Please, see and use GitHub issues: https://github.com/measurement-kit/measurement-kit/issues measurement-kit-0.7.1/CMakeLists.txt000066400000000000000000000123311315356162600174010ustar00rootroot00000000000000# Part of measurement-kit . # Measurement-kit is free software. See AUTHORS and LICENSE for more # information on the copying conditions. cmake_minimum_required(VERSION 3.6) # Definitions: set(MK_GEOIP "${MK_GEOIP}" CACHE PATH "Path where geoip is installed") set(MK_LIBEVENT "${MK_LIBEVENT}" CACHE PATH "Path where libevent is installed") set(MK_OPENSSL "${MK_OPENSSL}" CACHE PATH "Path where openssl is installed") # Compiler: set(CMAKE_CXX_STANDARD 14) set(MK_UNIX_CFLAGS "-Wall -Wextra -pedantic -I${CMAKE_SOURCE_DIR}/include") set(MK_UNIX_CXXFLAGS "-Wall -Wextra -pedantic -I${CMAKE_SOURCE_DIR}/include") add_definitions(-DENABLE_INTEGRATION_TESTS) if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MK_UNIX_CXXFLAGS} -Wmissing-prototypes") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MK_UNIX_CXXFLAGS}") endif() if("${CMAKE_C_COMPILER_ID}" MATCHES "Clang") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MK_UNIX_CFLAGS} -Wmissing-prototypes") elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MK_UNIX_CFLAGS}") endif() # Set target include directories and link libraries: if(UNIX) if(NOT ("${MK_GEOIP}" STREQUAL "")) list(APPEND MK_INCLUDE_DIRS "${MK_GEOIP}/include") list(APPEND MK_LINK_DIRS "${MK_GEOIP}/lib") endif() if(NOT ("${MK_LIBEVENT}" STREQUAL "")) list(APPEND MK_INCLUDE_DIRS "${MK_LIBEVENT}/include") list(APPEND MK_LINK_DIRS "${MK_LIBEVENT}/lib") endif() if(NOT ("${MK_OPENSSL}" STREQUAL "")) list(APPEND MK_INCLUDE_DIRS "${MK_OPENSSL}/include") list(APPEND MK_LINK_DIRS "${MK_OPENSSL}/lib") endif() endif() # Check dependencies: set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) include(CheckIncludeFiles) include(CheckFunctionExists) include(CheckLibraryExists) if(UNIX) # libc CHECK_FUNCTION_EXISTS(err HAVE_ERR) CHECK_FUNCTION_EXISTS(err HAVE_ERR) CHECK_FUNCTION_EXISTS(warn HAVE_WARN) CHECK_FUNCTION_EXISTS(warnx HAVE_WARNX) CHECK_FUNCTION_EXISTS(getopt HAVE_GETOPT) CHECK_FUNCTION_EXISTS(getopt_long HAVE_GETOPT_LONG) CHECK_FUNCTION_EXISTS(getopt_long_only HAVE_GETOPT_LONG_ONLY) CHECK_FUNCTION_EXISTS(gmtime_r HAVE_GMTIME_R) CHECK_FUNCTION_EXISTS(strtonum HAVE_STRTONUM) # geoip set(CMAKE_REQUIRED_INCLUDES "${MK_INCLUDE_DIRS}") CHECK_INCLUDE_FILES(GeoIP.h HAVE_GEOIP_H) CHECK_LIBRARY_EXISTS(GeoIP GeoIP_open "${MK_GEOIP}/lib" HAVE_LIBGEOIP) set(CMAKE_REQUIRED_INCLUDES "") if (NOT HAVE_GEOIP_H OR NOT HAVE_LIBGEOIP) message(FATAL_ERROR "geoip missing; Use -DMK_GEOIP to specify where it is installed (e.g. -DMK_GEOIP=/usr/local if it is installed under /usr/local)") endif() # openssl set(CMAKE_REQUIRED_INCLUDES "${MK_INCLUDE_DIRS}") CHECK_INCLUDE_FILES(openssl/rsa.h HAVE_OPENSSL_RSA_H) CHECK_LIBRARY_EXISTS(crypto RSA_new "${MK_OPENSSL}/lib" HAVE_LIBCRYPTO) CHECK_INCLUDE_FILES(openssl/ssl.h HAVE_OPENSSL_SSL_H) CHECK_LIBRARY_EXISTS(ssl SSL_new "${MK_OPENSSL}/lib" HAVE_LIBSSL) set(CMAKE_REQUIRED_INCLUDES "") if (NOT HAVE_OPENSSL_RSA_H OR NOT HAVE_LIBSSL) message(FATAL_ERROR "openssl/libressl missing; Use -DMK_OPENSSL to specify where it is installed (e.g. -DMK_OPENSSL=/usr/local if it is installed under /usr/local)") endif() # libevent set(CMAKE_REQUIRED_INCLUDES "${MK_INCLUDE_DIRS}") CHECK_INCLUDE_FILES(event2/event.h HAVE_EVENT2_EVENT_H) CHECK_LIBRARY_EXISTS(event event_new "${MK_LIBEVENT}/lib" HAVE_LIBEVENT) set(CMAKE_REQUIRED_INCLUDES "") if (NOT HAVE_EVENT2_EVENT_H OR NOT HAVE_LIBEVENT) message(FATAL_ERROR "libevent missing; Use -DMK_LIBEVENT to specify where it is installed (e.g. -DMK_LIBEVENT=/usr/local if it is installed under /usr/local)") endif() # libresolv (required by `./test/common/encoding`) CHECK_LIBRARY_EXISTS(resolv hstrerror "" HAVE_LIBRESOLV) if (HAVE_LIBRESOLV) list(APPEND MK_LIBS resolv) endif() list(APPEND MK_LIBS GeoIP crypto ssl event event_openssl event_pthreads) endif() # Add targets link_directories(${MK_LINK_DIRS}) ## libmeasurement_kit file( GLOB MK_LIBRARY_SOURCES "include/measurement_kit/*.hpp" "include/measurement_kit/*/*.hpp" "src/libmeasurement_kit/*/*.c" "src/libmeasurement_kit/*/*.cpp" ) add_library( measurement_kit_static STATIC ${MK_LIBRARY_SOURCES} ) target_include_directories( measurement_kit_static PUBLIC ${MK_INCLUDE_DIRS} ) target_link_libraries( measurement_kit_static ${MK_LIBS} Threads::Threads ) ## measurement_kit file( GLOB MK_PROGRAM_SOURCES "src/measurement_kit/*.cpp" "src/measurement_kit/*/*.cpp" ) add_executable( measurement_kit_exe ${MK_PROGRAM_SOURCES} ) target_link_libraries( measurement_kit_exe measurement_kit_static ${MK_LIBS} Threads::Threads ) ## tests enable_testing() file(GLOB MK_TESTS_SOURCES RELATIVE "${CMAKE_SOURCE_DIR}" "test/*/*.cpp") foreach(MK_TEST_SOURCE ${MK_TESTS_SOURCES}) string(REPLACE ".cpp" "" MK_TEST_NAME ${MK_TEST_SOURCE}) string(REPLACE "/" "_" MK_TEST_NAME ${MK_TEST_NAME}) add_executable(${MK_TEST_NAME} ${MK_TEST_SOURCE}) target_link_libraries( ${MK_TEST_NAME} measurement_kit_static ${MK_LIBS} Threads::Threads ) add_test(${MK_TEST_NAME} ${MK_TEST_NAME}) endforeach() measurement-kit-0.7.1/CONTRIBUTING.md000066400000000000000000000053211315356162600170730ustar00rootroot00000000000000# Contributing to MeasurementKit MeasurementKit is a Free and Open Source software project that welcomes new contributions. ## How to contribute code For guidelines on what coding style we follow refer to the [coding style document] (/doc/coding-style.md). ### 1. Fork You should first create a fork of measurement-kit by clicking on the fork button and cloning your fork with: ``` git clone git@github.com:username/measurement-kit.git cd measurement-kit git remote add upstream https://github.com/measurement-kit/measurement-kit.git ``` ### 2. Branch Branches should be created from the `master` branch with an accurately labelled name. If you want to work on a new feature you could name your branch `feature/myfeature`, if you are fixing a bug you could name it `bug/1234`. Create your branch from `master` like so: ``` git checkout -b mybranch ``` Then you can start hacking ### 3. Commit Make sure git knows your username and email address with the following: ``` git config --global user.name "Jane Doe" git config --global user.email "jane@example.com" ``` Try to keep the commits made on the branch small (a good branch should only address one specific issue). ### 4. Test Make sure all the existing unittests for measurement-kit are passing. ``` make check ``` If you add extra code or modify existing code, be sure that it is covered by the existing unittests and if not write them. In general, it would be good for pull requests not to reduce the current code coverage of the project. If you are submitting a branch fixing a bug, you should also be submitting a unittest that is capable of reproducing the bug you are attempting to fix. ### 5. Open a Pull Request You can then push your feature branch to your remote and open a pull request. ## Code Review process Small pull requests should be tagged as `hotfix` and can be self merged. All other pull request should be reviewed by another core developer who will take responsibility of the merge. The repository should be configured such that it is not possible to merge into `master` (or `stable`) if unit tests are not passing. If the diff is small, squash merge is preferred, otherwise preserve the history. In general it is a good idea to keep your branches in sync with master and rebase them from time to time before the review has happenned. However if the review has already begun it's better to merge and resolve the conflicts locally and push the merge commit, to allow the reviewer to see how the conflicts were resolved. Before a release, review the code base, fixing simple bugs directly and opening issues to describe more complex required fixes and refactoring opportunities. Also during such review make sure that the documentation is up to date with the code. measurement-kit-0.7.1/ChangeLog.md000066400000000000000000001006771315356162600170250ustar00rootroot00000000000000# MeasurementKit 0.7.1 [2017-09-05] - fix(*): use `gpg` rather than `gpg2` (#1320) - fix(geoip): make cache thread local (#1323) - Update to Catch v1.10.0 (#1327) - backport: ssl: refactor [...], fix thread safety (#1313) - Update tls_verify to v1.19 (#1328) - fix: ios build (#1331) # MeasurementKit 0.7.0 [2017-08-05] - build/ios/archive-library: fix version number - orchestrate.cpp: serialize also language (#1282) - ndt: make test progress more smooth - runnable: stop time tests with 10% tolerance - Add more parameters to dash - fix(http): re-renable previously disabled tests # MeasurementKit 0.7.0-beta [2017-07-17] - Cherry picks from v0.7.0-beta branch (#1278) - Fix: ssl verify errors (#1279) - docker: use libc++ with clang (#1275) - Integration branch for v0.7.0-beta (#1271) # MeasurementKit 0.7.0-alpha.3 [2017-07-11] - cmake: Fix build and register tests as such (#1267) - var: inherit -> compose (fix android build) - Fix Android build warnings - Allow to pass nettests input from command line (#1273) - connect: simplify access to connect-time stats (#1261) - Implement Neubot's DASH test (#769) - docker: exclude `builtin` from coveralls - FIX test/http/request.cpp for hustmail - REPAIR test/http/request.cpp build # MeasurementKit 0.7.0-alpha.2 [2017-06-28] - Add public API to get platform name - Simple implementation of fcompose() (#1262) - orchestration: guess params and other improvements (#1260) - orchestrator: do not write on disk (#1263) - `s/contact_bouncer/query_bouncer/` - [ci skip] update docs - travis: only build using docker (#1264) - Cleanup API for v0.7 (#1265) - Cleanup/move all headers (#1266) # MeasurementKit 0.7.0-alpha.1 [2017-06-11] - Implement DNS "ping" (#1256) - Initial implementation of orchestrator (#1258) # MeasurementKit 0.7.0-alpha [2017-06-01] Note: 0.6.x was branched off stable. The release before this release is therefore v0.5.0-alpha. - Fix coveralls badge (#1190) - Allow writing report on the stdout (#1199) - Bump version number to v0.7.0-dev (#1201) - Sync master with stable (#1213, #1224, #1236) - Fix failing regress tests (#1222) - Force non-strict HTTP parser (#1225) - Use SSLv2 and SSLv3 with `web_connectivity` (#1228) - Cherry pick nodejs/http-parser#364 (#1227) - Changes to logger suggested by @darkk (#1230) - Remove all refs to `oldstable` - dns: make system resolver truly async (#1234) - We don't actually need ReturnType (#1239) - dns: split dns.hpp into several headers (#1241) - common/worker.cpp: Fix a possible race condition - dns: common impl for `query_{class,type}` (#1242) - Start using bouncer (#1016) - Start requiring move semantic for callbacks (#1244) - runner: allow to run arbitrary tasks (#1249) - Further refine the runner model (#1251) - Add support for parsing ISO8601 - `parse_iso6801_utc`: add docs and more tests - Improve our json processing capabilities (#1253) - d/a/h/request.md: reindent and improve (#1254) - Fix `json_*_process_and_filter_errors()` - http/request: start adding JSON helpers - http/request: finish off json helpers - json helpers: Fix the order of arguments - ndt: do not abort if a test phase fails - Fix bouncer address # MeasurementKit 0.6.6 [2017-05-15] - n/connect.cpp: compile with libevent v2.0.x - logger: stop using deprecated `MK_LOG_JSON` - improve documentation - fix t/h/request.cpp regress test - e/h/request.cpp: fix usage string - `connect_impl`: Fix regression added in 95e834e9e2 # MeasurementKit 0.6.5 [2017-05-14] - Reveal SSL "dirty shutdown" errors - `web_connectivity`: allow dirty SSL shutdown - e/h/request.cpp: support custom CA bundle - h/request.cpp: remove a lie - l/connection.cpp: tweak debug message # MeasurementKit 0.6.4 [2017-05-14] - Add script to pretty print a report - `dns_injection` MUST use libevent engine - runable.cpp: don't create a null `input_` entry - `dns_injection`: force timeout to be 3.0 s - nettests: add support for UUID4 - runnable: make sure empty input becomes null entry - runnable: add more missing entry fields - runnable: start adding support for test-helpers - runnable: add empty `input_hashes` entry - `http_invalid_request_line`: add backend to result - runnable.cpp: remove unneeded `input_` hack - `http_invalid_request_line`: better error reporting - `multi_ndt`: allow upload during single stream - Sync `tcp_connect` with ooni-probe - net/connect: make error result more precise - ooni/templates: agent consistent w/ ooniprobe - `web_connectivity`: add support for backend - Further improve `web_connectivity` report # MeasurementKit 0.6.3 [2017-05-12] - test: use DNS libevent engine where needed - Add script to create iOS binaries archive # MeasurementKit 0.6.2 [2017-05-12] - By default use the system engine also in `stable` # MeasurementKit 0.6.1 [2017-05-12] - Use also SSLv3 and SSLv3 with `web_connectivity` (#1228) - Cherry pick nodejs/http-parser#364 (#1227) - Reliability fixes for web connectivity (#1230) # MeasurementKit 0.6.0 [2017-05-09] - Fix iOS build (#1206) - cocoapod: if possible download precompiled binary (#1207) - Backport command line improvements from master (#1211) - Be more precise with version numbers (#1212) - Sync stable with oldstable branches (#1214, #1221) - Update to catch v1.9.3 and adjust regress tests (#1215) - Backport regress test fix from master (see #1222) # MeasurementKit 0.6.0-beta [2017-05-02] - Backport build system changes from master - Sync files in top-level directory with master - Backport test/net/connect.cpp fix for libevent-2.1 - Add NOTICE file, forgotten in previous PR - Manually resolve ChangeLog.md conflict - Add `node_modules` to .gitignore - Backport `MK_MOCK()` simplification from master - Backport HHFM and meek tests from master - Also update .gitignore # MeasurementKit 0.4.4 [2017-05-02] - Disable test for bacardi.com - Backport #1186 to stable branch - Update to latest stable dependencies - Backport #1163 to stable branch - Backport #1179 to stable branch # MeasurementKit 0.5.0-alpha [2017-04-11] - Force the library to use the system resolver (#972) - Add OONI bouncer support (#967) - Refine and finish bouncer implementation (#1014) - Add documentation for OONI's bouncer (#1032) - Move dns resolution function from net to dns (#1022) - Simple refactoring of system resolver (#1040) - Forward port patch #1066 to master (#1067) - build/dependency: implement quick git clone (#1068) - build/dependency: factor more operations (#1069) - Start cleaning up docker build system (#1070) - Finish cleaning up docker build system (#1071) - README.md: attempt to fix coveralls badge (#1072) - travis: conditional build depending on branch (#1074) - More cleanups of the CI subsystem (#1075) - Increase code coverage a bit (#1036) - Attempt to fix issue with case sensitive drive (#1076) (#1077) - Backport simple hotfixes from #1017 (#1091) - Tweak build/ios/cross (#1094) - http: extract interesting stuff from #929 (#1095) - Repair regress tests (#1117) - Tweak README.md and ChangeLog.md (#1119) - Fix uninitialized values according to Valgrind (#1118) - Remove bashism (#1145) - configure.ac: add /usr/local by default on macOS (#1151) - test/net/connect.cpp: libevent 2.1.8 compat (#1152) - Make Transport more OO (#1153) - net: move most close logic in emitter (#1154) - ooni/templates http: include all request/responses (#1149) - replace short PGP key fingerprint with long one (#1157) - Refactor cmdline to have OONI-like interface (#1156) - net: further tweak the transport model (#1155) - Repair broken test/ooni/utils.cpp (#1164) - Fix `unknown_failure 3` bug (#1162) - Repair regress tests after travis failure (#1166) - build/ci/travis: fix branch name detection logic (#1167) - http: refactor redirect logic (#1168) - ooni/template.cpp: don't assume `!!response->request` (#1170) - Finish fixing travis branch handling (#1171) - common: add {start,end}swith (#1172) - http::Response: init numbers to know value (#1174) - http: treat EOF instead of response as error (#1175) - Fix embarassing mk::endswith() bug (#1173) - Fix `unknown_error_3009` bug (#1176) - Fix report/entry.hpp w/ new NDK, nlohmann::json (#1177) - Only run coveralls if we know the token (#1181) - meek fronting nettest (#1141) - Update to nlohmann/json v2.1.1 (#1179) - mock.hpp: reduce implicit `MK_MOCK_NAMESPACE` magic (#1142) - Start updating dependencies: the easy part (#1163) - Update valgrind suppression files (#1186) - Build and archive dependencies separately (#1185) - Update README, license, badges (#1188) - Refactor and improve build scripts (#1017) - HTTP header fields manipulation test (#1146) # MeasurementKit 0.4.3 [2017-03-14] - Backport 5d88cf9ff (#1177) to stable branch # MeasurementKit 0.4.2 [2017-03-12] - Backport #1162: fix `unknown_failure 3` bug - Backport #1163: repair regress tests after travis failure - Backport #1164: repair broken test/ooni/utils.cpp - Backport #1168: http: refactor redirect logic - Backport #1170: ooni/template.cpp: don't assume `!!response->request` - Backport #1172 and #1173: common: add {start,end}swith - Backport #1174: http::Response: init numbers to known value - Backport #1175: http: treat EOF-instead-of-response as error - Backport #1176: Fix `unknown_error_3009` bug # MeasurementKit 0.4.1 [2017-03-02] - Backport #1149: ooni/templates http: include all request/responses # MeasurementKit 0.4.0 [2017-02-13] - Repair circle-ci build for stable (#1123) - connect: support also ipv6 link local with scope (#1102) - Fix gitlab on stable by using yakkety (#1133) - Be more specific wrt connect() failure (#1126) - Add a name to each error (#1134) # MeasurementKit 0.4.0-beta.4 [2017-02-09] - .gitlab-ci.yml: also build stable (#1122) - http: fix EOF-implies-end-of-body logic (#1121) - http: fix schema less redirect (#1124) # MeasurementKit 0.4.0-beta.3 [2017-02-01] - `ip_lookup()`: validate result as IP address (#1108) - `web_connectivity`: do not `*request` unconditionally - runnable: progress now accounts for `max_runtime` - progress: also track opening/closing report - The header key comparison MUST be done with the lowercase version - Use std::transform to convert to lowercase - Use transform also in another place # MeasurementKit 0.4.0-beta.2 [2017-01-31] - Start updating documentation for release 0.4.0 (#1082) - report: Allow to specify application name and version (#1092) - report: include the platform (#1093) - Make sure http template produces good json (#1096) - var.hpp: fix as() to use dynamic cast (#1090) - test/net/connect.cpp: refactor to avoid global poller (#1099) - connect: start fixing IPv6 addresses (#1100) - net: start exposing network errors (#1101) - Feature: NDT stats (#1089) - Add regress tests for input processor (#1059) - Use default backends when it makes sense (#1097) - Propagate network errors (#1103) - Fix: web connectivity segfault (#1107) - `templates::http_request()`: scrub IP address (#1106) - `web_connectivity`: pass headers to backend (#1111) # MeasurementKit 0.4.0-beta.1 [2017-01-16] - net: improve handling of address:port (#1079) - `clang-format -i ooni/web_connectivity.cpp` (#1078) - Attempt to fix issue with case sensitive drive (#1076) - README.md: attempt to fix coveralls badge (#1073) - travis: fix coveralls (#1066) # MeasurementKit 0.4.0-beta [2017-01-13] - Feature: recognize utf8 (#1062) - Support for country-specific test lists (#1030) # MeasurementKit 0.4.0-alpha.3 [2017-01-06] - nettests: randomize input (#1029) - Add workaround for Android with API < 21 (#1048) - android build: simple changes backported from #1047 (#1049) - More hotfix backports from #1047 (#1050) - Fix API and ABI compatibility for old Androids (#1047) - `system_resolver.hpp`: do not warn on getaddrinfo failure (#1055) # MeasurementKit 0.4.0-alpha.2 [2016-12-28] - runnable: implement `max_runtime` option (#1028) - Fix libevent clock gettime (#1044) # MeasurementKit 0.4.0-alpha.1 [2016-12-15] - Improve `multi_ndt` entry format (#992) - Fix: libressl ios build (#994) - Refactor: ssl (#997) - Write ssl context regress tests (#998) - Implement mk::slurp() to read files at once (#996) - BaseTest: add `on_logger_eof()` method (#1004) - getaddrinfo: android dislikes `AI_V4MAPPED|AI_ALL` (#1005) - logger: allow multiple `on_eof()` callbacks (#1006) - runnable: allow multiple on-end callbacks (#1007) - Use builtin CA file if CA file is missing and we're using libressl (#999) - runnable: add `on_destroy()` callback (#1008) # MeasurementKit 0.4.0-alpha [2016-12-07] - cmdline.hpp: Use macros to simplify code (#858) - Make `no_collector` / `no_file_report` options really usable (#860) - Make sure filenames extension is .njson, not .json (#873) - dns: pass logger to query() (#878) - don't track njson files (#879) - dns.hpp: pass a `Var` to the callback (#862) - ssl: handle errors using callbacks not exceptions (#789) - Start moving libevent code into a specific folder (#891) - More abstract reactor API (#894) - reactor: move more code from poller to here (#895) - More reactor-related cleanups (#896) - More maintenance of reactor and poller (#897) - net: measure connect time during connect (#899) - Prepare for required successful build only on travis (#902) - ndt: multi stream test (#710) - Implement and use `reactor->pollfd()` (#898) - Add support for submitting reports via cloudfronted collectors (#907) - http/request: don't redirect if `*max_request <= 0` (#910) - Log dns debug to the correct logger (#912) - travis: valgrind: update openssl.supp (#928) - Move cmdline in src/measurement_kit (#930) - collector_client.hpp: remove backward compat stuff (#931) - version: use C linkage function (#932) - Reactor should come before logger in function args (#933) - ndt: exchange reactor and logger arguments (#934) - reactor.hpp: add missing header (#936) - Do not use `using namespace` in public headers (#937) - Refactoring of the nettests layer (#938) - nettests: move code from headers to .cpp files (#939) - runner: hide implementation details (#940) - net_test: less inline functions (#941) - Merge net_test.hpp and ooni_test.hpp (#942) - ooni_reporter: fix layers violation (#943) - Divide net_test in base_test and runnable (#944) - nettests: more refactoring (#945) - Feature: ignore collector errors (#946) - Move ooni_reporter in report module (#947) - nettests: pass `Var` to callback (#948) - nettests: run() now uses the current thread (#949) - dns: enums that should not conflict with windows (#951) - Resolve hosts using the system resolver (#918) - Support IPv6 link-local resolver (#915) - logger: add callback for JSON encoded events (#956) - ndt: print progress of the test (#958) - Make sure we always store and submit report-id (#950) - ndt: allow to specify alternative mlabns tool (#959) - Move network utils code in net directory (#960) - Always disable the Nagle algorithm (#961) - Set CFLAGS et al. in configure (#963) - Improve cmake for Unix (#965) - Implement single+multiple stream NDT test (#968) - Update dependencies for v0.4.0 (#982) - Implement ooni resources downloader (#811) - Improve the CMakeLists.txt file (#983) # MeasurementKit 0.3.9 [2016-12-04] - Revert "Add workaround for macOS" # MeasurementKit 0.3.8 [2016-12-04] - Make sure --disable-traceroute actually works - Add workaround for macOS # MeasurementKit 0.3.7 [2016-12-02] - Allow to quickly disable traceroute # MeasurementKit 0.3.6 [2016-12-01] - http/request: don't redirect if `*max_request <= 0` (#908) - Log dns debug to the correct logger (#912) (#914) - web-connectivity: log errors (#916) - bufferevent: use `BEV_OPT_DEFER_CALLBACKS` (#924) - Fix several warnings (#926) - `ooni_reporter.cpp`: make sure we submit report id (#927) # MeasurementKit 0.3.5 [2016-11-01] - a few `web_connectivity` fixes (#880, #889, #890) - fix progress in emitted progress json (#886) # MeasurementKit 0.3.4 [2016-10-28] - switch test collector to b.collector.test.ooni.io (#880) - remove `./build/android/library` (#870) - fixing `web_connectivity` bug #867 # MeasurementKit 0.3.3 [2016-10-23] - `connect.cpp`: increase default net/timeout (#872) - `web_connectivity`: set the accessible key (#871) - Make `no_collector`/`no_file_report` really usable (#859) # MeasurementKit 0.3.2 [2016-10-03] - `ooni_test`: continue even if we cannot submit an entry - for testing use the discarding https collector deployed on heroku - clanups and other small changes - update android and ios to compile using latest dependencies # MeasurementKit 0.3.1 [2016-10-03] - update dependencies (yes, I was optimistic yesterday) # MeasurementKit 0.3.0 [2016-10-02] We are now entering in stable land. There are some outstanding issues like making sure dependencies are up to date and that documentation is in sync with code, but we can take care of those in subsequent patch releases, if needed. We have been testing this version of MK for quite a while now, and it really looks like good. Compared to previous 0.3.0-beta.3, this release includes some goodies from master that are very inlikely to impact on stability. Namely: - flesh out basic contribution guide (#819) - backport simple portability changes from #820 (#821) - report: allow to pretty print entry (#825) - very lite refactoring of runner (#826) # MeasurementKit 0.3.0-beta.3 [2016-09-19] - ooni: refactor geoip to cache openned databases (#809) - reduce tarball size by not shipping geoip - ooni: allow caller to set probe_{ip,asn,cc} (#816) - ooni: fix regress by changing collector-url # MeasurementKit 0.3.0-beta.2 [2016-09-15] - ooni: allow to disable collector - geoip: skip compiling binaries - ooni: count entries and emit progress - ooni: allow to optionally avoid writing reports to disk - http: put geoip databases in current working dir - *: make sure all errors are named Error # MeasurementKit 0.3.0-beta.1 [2016-09-01] - Improve .gitignore - Merge stable branch into release/v0.3.0 branch - Fix build with --disable-integration-tests # MeasurementKit 0.3.0-beta [2016-08-31] - autogen.sh: don't list embedded-mk as dependency (#796) - teach acinclude.m4 to use brew's OpenSSL (#797) - sketch out cmake build system (mainly for Windows) (#798) - implement incremental ooni collector (#765) - run OONI tests in parallel (#768) # MeasurementKit 0.2.9 [2016-08-31] - Make sure install.sh is included when we build release # MeasurementKit 0.3.0-alpha.1 [2016-08-25] - fix type of `getopt()` return value - fix build for Android - improve docs - `net_test.hpp`: add `set_error_filepath()` - change Android output archive name to be `measurement_kit-$version-android_jni${optional_build_version}.tag.bz2` # MeasurementKit 0.3.0-alpha [2016-08-24] - Add command line interface and also build binary executable - Add OONI's web connectivity test - Improve NDT test implementation: add support for waiting in queue, convert NDT into a real OONI test, fix way in which speed is measured - `error.hpp`: allows to add an error a list of child errors - add `fmap.hpp`: allows to map() over a vector - `logger.hpp`: add EOF handler and allow to write logs on logfile, allow code to specify that the log message is in JSON format - `net_test.hpp`: pass error to begin() and end(), add `on_entry` handler, add handlers for entering into `begin` and `end` states - add `parallel.hpp`: allows to run functions in parallel and terminates only when all parallel functions have terminated (this interface is single threaded, not multi threaded, thus parallelism is only achieved when one function pauses waiting for I/O) - add `range.hpp`: to generate numbers in a given range (such as in Python) - `version.hpp`: add function to get library version - `http.hpp`: implement following redirection and case-insensitive headers search - `report/entry.hpp` now derives from nlohmann/json using public inheritance rather than private inheritance - Update nlohmann/json.hpp to v2.0.2 - Update `tls_verify.c` to v1.15 - mlabns: allow to specify alternative mlabns base url - net: add workarounds for when libevent's SSL bufferevents emit EOF before emitting data received before EOF, make emitter code more robust - ooni: it is now possible to avoid saving autonomous system number and country code, add code to lookup the real IP address of the resolver, refactor code to use GeoIP APIs - Update external dependencies versions - Minor changes and bug fixes # MeasurementKit 0.2.8 [2016-08-18] - Updated dependencies - Many improvements and changes in cross build scripts # MeasurementKit 0.2.7 [2016-08-02] - By default don't use OONI collector but the testing collector to avoid submitting integration tests results as OONI tests - Update ChangeLog - Bump patch version number # MeasurementKit 0.2.6 [2016-07-31] - Use OONI's default collector - Update ChangeLog - Bump patch version number # MeasurementKit 0.2.5 [2016-07-13] - Allow to `./configure --disable-integration-tests` - Cherry pick 6d6f118e9 (fix TLS timeout bug) - Bump patch version number # MeasurementKit 0.2.4 [2016-07-10] - Makefile.am: fix -release and -version-info flags - bump path version number - Add script to generate source package - Use https collector by default - Fix NDT example usage string # MeasurementKit 0.2.3 [2016-07-08] - make sure podspec uses up-to-date version number - bump version number to v0.2.3 # MeasurementKit 0.2.2 [2016-07-08] - document v0.2.1 release (I forgot to do that) - properly bump version number (again, I forgot to do that) - add script to automate release tasks - and document v0.2.2 release # MeasurementKit 0.2.1 [2016-07-08] - use jessie64 rather than trusty64 in Vagrant file to make sure we work on debian stable - make sure autogen.sh works ok on jessie64 - fix a bug that prevented headers to be installed when $DESTDIR wasn't specified # MeasurementKit 0.2.0 [2016-06-30] - autogen.sh: with -n do not use the network - fix net/connect timeout - update documentation for v0.2.0 - bump version to v0.2.0 # MeasurementKit 0.2.0-beta.2 [2016-06-19] - http/request_serializer: allow custom path - refactoring and small fixes - common/net_test: removed misleading identifier() function - common/utils: export time related utils functions - ooni: merge DSL and Impl tests, use functions to implement tests (#677) - ooni: avoid collisions in test file names - common/net_test: file_path => filepath # MeasurementKit 0.2.0-beta.1 [2016-06-08] - `ip_lookup()`: allow custom settings, reactor, and logger (required by Android app) # MeasurementKit 0.2.0-beta [2016-06-07] - add initial NDT client implementation - add more continuous integration providers using docker - add support for setting default CA bundle path - updated http-parser to v2.7.0 - updated Catch to v1.5.0 - add precompiled dependencies for Android and iOS - upgrade Android build scripts to NDK r11c - switch to use libevent's upstream repository instead of our fork - peg GeoIP to v2.7.9 rather than using the master branch - update libressl to v2.3.6 - add more documentation for common - start updating existing docs - migrate the tree to use templates to mock API calls - rationalize HTTP and mlabns APIs - rationalize OONI tests DSL API (this would probably break apps) - add client for OONI report protocol - make Delegate more convenient - make Error way more robust and convenient, e.g. allow to chain errors - use define to increase robustness of error definitions - allow to pass flags to logger to convey extended semantic, e.g. state update - add more helpful MOCK macros - unify NetTest and NetTestDsl object models (OONI not yet ready for that) - rename Poller as Reactor (more precise name); Poller is now a React implement. - Reactor: add `loop_with_initial_event_and_connectivity` - rename Async as Runner (more precise name) - make Settings more useful - add nlohmann/json as external header - rewrite report::Entry using nlohmann/json via private inheritance - FIX: make sure `readn()` never consumes too much stack - export `report` headers as public API now that it uses `report::Entry` - make sure we don't ignore possible errors when writing report - remove unused, incomplete Tor controller - downgrade minimum iOS platform from 9.0 to 7.1 - use `std::promise<>` and `std::future<>` for increased robustness - Poller: make sure we ignore `SIGPIPE` - significantly increase code coverage (now greater than 93%) - make sure we handle `EPIPE` - FIX: make sure OONI code produces spec compliant reports - refactor OoniTestImpl replacing InputGenerator with much simpler code - add to OONI support for geolookup and for automatically submitting reports # MeasurementKit 0.2.0-alpha [2016-05-12] We are not ready to declare a stable release yet, because tons of things still need love. However, we've reached a point where we could tag an alpha release. Too many changes, hence listing them in the order in which I see them when reading the huge diff since the previous stable release: - autogenerate toplevel headers - rewrite async - add more functional programming abstractions - allow to bind context to errors - rename the Maybe object as ErrorOr - remove evbuffer wrapper - introduce lexical_cast - use templates rather than Libs object to make code testable - all global objects are now `Var<>` rather than raw pointers - more granular logger levels - make logger thread safe - the Poller is now known as Reactor (but Poller is still an implementation of Reactor) - removed code to manage global dns resolver, now each test sets its own resolver - now Settings maps strings to most scalar types - now it is possible to cast from `Var` to `Var` - rewritten dns code from scratch to increase memory safety - rewritten http code from scratch to increase memory safety - prefix settings with module name, to avoid conflicts - implement client for mlabns - remove TransportInterface, make Transport abstract and pass around `Var` - rewrite from scratch the connect flow to increase memory safety - implement SSL transport - verify SSL certificates - allow to connect many socket at once - migrated OONI code to use JSON rather than YAML (thus replacing yaml-cpp dependency with nlohmann/json) - as a consequence of previous change, remove boost from dependencies - implement GeoIP using the old rather than the new maxmind library (not all free database available for new library) - removed most dependency from tree and rely now on the `./build/dependency` script - add ./autogen.sh script to automatically generate parts of the tree that it would be otherwise tedious to maintain - rewritten from scratch and significantly improved travis.yml - added more example files - moved the mobile subtree below build along with the new `./build/dependency` script - added basic listener - more cleanups and bug fixes To speed up cross compiling, this release would also be the first release to contain bits of compiled code (e.g. libressl) that could be downloaded during the cross compilation process. # MeasurementKit 0.1.2 [2016-02-04] - cleanups and bug fixes # MeasurementKit 0.1.1 [2016-01-13] - allow to specify report file path for OONI tests - add missing documentation - add Vagrantfile - mv ooni::NetTest ooni::NetTest to avoid confusion with common::NetTest - misc fixes # MeasurementKit 0.1.0 [2015-12-16] - allow to clear DNS servers on Android and iOS - doc: add examples and tutorials - a few more small fixes here and there # MeasurementKit 0.1.0-beta.4 [2015-12-12] - http: avoid throwing runtime-error - poller: add functions to manipulate default's evdns-base - updated changelog file # MeasurementKit 0.1.0-beta.3 [2015-12-09] - readd documentation of private classes - add support for mkdocs - bugfix: make the Connection class non-copyable and non-movable - fixes to simplify using cross-compiled android libraries - make OONI tests set_verbose() accept a boolean value (true by default) - improve iOS build system # MeasurementKit 0.1.0-beta.2 [2015-12-07] - install missing traceroute header - shrink android build in size and create tarballs - rename and simplify namespaces - rename measurement_kit to mk - remove namespace common - update dependencies to latest version - simplify transport usage - rename Transport to TransportInterface - reintroduce Transport as a proxy for Var - teach connect() to return Maybe - other minor changes # MeasurementKit 0.1.0-beta.1 [2015-12-02] - implemented code coverage using clang - misc build system improvements - make sure that dependencies headers do not appear in measurement-kit public headers - fix build process to avoid installing dependencies headers for android - ooni.hpp: more abstract api for running ooni tests (this changed the api of the ooni sublibrary) - net.hpp: rename Buffer::foreach() to Buffer::for_each() - net.hpp: modify Buffer::readline() to return Maybestd::string - net.hpp: modify signature of Transport::on_data() - net.hpp: modify signature of net::connect() - common.hpp: add Async::global() - common.hpp: implement the Maybe template - moved many headers from include to src to make sure they are not part of the public api - fix http-parser to throw common::Error subclasses on error - net/stream.cpp: route common::Error exceptions received when reading/writing - improve regress tests - add more documentation # MeasurementKit 0.1.0-alpha.1 [2015-11-21] * Project name changed to MeasurementKit * Most code has been rewritten using C++11 * Cleanup the API in: * common * dns * http * net * ooni * report * traceroute * Implemented OONI tests: * dns injection * http invalid request line * tcp connect * Many more changes with respect to LibNeubot (compared to that project, MeasurementKit is basically another project) # LibNeubot 3.0.0 [2014-05-04] * Rewrite NeubotPollable now that I know that, in C++, a structure can inherit from a class. As a result, the FooState structure is now gone and the API now looks like v1.0 again. That is, again the poller is passed to the Pollable constructor, not to init(). * Related to the previous change: clarified that the Pollable main purpose is to allow experiments in which Neubot uses LibNeubot. * Related to the previous change: crank major (we're now at API 3.0). * Take advantage of the API 3.0 cranking and install the headers at a different location ( becomes ). * Add (but do not use yet) joyent/http-parser as submodule. * Update the OpenBSD port and fix the code accordingly (mainly cases in which mixed libevent 1.4 and 2.0 headers were being used). * Related to the previous change: update README to better clarify which are the dependencies. * Deprecate gen_cxx and neubot.hh, now that it's clear that the code will be written in C++ to ease the interaction with SWIG. * Move testing code in `test/`. * Significant improvements in gen_python, which now enforces the type safety (i.e., you can only pass to Pollable_foo() an instance of the Python Pollable class), and in general produces much less bloated and more pythonic Python code. * Related to the previous change: half of the unit test is now gone because it was not typesafe (we passed integers to functions in hope that they were pointer to the right C/C++ objects). * More minor changes, fixes and tweaks. # LibNeubot 2.0.0 [2014-04-11] * Add Android.mk to compile a static library for Android * Remove the unused LibNeubot.java/gen_java thing * Reimplement NeubotPollable using C++ and write C wrappers to provide a similar API (however, the arguments of the constructor and of attach() were changed, hence the API bump) * Move Java code that was autogenerated with SWIG into the neubot/neubot_android repository * Make sure gen_cxx generates code that works on Android: correct the order of the generated classes, replace the nonworking cast with the invocation of the ->pointer() method * Unify gen_py/gen_python and libneubot.py/libneubot1.py: now gen_python generates a libneubot.py file that contains the old stuff plus the stuff that was in libneubot1.py, moreover, the gen_py script and libneubot1.py were removed * Regen libneubot_python * Make sure shared C functions (e.g., log.h and utils.h) are correctly exported to C++ * While bumping the API, unbreak the resolve() API * While touching the Pollable, reimplement timeouts using the support provided by libevent * Realize that the destruction of objects must flow from the derived classes to the base classes (as C++ does) not the other way round (as PyNeubot does) * Add some defines needed to compile on Android * Export the logs to the logcat to ease the debugging # LibNeubot 1.0.1 [2014-02-18] * Tweak gen_cxx to generate code that SWIG can handle * Use SWIG to generate Java and Python wrappers # LibNeubot 1.0.0 [2013-12-15] * Return status_t in NeubotPoller_defer_{read,write} * Pass opaque, not pollable, to NeubotPollable callbacks * libneubot.json: Add and use hooks, slots and __destructor__ * Add easier-to-use libneubot1.py wrappers * Add neubot.hh, wrappers for C++ # LibNeubot 0.1.0 [2013-12-12] * Initial release measurement-kit-0.7.1/LICENSE000066400000000000000000000026611315356162600156530ustar00rootroot00000000000000BSD 2-Clause License Copyright (c) 2013-2017, Simone Basso, Arturo Filastò, Nexa Center for Internet & Society - Politecnico di Torino (DAUIN), and the measurement-kit contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. measurement-kit-0.7.1/Makefile.am000066400000000000000000000043131315356162600166760ustar00rootroot00000000000000# Part of measurement-kit . # Measurement-kit is free software. See AUTHORS and LICENSE for more # information on the copying conditions. AUTOMAKE_OPTIONS = foreign 1.9 subdir-objects ACLOCAL_AMFLAGS = -I m4 VERSION_INFO = -release @VERSION@ -version-info 0 lib_LTLIBRARIES = libmeasurement_kit.la libmeasurement_kit_la_LDFLAGS = $(VERSION_INFO) libmeasurement_kit_la_SOURCES = # Empty measurement_kit_SOURCES = # Empty if BUILD_BINARIES bin_PROGRAMS = measurement_kit measurement_kit_LDADD = libmeasurement_kit.la endif noinst_PROGRAMS = # Empty ALL_TESTS = # Empty include include.am # We link with libresolv to have an oracle for our base64 implementation test_common_encoding_LDADD += -lresolv TESTS = $(ALL_TESTS) check_PROGRAMS = $(ALL_TESTS) # # Running tests through Valgrind by abusing of the LOG_COMPILER feature # which is enabled by automake < 1.14 only when parallel tests are forced, # so you now see why they are enabled explicitly in configure.ac # # See http://ansuz.sooke.bc.ca/entry/233 # # (Yes, of course this means valgrind runs in parallel -- i.e. faster.) # # On travis-ci we need on specific suppression for a memory warning that I # honestly don't understand but that doesn't appear when building using docker # on circle-ci and gitlab (BTW docker on travis using valgrind was odd since # there were tons of errors unlike seen on every other docker and so I decided # it was wiser avoding docker on travis). On other platforms (including my # own docker on VoidLinux) no suppression file is needed. # # See https://travis-ci.org/measurement-kit/measurement-kit/jobs/172742411#L2131 # VALGRIND = $(LIBTOOL) --mode=execute valgrind --trace-children=yes \ --error-exitcode=1 --dsymutil=yes --leak-check=yes --gen-suppressions=all VALGRIND_TRAVIS = $(VALGRIND) --suppressions=build/valgrind/openssl.supp VALGRIND_DOCKER = $(VALGRIND) --suppressions=build/valgrind/strlen.supp check-am-valgrind: $(MAKE) $(AM_MAKEFLAGS) check-am LOG_COMPILER='$(VALGRIND_TRAVIS)' run-valgrind-docker: $(MAKE) $(AM_MAKEFLAGS) check-am LOG_COMPILER='$(VALGRIND_DOCKER)' run-valgrind: $(MAKE) $(AM_MAKEFLAGS) check-am LOG_COMPILER='$(VALGRIND)' measurement-kit-0.7.1/NOTICE000066400000000000000000000114531315356162600155510ustar00rootroot00000000000000The following copyright statement applies to the scripts in build/ios, which are a derivative work of ursachec/CPAProxy. Portions Copyright (c) 2013, Claudiu-Vlad Ursache 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. Portions Copyright (c) 2010, Pierre-Olivier Latour All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The name of Pierre-Olivier Latour may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - The following copyright statement applies to portions of acinclude.m4 that search for a default CA bundle; they derive from curl code. Portions Copyright (c) 1996 - 2016, Daniel Stenberg, daniel@haxx.se, and many contributors, see the THANKS file. All rights reserved. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 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 OF THIRD PARTY RIGHTS. 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. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. - - - The following statement applies to src/libmeasurement_kit/ext/sole.{c,h}pp which is a derivative work of . Portions Copyright (c) 2015 r-lyeh (https://github.com/r-lyeh) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. measurement-kit-0.7.1/README.md000066400000000000000000000202311315356162600161160ustar00rootroot00000000000000# MeasurementKit > Portable C++14 network measurement library [![Android](https://api.bintray.com/packages/measurement-kit/android/android-libs/images/download.svg)](https://bintray.com/measurement-kit/android/android-libs/_latestVersion) [![GitHub license](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg)](https://raw.githubusercontent.com/measurement-kit/measurement-kit/master/LICENSE) [![Github Releases](https://img.shields.io/github/release/measurement-kit/measurement-kit.svg)](https://github.com/measurement-kit/measurement-kit/releases) [![Github Issues](https://img.shields.io/github/issues/measurement-kit/measurement-kit.svg)](https://github.com/measurement-kit/measurement-kit/issues) - - - | branch | travis-ci | coveralls | gitlab-ci | circle-ci| |--------|-----------|-----------|-----------|----------| | master | [![Travis Build Status](https://travis-ci.org/measurement-kit/measurement-kit.svg?branch=master)](https://travis-ci.org/measurement-kit/measurement-kit) | [![Coverage Status](https://coveralls.io/repos/github/measurement-kit/measurement-kit/badge.svg?branch=master)](https://coveralls.io/github/measurement-kit/measurement-kit?branch=master) | [![GitLab Build Status](https://gitlab.com/measurement-kit/measurement-kit/badges/master/build.svg)](https://gitlab.com/measurement-kit/measurement-kit/commits/master) | [![CircleCI](https://circleci.com/gh/measurement-kit/measurement-kit.svg?style=svg)](https://circleci.com/gh/measurement-kit/measurement-kit) | | stable | [![Travis Build Status](https://travis-ci.org/measurement-kit/measurement-kit.svg?branch=stable)](https://travis-ci.org/measurement-kit/measurement-kit?branch=stable) | [![Coverage Status](https://coveralls.io/repos/measurement-kit/measurement-kit/badge.svg)](https://coveralls.io/github/measurement-kit/measurement-kit?branch=stable) | [![GitLab Build Status](https://gitlab.com/measurement-kit/measurement-kit/badges/stable/build.svg)](https://gitlab.com/measurement-kit/measurement-kit/commits/stable) | [![CircleCI](https://circleci.com/gh/measurement-kit/measurement-kit/tree/stable.svg?style=svg)](https://circleci.com/gh/measurement-kit/measurement-kit/tree/stable) | MeasurementKit is a library that implements open network measurement methodologies (performance, censorship, etc.) and targets mobile platforms (Android and iOS). It is meant to be embedded by third party applications with specific network measurement needs and/or to be used by researchers as a basis to implement novel tools. Currently it implements the following high-level tests: - [OONI](https://ooni.torproject.org/)'s [Web Connectivity](https://github.com/TheTorProject/ooni-spec/blob/master/test-specs/ts-017-web-connectivity.md) test - the [network diagnostic tool](https://github.com/ndt-project/ndt/wiki/NDTTestMethodology) network performance test - [OONI](https://ooni.torproject.org/)'s [DNS Injection](https://github.com/TheTorProject/ooni-spec/blob/master/test-specs/ts-012-dns-injection.md) test - [OONI](https://ooni.torproject.org/)'s [HTTP Invalid Request Line](https://github.com/TheTorProject/ooni-spec/blob/master/test-specs/ts-007-http-invalid-request-line.md) test - [OONI](https://ooni.torproject.org/)'s [TCP Connect](https://github.com/TheTorProject/ooni-spec/blob/master/test-specs/ts-008-tcpconnect.md) test - [OONI](https://ooni.torproject.org/)'s [Meek Fronted Requests](https://github.com/TheTorProject/ooni-spec/blob/master/test-specs/ts-014-meek-fronted-requests.md) test - [OONI](https://ooni.torproject.org/)'s [HTTP Header Field Manipulation](https://github.com/TheTorProject/ooni-spec/blob/master/test-specs/ts-006-header-field-manipulation.md) test - Neubot's [MPEG DASH test](https://github.com/neubot/neubot/tree/master/mod_dash) It contains building-block functionalities useful to implement your own tests. More in detail it currently implements: - [TCP connection](https://github.com/measurement-kit/measurement-kit/blob/master/include/measurement_kit/net/transport.hpp) (with which you can create a TCP connection towards and endpoint, receive and send data) - [DNS client](https://github.com/measurement-kit/measurement-kit/blob/master/include/measurement_kit/dns/dns.hpp) (with which you can resolve and reverse-resolve A and AAAA records using arbitrary name servers) - [HTTP client](https://github.com/measurement-kit/measurement-kit/blob/master/include/measurement_kit/http/http.hpp) (with which you can send HTTP/1.1 requests and receive and parse the corresponding responses) - [traceroute for Android](https://github.com/measurement-kit/measurement-kit/blob/master/include/measurement_kit/traceroute/android.hpp) (with which you can send individual traceroute probes with a specified payload and TTL) - [mlab-ns client](https://github.com/measurement-kit/measurement-kit/blob/master/include/measurement_kit/mlabns/mlabns.hpp) (with which you can interact with Measurement Lab backend to know the server with which to run tests) - the functionality to communicate with the [OONI collector](https://github.com/TheTorProject/ooni-backend) - the functionality to communicate with the [OONI bouncer](https://github.com/TheTorProject/ooni-backend) In the short term we plan to add to MeasurementKit: - more OONI tests Other functionalities that we would like to add are building-blocks functionalities such as [uTP](https://github.com/bittorrent/libutp), and traceroute for iOS. The following index illustrates the content of the remainder of this file: - [How to clone the repository](#how-to-clone-the-repository) - [How to test a specific branch](#how-to-test-a-specific-branch) - [How to build MeasurementKit](#how-to-build-measurementkit) - [How to build MeasurementKit on a Unix-like system](#how-to-build-measurementkit-on-a-unix-like-system) - [How to test MeasurementKit on a Unix-like system](#how-to-test-measurementkit-on-a-unix-like-system) - [How to build MeasurementKit on Android](#how-to-build-measurementkit-on-android) - [How to build MeasurementKit on iOS](#how-to-build-measurementkit-on-ios) - [How to add MeasurementKit to an Xcode project](#how-to-add-measurementkit-to-an-xcode-project) - [How to use MeasurementKit](#how-to-use-measurementkit) ## How to clone the repository To clone MeasurementKit repository, do: git clone https://github.com/measurement-kit/measurement-kit ## How to test a specific branch If you need to checkout a specific branch (say `feature/foo`) for testing it, clone the repository and then type: ``` git fetch origin git checkout feature/foo ``` Then proceed with the instruction to build and test MeasurementKit. For more detailed instructions see [contributing instructions]( CONTRIBUTING.md). ## How to build MeasurementKit ### How to build MeasurementKit on a Unix-like system Very briefly, to build from the git repository do: ``` ./autogen.sh ./configure make ``` See [the Unix tutorial](doc/tutorial/unix.md) for more details. ### How to test MeasurementKit on a Unix-like system Once you have built MeasurementKit, run tests like: ``` make check ``` ### How to build MeasurementKit on Android We have [a specific repository](https://github.com/measurement-kit/android-libs) for compiling MeasurementKit for Android. You may also want to read the [documentation explaining how to cross compile MK dependencies for Android]( doc/build/android.md). ### How to build MeasurementKit on iOS Having Xcode command line tools installed, run: ``` ./build/ios/library ``` See the [iOS tutorial](doc/tutorial/ios.md) for more info. ### How to add MeasurementKit to an Xcode project. Make sure your [Podfile](https://guides.cocoapods.org/syntax/podfile.html) looks like this: ```ruby target 'YourTargetNameHere' do pod 'measurement_kit', :git => 'https://github.com/measurement-kit/measurement-kit.git', :branch => 'stable' end ``` Run `pod install` (or `pod update`) and remember to open the `.xcworkspace` rather than the `.xcodeproj`. See the [iOS tutorial]( doc/tutorial/ios.md) for more info. ## How to use MeasurementKit You probably want to start using the [nettests API](doc/api/nettests.md) that is the high level API for running tests. To this end, see also the [nettests API examples](example/nettests) and the [Unix tutorial](doc/tutorial/unix.md). measurement-kit-0.7.1/TODO.md000066400000000000000000000010121315356162600157220ustar00rootroot00000000000000TODO ==== These tests still need to be implemented: * [DNS Consistency](https://gitweb.torproject.org/ooni/spec.git/blob/HEAD:/test-specs/ts-002-dnsconsistency.md) * [HTTP Requests](https://gitweb.torproject.org/ooni/spec.git/blob/HEAD:/test-specs/ts-003-http-requests.md) * [Header Field Manipulation](https://gitweb.torproject.org/ooni/spec.git/blob/HEAD:/test-specs/ts-006-header-field-manipulation.md) * [Captive portal](https://gitweb.torproject.org/ooni/spec.git/blob/HEAD:/test-specs/ts-010-captive-portal.md) measurement-kit-0.7.1/Vagrantfile000066400000000000000000000003541315356162600170300ustar00rootroot00000000000000Vagrant.configure(2) do |config| config.vm.synced_folder ".", "/mk" config.vm.define "yakkety" do |yakkety| yakkety.vm.box = "ubuntu/yakkety64" yakkety.vm.provider "virtualbox" do |v| v.memory = 2048 end end end measurement-kit-0.7.1/acinclude.m4000066400000000000000000000227541315356162600170440ustar00rootroot00000000000000dnl Part of measurement-kit . dnl Measurement-kit is free software. See AUTHORS and LICENSE for more dnl information on the copying conditions. AC_DEFUN([MK_AM_ENABLE_COVERAGE], [ AC_ARG_ENABLE([coverage], AS_HELP_STRING([--enable-coverage, build for coverage]), [enable_coverage=yes], []) ]) AC_DEFUN([MK_AM_ADD_COVERAGE_FLAGS_IF_NEEDED], [ if test "$enable_coverage" = "yes"; then CFLAGS="$CFLAGS --coverage -g -O0" CXXFLAGS="$CXXFLAGS --coverage -g -O0" LDFLAGS="$LDFLAGS --coverage" fi ]) AC_DEFUN([MK_AM_DISABLE_EXAMPLES], [ AC_ARG_ENABLE([examples], AS_HELP_STRING([--disable-examples, skip building of examples programs]), [], [enable_examples=yes]) AM_CONDITIONAL([BUILD_EXAMPLES], [test "$enable_examples" = "yes"]) ]) AC_DEFUN([MK_AM_DISABLE_BINARIES], [ AC_ARG_ENABLE([binaries], AS_HELP_STRING([--disable-binaries, skip building of binary programs]), [], [enable_binaries=yes]) AM_CONDITIONAL([BUILD_BINARIES], [test "$enable_binaries" = "yes"]) ]) AC_DEFUN([MK_AM_DISABLE_INTEGRATION_TESTS], [ AC_ARG_ENABLE([integration-tests], AS_HELP_STRING([--disable-integration-tests, skip building of integration tests]), [], [CPPFLAGS="$CPPFLAGS -DENABLE_INTEGRATION_TESTS"]) ]) AC_DEFUN([MK_AM_DISABLE_TRACEROUTE], [ AC_ARG_ENABLE([traceroute], AS_HELP_STRING([--disable-traceroute, do not build traceroute]), [], [CPPFLAGS="$CPPFLAGS -DENABLE_TRACEROUTE"]) ]) AC_DEFUN([MK_AM_CHECK_LIBC_FUNCS], [ AC_CHECK_FUNCS([ \ err \ errx \ warn \ warnx \ getopt \ getopt_long \ getopt_long_only \ gmtime_r \ strcasecmp \ strtonum \ ]) ]) AC_DEFUN([MK_AM_LIBEVENT], [ AC_ARG_WITH([libevent], [AS_HELP_STRING([--with-libevent], [event I/O library @<:@default=check@:>@]) ], [ CPPFLAGS="$CPPFLAGS -I$withval/include" LDFLAGS="$LDFLAGS -L$withval/lib" ], []) mk_not_found="" AC_CHECK_HEADERS(event2/event.h, [], [mk_not_found=1]) AC_CHECK_LIB(event, event_new, [], [mk_not_found=1]) AC_CHECK_HEADERS(event2/thread.h, [], [mk_not_found=1]) AC_CHECK_LIB(event_pthreads, evthread_use_pthreads, [], [mk_not_found=1]) AC_CHECK_LIB(event_openssl, bufferevent_openssl_filter_new, [], [mk_not_found=1]) AC_CHECK_FUNCS([bufferevent_openssl_set_allow_dirty_shutdown]) if test "$mk_not_found" = "1"; then AC_MSG_WARN([Failed to find dependency: libevent]) echo " - to install on Debian: sudo apt-get install libevent-dev" echo " - to install on OSX: brew install libevent" echo " - to compile from sources: ./build/dependency libevent" AC_MSG_ERROR([Please, install libevent and run configure again]) fi ]) AC_DEFUN([MK_AM_GEOIP], [ AC_ARG_WITH([geoip], [AS_HELP_STRING([--with-geoip], [GeoIP library @<:@default=check@:>@]) ], [ CPPFLAGS="$CPPFLAGS -I$withval/include" LDFLAGS="$LDFLAGS -L$withval/lib" ], []) mk_not_found="" AC_CHECK_HEADERS(GeoIP.h, [], [mk_not_found=1]) AC_CHECK_LIB(GeoIP, GeoIP_open, [], [mk_not_found=1]) if test "$mk_not_found" = "1"; then AC_MSG_WARN([Failed to find dependency: geoip]) echo " - to install on Debian: sudo apt-get install libgeoip-dev" echo " - to install on OSX: brew install libgeoip" echo " - to compile from sources: ./build/dependency geoip" AC_MSG_ERROR([Please, install geoip and run configure again]) fi ]) AC_DEFUN([MK_AM_OPENSSL], [ AC_ARG_WITH([openssl], [AS_HELP_STRING([--with-openssl], [SSL toolkit @<:@default=check@:>@]) ], [ CPPFLAGS="$CPPFLAGS -I$withval/include" LDFLAGS="$LDFLAGS -L$withval/lib" ], [ if test -d /usr/local/Cellar/openssl; then AC_MSG_WARN([Using the OpenSSL installed via brew...]) mk_openssl_v=`ls /usr/local/Cellar/openssl|tail -n1` mk_openssl_d="/usr/local/Cellar/openssl/$mk_openssl_v" CPPFLAGS="$CPPFLAGS -I$mk_openssl_d/include" LDFLAGS="$LDFLAGS -L$mk_openssl_d/lib" fi ]) mk_not_found="" AC_CHECK_HEADERS(openssl/ssl.h, [], [mk_not_found=1]) AC_CHECK_LIB(crypto, RSA_new, [], [mk_not_found=1]) AC_CHECK_LIB(ssl, SSL_new, [], [mk_not_found=1]) dnl This test breaks the build with 12.04 on travis because the linker there dnl requires `LD_RUN_PATH` which sadly is not honoured by this test, still dnl no worries because actually this check only makes sense for Mac systems if test "`uname`" = "Darwin"; then AC_MSG_CHECKING([whether OpenSSL is older than 1.0.0]) AC_RUN_IFELSE([ AC_LANG_SOURCE([ #include #include /* Code taken from tor/src/common/crypto.h */ #define OPENSSL_VER(a,b,c,d,e) \ (((a)<<28) | \ ((b)<<20) | \ ((c)<<12) | \ ((d)<< 4) | \ (e)) #define OPENSSL_V_SERIES(a,b,c) OPENSSL_VER((a),(b),(c),0,0) /* Code taken from tor/src/common/compat_openssl.h */ #if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,0) # error "We require OpenSSL >= 1.0.0" #endif #if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) && \ ! defined(LIBRESSL_VERSION_NUMBER) /* We define this macro if we're trying to build with the majorly refactored * API in OpenSSL 1.1 */ #define OPENSSL_1_1_API #endif #ifndef OPENSSL_1_1_API #define OpenSSL_version_num() SSLeay() #endif int main() { if (OpenSSL_version_num() != OPENSSL_VERSION_NUMBER) { return 1; } if (OpenSSL_version_num() < OPENSSL_V_SERIES(1, 0, 0)) { return 2; } return 0; } ]) ], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) if test -d /usr/local/Cellar/openssl; then AC_MSG_WARN([MacOS ships an old system-wide OpenSSL but you seem to]) AC_MSG_WARN([have a new version installed with brew.]) AC_MSG_WARN([So, you should try adding this flag to configure:]) AC_MSG_WARN(['--with-openssl=/usr/local/Cellar/openssl/VERSION/']) fi mk_not_found=1 ], [AC_MSG_RESULT([Skip the test because we are cross-compiling])]) fi if test "$mk_not_found" = "1"; then AC_MSG_WARN([Failed to find dependency: openssl]) echo " - to install on Debian: sudo apt-get install libssl-dev" echo " - to install on OSX: brew install openssl" echo " - to compile from sources: ./build/dependency libressl" AC_MSG_ERROR([Please, install openssl and run configure again]) fi ]) AC_DEFUN([MK_AM_REQUIRE_C99], [ AC_PROG_CC_C99 if test x"$ac_cv_prog_cc_c99" = xno; then AC_MSG_ERROR([a C99 compiler is required]) fi ]) AC_DEFUN([MK_AM_REQUIRE_CXX14], [ mk_saved_cxxflags="$CXXFLAGS" CXXFLAGS=-std=c++14 AC_MSG_CHECKING([whether CXX supports -std=c++14]) AC_LANG_PUSH([C++]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], [AC_MSG_RESULT([yes])] [], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([a C++14 compiler is required]) ]) CXXFLAGS="$mk_saved_cxxflags -std=c++14" AC_LANG_POP([C++]) ]) AC_DEFUN([MK_CHECK_CA_BUNDLE], [ AC_MSG_CHECKING([CA bundle path]) AC_ARG_WITH([ca-bundle], AC_HELP_STRING([--with-ca-bundle=FILE], [Path to a file containing CA certificates (example: /etc/ca-bundle.crt)]), [ want_ca="$withval" ], [want_ca="unset"]) if test "x$want_ca" != "xunset"; then ca="$want_ca" else ca="no" if test "x$cross_compiling" != "xyes"; then for a in /etc/ssl/certs/ca-certificates.crt \ /etc/pki/tls/certs/ca-bundle.crt \ /usr/share/ssl/certs/ca-bundle.crt \ /usr/local/share/certs/ca-root.crt \ /etc/ssl/cert.pem \ /usr/local/etc/openssl/cert.pem; do if test -f "$a"; then ca="$a" break fi done fi fi if test "x$ca" != "xno"; then MK_CA_BUNDLE="$ca" AC_DEFINE_UNQUOTED(MK_CA_BUNDLE, "$ca", [Location of default ca bundle]) AC_SUBST(MK_CA_BUNDLE) AC_MSG_RESULT([$ca]) elif test "x$cross_compiling" == "xyes"; then AC_MSG_RESULT([skipped (cross compiling)]) AC_MSG_WARN([skipped the ca-bundle detection when cross-compiling]) AC_DEFINE_UNQUOTED(MK_CA_BUNDLE, "", [Location of default ca bundle]) AC_SUBST(MK_CA_BUNDLE) else AC_MSG_RESULT([no]) AC_MSG_ERROR([you should give a ca-bundle location]) fi ]) AC_DEFUN([MK_AM_CXXFLAGS_ADD_WARNINGS], [ AC_MSG_CHECKING([whether compiler is clang to add clang specific warnings]) if test echo | $CXX -dM -E - | grep __clang__ > /dev/null; then AC_MSG_RESULT([yes]) CXXFLAGS="$CXXFLAGS -Wmissing-prototypes" else AC_MSG_RESULT([yes]) fi ]) AC_DEFUN([MK_AM_PRINT_SUMMARY], [ echo "==== configured variables ===" echo "CPP : $CPP" echo "CC : $CC" echo "CXX : $CXX" echo "CFLAGS : $CFLAGS" echo "CPPFLAGS : $CPPFLAGS" echo "CXXFLAGS : $CXXFLAGS" echo "LDFLAGS : $LDFLAGS" echo "LIBS : $LIBS" ]) measurement-kit-0.7.1/autogen.sh000077500000000000000000000114701315356162600166450ustar00rootroot00000000000000#!/bin/sh set -e export LC_ALL=C # Stable sorting regardless of the locale . build/autogen.d/geoip no_geoip=0 cmake=0 while [ $# -gt 0 ]; do opt=$1; shift if [ "$opt" = "--no-geoip" -o "$opt" = "-n" ]; then no_geoip=1 elif [ "$opt" = "--cmake" ]; then cmake=1 else echo "usage: $0 [--cmake] [-n|--no-geoip]" 1>&2 exit 1 fi done slug() { echo $(echo $1|tr '/-' '_'|sed 's/^include_measurement_kit/mk/g') } gen_automatic_includes() { hh=include/measurement_kit/common/git_version.hpp echo "// File autogenerated by \`$0\`, do not edit" > $hh echo "#ifndef MEASUREMENT_KIT_COMMON_GIT_VERSION_HPP" >> $hh echo "#define MEASUREMENT_KIT_COMMON_GIT_VERSION_HPP" >> $hh echo "" >> $hh echo "#define MK_VERSION_FULL \"`git describe --tags`\"" >> $hh echo "" >> $hh echo "#endif" >> $hh rm -f include/measurement_kit/*.hpp for name in $(ls include/measurement_kit/|grep -v portable); do hh=include/measurement_kit/$name.hpp echo "// File autogenerated by \`$0\`, do not edit" > $hh echo "#ifndef MEASUREMENT_KIT_$(echo $name|tr 'a-z' 'A-Z')_HPP" >> $hh echo "#define MEASUREMENT_KIT_$(echo $name|tr 'a-z' 'A-Z')_HPP" >> $hh for nn in $(ls include/measurement_kit/$name/); do echo "#include " >> $hh done echo "#endif" >> $hh done } gen_headers() { echo "$(slug $1)_includedir = \${prefix}/$1" echo "$(slug $1)_include_HEADERS = # Empty" for name in `ls $1`; do if [ ! -d $1/$name ]; then echo "$(slug $1)_include_HEADERS += $1/$name" fi done echo "" for name in `ls $1`; do if [ -d $1/$name ]; then gen_headers $1/$name fi done } gen_sources() { for name in `ls $2`; do if [ ! -d $2/$name ]; then if echo $name | grep -q '\.c[p]*$'; then echo "$1 += $2/$name" fi fi done for name in `ls $2`; do if [ -d $2/$name ]; then gen_sources $1 $2/$name fi done } gen_executables() { for name in `ls $2`; do if [ ! -d $2/$name ]; then if echo $name | grep -q '\.c[p]*$'; then bin_name=$(echo $name | sed 's/\.c[p]*$//g') echo "" echo "if $3" echo " $1 += $2/$bin_name" echo "endif" echo "/$2/$bin_name" >> .gitignore echo "$(slug $2/$bin_name)_SOURCES = $2/$name" echo "$(slug $2/$bin_name)_LDADD = libmeasurement_kit.la" fi fi done for name in `ls $2`; do if [ -d $2/$name ]; then gen_executables $1 $2/$name $3 fi done } grep -v -E "^/(test|example){1}/.*" .gitignore > .gitignore.new echo /GeoIP.dat >> .gitignore.new echo /GeoIPASNum.dat >> .gitignore.new echo /GeoLiteCity.dat >> .gitignore.new mv .gitignore.new .gitignore echo "* Generating automatic includes: include/measurement_kit/*.hpp" gen_automatic_includes include/measurement_kit echo "* Generating include.am" echo "# Autogenerated by $0 on date $(date)" > include.am echo "" >> include.am gen_sources libmeasurement_kit_la_SOURCES src/libmeasurement_kit >> include.am gen_sources measurement_kit_SOURCES src/measurement_kit >> include.am echo "" >> include.am gen_headers include/measurement_kit >> include.am gen_executables noinst_PROGRAMS example BUILD_EXAMPLES >> include.am gen_executables ALL_TESTS test BUILD_TESTS >> include.am echo "* Updating .gitignore" sort -u .gitignore > .gitignore.new mv .gitignore.new .gitignore if [ $no_geoip -ne 1 ]; then autogen_get_geoip fi if [ $cmake -eq 0 ]; then echo "* Running 'autoreconf -i'" autoreconf -i fi echo "" echo "=== autogen.sh complete ===" echo "" echo "MeasurementKit is now ready to be compiled. To proceed you shall run" echo "now the './configure' script that adapts the build to your system." echo "" echo "The './configure' script shall also check for external dependencies. " echo "MeasurementKit external dependencies are:" echo "" echo " - GeoIP" echo " - openssl / libressl" echo " - libevent" echo "" echo "If any of these dependencies is missing, the './configure' script shall" echo "stop and tell you how you could install it." measurement-kit-0.7.1/build/000077500000000000000000000000001315356162600157405ustar00rootroot00000000000000measurement-kit-0.7.1/build/android/000077500000000000000000000000001315356162600173605ustar00rootroot00000000000000measurement-kit-0.7.1/build/android/.gitignore000066400000000000000000000000201315356162600213400ustar00rootroot00000000000000*.tgz *.tgz.asc measurement-kit-0.7.1/build/android/archive-deps000077500000000000000000000011321315356162600216550ustar00rootroot00000000000000#!/bin/sh set -e ROOTDIR=$(cd $(dirname $0)/../.. && pwd -P) cd $ROOTDIR/build/android # Do not ship *.la files that would break the build and, while there, also # remove directories that we don't need for cross compiling MK find jni -type f -name \*.la -exec rm {} \; find jni -type f -name \*.pc -exec rm {} \; find jni -type d -depth -name share -exec rm -rf {} \; find jni -type d -depth -name bin -exec rm -rf {} \; find jni -type d -depth -name pkgconfig -exec rm -rf {} \; now=`date +%Y%m%dT%H%M%SZ` tar -czf android-dependencies-$now.tgz jni $ROOTDIR/build/sign android-dependencies-$now.tgz measurement-kit-0.7.1/build/android/cross000077500000000000000000000106441315356162600204440ustar00rootroot00000000000000#!/bin/sh set -e ROOTDIR=$(cd $(dirname $0) && pwd -P) if [ $# -lt 1 ]; then echo "Usage: $0 ARCH" 1>&2 echo "" 1>&2 echo " ARCH: armeabi, armeabi-v7a, arm64, mips, mips64, x86, x86_64" 1>&2 echo "" 1>&2 echo "Example usage:" 1>&2 echo " $0 arm64" 1>&2 exit 1 fi ARCH=$1 shift echo "" echo "Cross compiling for $ARCH" # Place where make-toolchain creates a standalone toolchain export ANDROID_TOOLCHAIN=${ROOTDIR}/toolchain/${ARCH} # Directory under the toolchain where we have headers and libs export SYSROOT=${ANDROID_TOOLCHAIN}/sysroot # # Map the selected architecture to useful variables: # # TOOLCHAIN_NAME: name of the toolchain to use. # DESTDIR_NAME: name of the directory where to install headers and libs. # CFLAGS: flags to be passed to C compiler. # CXXFLAGS: flags to be passed to C++ compiler. # LIB_SUFFIX: unset unless toolchain has lib64 libs directory. # CONFIG_EXTRA: optional extra flags to be passed to configure script. # if [ "$ARCH" = "arm64" ]; then # Note: arm64 is also known as aarch64 and as armv8 TOOLCHAIN_NAME=aarch64-linux-android DESTDIR_NAME=arm64-v8a elif [ "$ARCH" = "armeabi" ]; then TOOLCHAIN_NAME=arm-linux-androideabi DESTDIR_NAME=$ARCH # # These flags have been copied from the flags used by # ndk-build when building measurement-kit as a C++ library. # # According to Wikipedia [1], armv5te means v5 of the architecture, # with thumbs and DSP extensions. Xscale is a processor built by third # parties compatible with armv5te that doesn't have floating point, # hence the -msoft-float flag. The -mthumb instructions forces emitting # instructions using the thumb instruction set where common instructions # are encoded using 16 bits rather than 32 bits. # # [1] https://en.wikipedia.org/wiki/ARM_architecture#Cores # # Note: `-Os` was originally part of the flags but this led to # non working libevent binaries as documented in #1051. Also # `-fno-integrated-as` is needed to avoid another segfault. # CFLAGS="-target armv5te-none-linux-androideabi -march=armv5te -mtune=xscale -msoft-float -mthumb -fno-integrated-as" CXXFLAGS=$CFLAGS elif [ "$ARCH" = "armeabi-v7a" ]; then TOOLCHAIN_NAME=arm-linux-androideabi DESTDIR_NAME=$ARCH # # See above. # CFLAGS="-target armv7-none-linux-androideabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb" CXXFLAGS="$CFLAGS" elif [ "$ARCH" = "mips" ]; then # Note: mips is actually mipsel (i.e. little endian) TOOLCHAIN_NAME=mipsel-linux-android DESTDIR_NAME=mips elif [ "$ARCH" = "mips64" ]; then # Note: this is mips 64bit little endian TOOLCHAIN_NAME=mips64el-linux-android DESTDIR_NAME=mips64 LIB_SUFFIX=64 CONFIG_EXTRA="--disable-asm" # See issue 653 elif [ "$ARCH" = "x86" ]; then TOOLCHAIN_NAME=i686-linux-android DESTDIR_NAME=x86 elif [ "$ARCH" = "x86_64" ]; then TOOLCHAIN_NAME=x86_64-linux-android DESTDIR_NAME=x86_64 LIB_SUFFIX=64 else echo "$0: invalid $ARCH" 1>&2 exit 1 fi # Override makefile's defaults with toolchain's tools. We use clang. TOOL_PREFIX=${ANDROID_TOOLCHAIN}/bin/${TOOLCHAIN_NAME} export CPP=${TOOL_PREFIX}-cpp export AR=${TOOL_PREFIX}-ar export AS=${TOOL_PREFIX}-as export NM=${TOOL_PREFIX}-nm export CC=${TOOL_PREFIX}-clang export CXX=${TOOL_PREFIX}-clang++ export LD=${TOOL_PREFIX}-ld export RANLIB=${TOOL_PREFIX}-ranlib export STRIP=${TOOL_PREFIX}-strip # Teach the preprocessor to find toolchain includes export CPPFLAGS="${CPPFLAGS} --sysroot=${SYSROOT} -I${SYSROOT}/usr/include -I${ANDROID_TOOLCHAIN}/include" # Pass specific flags to the C and/or CXX compiler export CFLAGS="${CFLAGS}" export CXXFLAGS="${CXXFLAGS}" # Teach the linker to find toolchain libraries export LDFLAGS="${LDFLAGS} -L${SYSROOT}/usr/lib${LIB_SUFFIX} -L${ANDROID_TOOLCHAIN}/lib" # Extra libraries to link with. Should not be needed. #export LIBS="-lm" # # Flags for ./build/dependency (cross-)build system # # Tell configure to use the toolchain and build only static libs export pkg_configure_flags="--host=${TOOLCHAIN_NAME} --disable-shared $CONFIG_EXTRA" # Where to install headers and libraries export pkg_prefix="${ROOTDIR}" # Tell ./build/dependency that we are cross compiling export pkg_cross="jni" # Tell ./build/dependency the name of the cross architecture export pkg_cross_arch="${DESTDIR_NAME}" if [ $# -gt 0 ]; then $@ else env fi measurement-kit-0.7.1/build/android/dependency000077500000000000000000000013341315356162600214250ustar00rootroot00000000000000#!/bin/sh set -e if [ $# -lt 2 ]; then echo "usage: $0 NDK_DIR spec" 1>&2 exit 1 fi ROOTDIR=$(cd $(dirname $0)/../.. && pwd -P) BUILDDIR=$ROOTDIR/build ANDROIDDIR=$BUILDDIR/android NDK_DIR=$1 SPEC=$2 echo "" echo "Cross-compiling $SPEC for all archs" ALL_ARCHS="armeabi armeabi-v7a arm64 mips mips64 x86 x86_64" for ARCH in $ALL_ARCHS; do echo "" echo "Cross compiling $SPEC for arch ${ARCH}" rm -rf $ANDROIDDIR/toolchain/${ARCH} $ANDROIDDIR/make-toolchain ${NDK_DIR} ${ARCH} $ANDROIDDIR/cross ${ARCH} $BUILDDIR/dependency $SPEC done # Install spec so we know what version was used to build the archive install -d $ANDROIDDIR/jni/spec install -m644 $BUILDDIR/spec/$SPEC $ANDROIDDIR/jni/spec/$SPEC measurement-kit-0.7.1/build/android/fetch-dep000077500000000000000000000001551315356162600211460ustar00rootroot00000000000000#!/bin/sh set -e ROOTDIR=$(cd $(dirname $0) && pwd -P) export pkg_prefix=$ROOTDIR $ROOTDIR/../fetch-dep "$@" measurement-kit-0.7.1/build/android/jni/000077500000000000000000000000001315356162600201405ustar00rootroot00000000000000measurement-kit-0.7.1/build/android/jni/arm64-v8a/000077500000000000000000000000001315356162600215655ustar00rootroot00000000000000measurement-kit-0.7.1/build/android/jni/arm64-v8a/.gitignore000066400000000000000000000000021315356162600235450ustar00rootroot00000000000000* measurement-kit-0.7.1/build/android/jni/armeabi-v7a/000077500000000000000000000000001315356162600222335ustar00rootroot00000000000000measurement-kit-0.7.1/build/android/jni/armeabi-v7a/.gitignore000066400000000000000000000000021315356162600242130ustar00rootroot00000000000000* measurement-kit-0.7.1/build/android/jni/armeabi/000077500000000000000000000000001315356162600215405ustar00rootroot00000000000000measurement-kit-0.7.1/build/android/jni/armeabi/.gitignore000066400000000000000000000000021315356162600235200ustar00rootroot00000000000000* measurement-kit-0.7.1/build/android/jni/mips/000077500000000000000000000000001315356162600211105ustar00rootroot00000000000000measurement-kit-0.7.1/build/android/jni/mips/.gitignore000066400000000000000000000000021315356162600230700ustar00rootroot00000000000000* measurement-kit-0.7.1/build/android/jni/mips64/000077500000000000000000000000001315356162600212625ustar00rootroot00000000000000measurement-kit-0.7.1/build/android/jni/mips64/.gitignore000066400000000000000000000000021315356162600232420ustar00rootroot00000000000000* measurement-kit-0.7.1/build/android/jni/x86/000077500000000000000000000000001315356162600205655ustar00rootroot00000000000000measurement-kit-0.7.1/build/android/jni/x86/.gitignore000066400000000000000000000000021315356162600225450ustar00rootroot00000000000000* measurement-kit-0.7.1/build/android/jni/x86_64/000077500000000000000000000000001315356162600210765ustar00rootroot00000000000000measurement-kit-0.7.1/build/android/jni/x86_64/.gitignore000066400000000000000000000000021315356162600230560ustar00rootroot00000000000000* measurement-kit-0.7.1/build/android/make-toolchain000077500000000000000000000026531315356162600222070ustar00rootroot00000000000000#!/bin/sh set -e if [ $# -ne 2 -a $# -ne 3 ]; then echo "" 1>&2 echo "Usage: $0 NDK_DIR ARCH [API]" 1>&2 echo "" 1>&2 echo " NDK_DIR: path where NDK is installed" 1>&2 echo " ARCH: armeabi, armeabi-v7a, arm64, mips, mips64, x86, x86_64" 1>&2 echo " API: 1 ... 25" 1>&2 echo "" 1>&2 echo "If API is omitted, the minimum possible API for the " 1>&2 echo "required architecture is used." 1>&2 echo "" 1>&2 echo "Example usage (on MacOS with Android Studio installed):" 1>&2 echo " $0 ~/Library/Android/sdk/ndk-bundle arm 19" 1>&2 echo "" 1>&2 exit 1 fi ROOTDIR=$(cd $(dirname $0) && pwd -P) NDK_DIR=$1 ARCH=$2 API=$3 BASEDIR=$ROOTDIR/toolchain # Directory where to install the toolchain. This must be done _before_ # mapping the input architecture to a real toolchain architecture. INSTALL_DIR=$BASEDIR/${ARCH} # Map input architecture to toolchain architecture (armeabi and # armeabi-v7a both use the arm toolchain) if [ "$ARCH" = "armeabi" -o "$ARCH" = "armeabi-v7a" ]; then ARCH="arm" fi if [ "$API" = "" ]; then if [ "$ARCH" = "arm64" -o "$ARCH" = "mips64" -o "$ARCH" = "x86_64" ]; then API=21 else API=14 fi fi MAKE_TOOLCHAIN=${NDK_DIR}/build/tools/make_standalone_toolchain.py echo "Creating toolchain for API ${API} and ARCH ${ARCH} in ${INSTALL_DIR}" $MAKE_TOOLCHAIN --arch=${ARCH} --api=${API} --install-dir=${INSTALL_DIR} \ --stl=libc++ measurement-kit-0.7.1/build/android/toolchain/000077500000000000000000000000001315356162600213405ustar00rootroot00000000000000measurement-kit-0.7.1/build/android/toolchain/.gitignore000066400000000000000000000000021315356162600233200ustar00rootroot00000000000000* measurement-kit-0.7.1/build/autogen.d/000077500000000000000000000000001315356162600176245ustar00rootroot00000000000000measurement-kit-0.7.1/build/autogen.d/geoip000066400000000000000000000010601315356162600206470ustar00rootroot00000000000000#!/bin/sh set -e autogen_get_geoip() { echo "* Fetching geoip database" base=https://download.maxmind.com/download/geoip/database if [ ! -f "GeoIP.dat" ]; then wget $base/GeoLiteCountry/GeoIP.dat.gz -O GeoIP.dat.gz gzip -d GeoIP.dat.gz fi if [ ! -f "GeoLiteCity.dat" ]; then wget $base/GeoLiteCity.dat.gz -O GeoLiteCity.dat.gz gzip -d GeoLiteCity.dat.gz fi if [ ! -f "GeoIPASNum.dat" ]; then wget $base/asnum/GeoIPASNum.dat.gz -O GeoIPASNum.dat.gz gzip -d GeoIPASNum.dat.gz fi } measurement-kit-0.7.1/build/bundle-ca000077500000000000000000000025361315356162600175260ustar00rootroot00000000000000#!/usr/bin/env python # Part of measurement-kit . # Measurement-kit is free software. See AUTHORS and LICENSE for more # information on the copying conditions. """ Usage: bundle-ca libressl-version ca-bundle-path output-header-path """ import sys def main(): """ Main function """ libressl_version = sys.argv[1].encode("ascii") ca_bundle_path = sys.argv[2] output_header_path = sys.argv[3] with open(ca_bundle_path, "rb") as filep: ca_bundle_data = filep.read() with open(output_header_path, "wb") as filep: filep.write(b""" /* * Warning: autogenerated file; do not edit! * * Returns the CA file shipped with the libressl version we compile with * as a vector of unsigned characters. This could then be passed to libressl * specific functions for loading CAs from a memory buffer. * * Based on curl cacert-%s */ #include "private/net/builtin_ca_bundle.hpp" namespace mk { namespace net { std::vector builtin_ca_bundle() { static std::vector cav{ """ % libressl_version) for number in ca_bundle_data: if sys.version_info.major == 2: number = ord(number) filep.write(b"%d," % number) filep.write(b""" }; return cav; } } // namespace net } // namespace mk """) if __name__ == "__main__": main() measurement-kit-0.7.1/build/ci/000077500000000000000000000000001315356162600163335ustar00rootroot00000000000000measurement-kit-0.7.1/build/ci/circle000077500000000000000000000001321315356162600175160ustar00rootroot00000000000000#!/bin/sh set -e export pkg_make_flags="$pkg_make_flags V=0 -j$(nproc)" ./build/docker/$1 measurement-kit-0.7.1/build/ci/gitlab000077500000000000000000000001451315356162600175230ustar00rootroot00000000000000#!/bin/sh set -e export pkg_make_flags="$pkg_make_flags V=0 -j$(nproc)" ./build/docker/script/run $1 measurement-kit-0.7.1/build/ci/travis000077500000000000000000000000551315356162600175710ustar00rootroot00000000000000#!/bin/sh set -e ./build/docker/$DOCKER_SPEC measurement-kit-0.7.1/build/cmake/000077500000000000000000000000001315356162600170205ustar00rootroot00000000000000measurement-kit-0.7.1/build/cmake/macos_with_brew000077500000000000000000000003361315356162600221240ustar00rootroot00000000000000#!/bin/sh set -e rootdir=$(cd $(dirname $(dirname $0)) && pwd -P) cmake -D MK_GEOIP=/usr/local -D MK_LIBEVENT=/usr/local \ -D MK_OPENSSL=/usr/local/opt/openssl . echo "" echo "Now run 'make'" measurement-kit-0.7.1/build/dependency000077500000000000000000000116071315356162600200110ustar00rootroot00000000000000#!/bin/sh print_usage() { cat << EOF usage: $0 dependency-name Clones repository, configure, build and install dependency. By default sources are below './third_party' and installed software is below './builtin/'. Override default behavior by setting these environment variables: - pkg_clone_flags: extra flags for 'git clone' (e.g. '--recursive') - pkg_configure_flags: extra flags for './configure' (if any) - pkg_cmake_flags: extra flags for 'cmake .' (if CMakeLists.txt exists) - pkg_make_check_rule: rule to run tests (default: not set, no tests are run) - pkg_make_flags: extra flags for 'make' (e.g. 'V=0') - pkg_make_install_flags: extra flags for 'make install' (e.g. DESTDIR=/opt) - pkg_prefix: prefix where to install (e.g. '/usr/local') - pkg_steps: steps to execute (default is: 'init patch_pre_autogen autogen patch_post_autogen configure make make_check make_install') Examples: - use four processors to compile libressl: - pkg_make_flags=-j4 ./build/dependency libressl EOF } apply_patches() { if [ -d ../../../build/patch/$1 ]; then for diff in `find ../../../build/patch/$1 -type f`; do echo "* apply patch: $diff" git apply -v $diff done fi } pkg_init() { if [ -f Makefile ]; then echo "- make distclean" make distclean fi } pkg_patch_pre_autogen() { apply_patches pre-autogen/$pkg_name/common if [ "$pkg_cross" != "" ]; then apply_patches pre-autogen/$pkg_name/$pkg_cross fi } pkg_autogen() { if [ -x ./autogen.sh ]; then echo "- ./autogen.sh" ./autogen.sh elif [ -f ./configure.ac ]; then echo "- autoreconf -i" autoreconf -i fi } pkg_patch_post_autogen() { apply_patches post-autogen/$pkg_name/common if [ "$pkg_cross" != "" ]; then apply_patches post-autogen/$pkg_name/$pkg_cross fi } pkg_configure() { if [ -x ./configure ]; then echo "- ./configure --prefix=/ $pkg_configure_flags" ./configure --prefix=/ $pkg_configure_flags elif [ -f ./CMakeLists.txt ]; then echo "- cmake -D CMAKE_INSTALL_PREFIX=/ $pkg_cmake_flags ." cmake -D CMAKE_INSTALL_PREFIX=/ $pkg_cmake_flags . fi } pkg_make() { echo "- make $pkg_make_flags" make $pkg_make_flags } pkg_make_check() { if [ "$pkg_make_check_rule" != "" ]; then echo "- make $pkg_make_flags $pkg_make_check_rule" if ! make $pkg_make_flags $pkg_make_check_rule; then if [ -f ./test-suite.log ]; then cat ./test-suite.log fi exit 1 fi else echo 'not running checks because $pkg_make_check_rule is not set' fi } pkg_make_install() { if [ "$pkg_make_install_rule" = "" ]; then pkg_make_install_rule=install fi vspec=$pkg_branch_or_tag if [ "$pkg_tip" != "" ]; then vspec="$pkg_tip" fi based=$pkg_rootdir/third_party/tmp/$pkg_name-$vspec adir=$based/$pkg_cross/$pkg_cross_arch echo "- make $pkg_make_install_flags $pkg_make_install_rule" make $pkg_make_install_flags $pkg_make_install_rule DESTDIR=$adir find $adir -depth -type d -name bin -exec rm -rf {} \; find $adir -depth -type d -name pkgconfig -exec rm -rf {} \; find $adir -depth -type d -name sbin -exec rm -rf {} \; find $adir -depth -type f -name \*.la -exec rm -rf {} \; tarname=$pkg_rootdir/$pkg_name-$vspec tarname=$tarname-$pkg_cross-$pkg_cross_arch tarname=$tarname-`date -u +%Y%m%dT%H%M%SZ` tarname=$tarname.tgz echo "" echo "- create archive $tarname" (cd $based && tar -cvzf $tarname ./) rm -rf $pkg_rootdir/third_party/tmp echo "" echo "- install from $tarname into $pkg_prefix" install -d $pkg_prefix (cd $pkg_prefix && tar -xvzf $tarname) } pkg_none() { echo "- no action" } set -e if [ $# -ne 1 ]; then print_usage exit 1 fi pkg_rootdir=$(cd $(dirname $(dirname $0)) && pwd -P) if [ -z "$pkg_prefix" ]; then pkg_prefix=$pkg_rootdir/builtin fi export pkg_prefix cd $pkg_rootdir # Note that the spec has access to $pkg_rootdir . build/spec/$1 if [ "$pkg_repository" != "" ]; then rm -rf third_party/src/$pkg_name git clone $pkg_clone_flags --single-branch --depth 2 \ --branch $pkg_branch_or_tag $pkg_repository third_party/src/$pkg_name cd third_party/src/$pkg_name if [ "$pkg_tip" != "" ]; then if [ "`git rev-parse HEAD`" != "$pkg_tip" ]; then # Mainly because this allows us to know which commit was the # tip of the branch when we compiled a dependency echo "FATAL: unexpected HEAD commit SHA-1" 1>&2 exit 1 fi fi fi if [ -z "$pkg_steps" ]; then pkg_steps="init patch_pre_autogen autogen patch_post_autogen configure make make_check make_install" fi for step in $pkg_steps; do echo "" echo "./build/dependency: $step" echo "" pkg_$step done echo "" measurement-kit-0.7.1/build/docker/000077500000000000000000000000001315356162600172075ustar00rootroot00000000000000measurement-kit-0.7.1/build/docker/coveralls000077500000000000000000000002131315356162600211230ustar00rootroot00000000000000#!/bin/sh set -e REPOROOT=$(cd $(dirname $(dirname $(dirname $0))) && pwd -P) $REPOROOT/build/docker/script/setup ubuntu:yakkety coveralls measurement-kit-0.7.1/build/docker/script/000077500000000000000000000000001315356162600205135ustar00rootroot00000000000000measurement-kit-0.7.1/build/docker/script/init000077500000000000000000000000701315356162600214010ustar00rootroot00000000000000#!/bin/sh set -e cd /mk ./build/docker/script/run "$@" measurement-kit-0.7.1/build/docker/script/run000077500000000000000000000015201315356162600212430ustar00rootroot00000000000000#!/bin/sh set -e if [ $# -lt 1 ]; then echo "usage: $0 spec-name [phase ...]" 1>&2 exit 1 fi spec_name=$1 shift subr_depend() { echo "- install debian deps: $debian_deps" apt-get update apt-get upgrade -y apt-get install -y $debian_deps if [ "$pip_deps" != "" ]; then echo "- install pip deps: $pip_deps" pip install --user $pip_deps fi } subr_start_over() { if [ -f Makefile ]; then make distclean fi } subr_build() { ./build/dependency mk } subr_finalize() { echo "- finalize" } . build/docker/spec/$spec_name env | sed 's/^COVERALLS_REPO_TOKEN=.*$/COVERALLS_REPO_TOKEN=[secure]/g' sleep 5 if [ $# -eq 0 ]; then set -- depend start_over build finalize fi while [ $# -gt 0 ]; do echo "" echo "docker/script/run: $1" echo "" subr_$1 shift done measurement-kit-0.7.1/build/docker/script/setup000077500000000000000000000014371315356162600216060ustar00rootroot00000000000000#!/bin/sh set -e REPOROOT=$(cd $(dirname $(dirname $(dirname $(dirname $0)))) && pwd -P) docker_image=$1 if [ "$docker_image" = "" ]; then echo "usage: $0 docker-image-name docker-spec-name" 1>&2 exit 1 fi shift docker run \ -e "pkg_configure_flags=$pkg_configure_flags" \ -e "pkg_make_flags=$pkg_make_flags" \ -e "COVERALLS_REPO_TOKEN=$COVERALLS_REPO_TOKEN" \ -e "TRAVIS_BRANCH=$TRAVIS_BRANCH" \ -v $REPOROOT:/mk \ $docker_image \ /mk/build/docker/script/init "$@" measurement-kit-0.7.1/build/docker/spec/000077500000000000000000000000001315356162600201415ustar00rootroot00000000000000measurement-kit-0.7.1/build/docker/spec/coveralls000066400000000000000000000027671315356162600220720ustar00rootroot00000000000000#!/bin/sh set -e export pkg_configure_flags="$pkg_configure_flags --enable-coverage" export pkg_make_check_rule="check" debian_deps="$debian_deps autoconf" debian_deps="$debian_deps automake" debian_deps="$debian_deps g++" debian_deps="$debian_deps git" debian_deps="$debian_deps libevent-dev" debian_deps="$debian_deps libgeoip-dev" debian_deps="$debian_deps libssl-dev" debian_deps="$debian_deps libtool" debian_deps="$debian_deps make" debian_deps="$debian_deps python" debian_deps="$debian_deps python-pip" debian_deps="$debian_deps wget" pip_deps="$pip_deps cpp-coveralls" subr_finalize() { if [ "$COVERALLS_REPO_TOKEN" != "" ]; then $HOME/.local/bin/coveralls \ --gcov-options '\-lp' \ --build-root . \ --exclude include/measurement_kit/ext \ --exclude include/private/ext \ --exclude src/libmeasurement_kit/ext \ --exclude src/libmeasurement_kit/portable \ --exclude src/measurement_kit \ --exclude example \ --exclude third_party \ --exclude builtin \ > /dev/null; fi } measurement-kit-0.7.1/build/docker/spec/valgrind-clang000066400000000000000000000011661315356162600227600ustar00rootroot00000000000000#!/bin/sh set -e export CPP="clang -E" export CC="clang" export CXX="clang++" export CXXFLAGS="-stdlib=libc++" export pkg_make_check_rule="run-valgrind-docker" debian_deps="$debian_deps autoconf" debian_deps="$debian_deps automake" debian_deps="$debian_deps clang" debian_deps="$debian_deps git" debian_deps="$debian_deps libc++-dev" debian_deps="$debian_deps libc++abi-dev" debian_deps="$debian_deps libevent-dev" debian_deps="$debian_deps libgeoip-dev" debian_deps="$debian_deps libssl-dev" debian_deps="$debian_deps libtool" debian_deps="$debian_deps make" debian_deps="$debian_deps valgrind" debian_deps="$debian_deps wget" measurement-kit-0.7.1/build/docker/spec/valgrind-gcc000066400000000000000000000007741315356162600224340ustar00rootroot00000000000000#!/bin/sh set -e export CPP="gcc -E" export CC="gcc" export CXX="g++" export pkg_make_check_rule="run-valgrind-docker" debian_deps="$debian_deps autoconf" debian_deps="$debian_deps automake" debian_deps="$debian_deps g++" debian_deps="$debian_deps git" debian_deps="$debian_deps libevent-dev" debian_deps="$debian_deps libgeoip-dev" debian_deps="$debian_deps libssl-dev" debian_deps="$debian_deps libtool" debian_deps="$debian_deps make" debian_deps="$debian_deps valgrind" debian_deps="$debian_deps wget" measurement-kit-0.7.1/build/docker/valgrind-clang000077500000000000000000000002161315356162600220240ustar00rootroot00000000000000#!/bin/sh set -e REPOROOT=$(cd $(dirname $(dirname $(dirname $0))) && pwd -P) $REPOROOT/build/docker/script/setup ubuntu:zesty valgrind-clang measurement-kit-0.7.1/build/docker/valgrind-gcc000077500000000000000000000002161315356162600214740ustar00rootroot00000000000000#!/bin/sh set -e REPOROOT=$(cd $(dirname $(dirname $(dirname $0))) && pwd -P) $REPOROOT/build/docker/script/setup ubuntu:yakkety valgrind-gcc measurement-kit-0.7.1/build/fetch-dep000077500000000000000000000017531315356162600175330ustar00rootroot00000000000000#!/bin/sh args=`getopt ps: $*` if [ $? -ne 0 ]; then echo "usage: $0 [-p] [-s regex]" 1>&2 exit 1 fi set -- $args while [ $# -ne 0 ]; do case "$1" in -p) arguments="$arguments -p" shift ;; -s) arguments="$arguments -s $2" shift shift ;; --) shift break ;; *) echo "usage: $0 [-p] [-s regex]" 1>&2 exit 1 esac done if [ $# -ne 0 ]; then echo "usage: $0 [-p] [-s regex]" 1>&2 exit 1 fi set -e pkg_rootdir=$(cd $(dirname $(dirname $0)) && pwd -P) cd $pkg_rootdir if [ "$pkg_prefix" = "" ]; then pkg_prefix="$pkg_rootdir/builtin" fi npm install download-github-release ./node_modules/.bin/download-github-release $arguments \ measurement-kit dependencies for file in *.tgz; do gpg --verify $file.asc $file install -d $pkg_prefix tar -C $pkg_prefix -xf $file done measurement-kit-0.7.1/build/get-geoip000077500000000000000000000000751315356162600175500ustar00rootroot00000000000000#!/bin/sh set -e . ./build/autogen.d/geoip autogen_get_geoip measurement-kit-0.7.1/build/ios/000077500000000000000000000000001315356162600165325ustar00rootroot00000000000000measurement-kit-0.7.1/build/ios/.gitignore000066400000000000000000000000321315356162600205150ustar00rootroot00000000000000.DS_Store *.tgz *.tgz.asc measurement-kit-0.7.1/build/ios/Frameworks/000077500000000000000000000000001315356162600206525ustar00rootroot00000000000000measurement-kit-0.7.1/build/ios/Frameworks/.gitignore000066400000000000000000000000021315356162600226320ustar00rootroot00000000000000* measurement-kit-0.7.1/build/ios/archive-deps000077500000000000000000000011161315356162600210310ustar00rootroot00000000000000#!/bin/sh set -e ROOTDIR=$(cd $(dirname $0)/../.. && pwd -P) cd $ROOTDIR/build/ios # Do not ship *.la files that would break the build and, while there, also # remove directories that we don't need for cross compiling MK find tmp -type f -name \*.la -exec rm {} \; find tmp -type f -name \*.pc -exec rm {} \; find tmp -type d -depth -name share -exec rm -rf {} \; find tmp -type d -depth -name bin -exec rm -rf {} \; find tmp -type d -depth -name pkgconfig -exec rm -rf {} \; now=`date +%Y%m%dT%H%M%SZ` tar -czf ios-dependencies-$now.tgz tmp $ROOTDIR/build/sign ios-dependencies-$now.tgz measurement-kit-0.7.1/build/ios/archive-library000077500000000000000000000011031315356162600215360ustar00rootroot00000000000000#!/bin/sh set -e ROOTDIR=$(cd $(dirname $0)/../.. && pwd -P) cd $ROOTDIR D=build/ios V=0.7.1 # Do not ship *.la files that would break the build and, while there, also # remove directories that we don't need for cross compiling MK find $D/tmp -type f -name \*.la -exec rm {} \; find $D/tmp -type f -name \*.pc -exec rm {} \; find $D/tmp -type d -depth -name share -exec rm -rf {} \; find $D/tmp -type d -depth -name bin -exec rm -rf {} \; find $D/tmp -type d -depth -name pkgconfig -exec rm -rf {} \; tar -czf ios_binaries-$V.tgz $D/tmp $ROOTDIR/build/sign ios_binaries-$V.tgz measurement-kit-0.7.1/build/ios/build-frameworks000077500000000000000000000034601315356162600217400ustar00rootroot00000000000000#!/bin/sh set -e ROOTDIR=$(cd $(dirname $0) && pwd -P) EXTLIBRARIES="libevent libevent_pthreads libevent_openssl libcrypto libssl libGeoIP" list_libs() { input_lib=$1 libs="" for arch in i386 x86_64; do if [ -f tmp/iphonesimulator/$arch/lib/$input_lib.a ]; then libs="$libs tmp/iphonesimulator/$arch/lib/$input_lib.a" fi done for arch in arm64 armv7s armv7; do if [ -f tmp/iphoneos/$arch/lib/$input_lib.a ]; then libs="$libs tmp/iphoneos/$arch/lib/$input_lib.a" fi done echo $libs } ( cd "$ROOTDIR" # Clean old frameworks (if any) rm -rf Frameworks/* # Create framework folders for lib in $EXTLIBRARIES measurement_kit; do mkdir Frameworks/$lib.framework done # Copying first headers we find. This has no implications because # measurement-kit uses no machine-dependent headers. for platform in iphoneos iphonesimulator; do for arch in i386 x86_64 armv7 armv7s arm64; do if [ -d tmp/$platform/$arch/include/measurement_kit ]; then cp -Rp tmp/$platform/$arch/include/measurement_kit \ Frameworks/measurement_kit.framework/Headers break fi done done # Lipo external libraries for lib in $EXTLIBRARIES; do lipo -create -output Frameworks/$lib.framework/$lib `list_libs $lib` done # Lipo measurement-kit library lipo -create -output Frameworks/measurement_kit.framework/measurement_kit \ `list_libs libmeasurement_kit` # Create fake header to make CocoaPod happy for lib in $EXTLIBRARIES; do install -d Frameworks/$lib.framework/Headers echo "/* Make CocoaPod happy */" > \ Frameworks/$lib.framework/Headers/dummy_header.h done ) measurement-kit-0.7.1/build/ios/cross000077500000000000000000000032321315356162600176110ustar00rootroot00000000000000#!/bin/sh set -e if [ $# -lt 2 ]; then echo "$0 iphonesimulator i386|x86_64 [command [args...]]" 1>&2 echo "$0 iphoneos armv7|armv7s|arm64 [command [args...]]" 1>&2 exit 1 fi PLATFORM=$1 shift ARCH=$1 shift MINIOSVERSION="9.0" if [ "$PLATFORM" = "iphoneos" ]; then EXTRA_CONFIG="--host=arm-apple-darwin --target=arm-apple-darwin --disable-shared" MINVERSION="-miphoneos-version-min=$MINIOSVERSION" elif [ "$ARCH" = "i386" ]; then EXTRA_CONFIG="--host=i386-apple-darwin --target=i386-apple-darwin --disable-shared" MINVERSION="-mios-simulator-version-min=$MINIOSVERSION" elif [ "$ARCH" = "x86_64" ]; then EXTRA_CONFIG="--host=x86_64-apple-darwin --target=x86_64-apple-darwin --disable-shared" MINVERSION="-mios-simulator-version-min=$MINIOSVERSION" else echo "$0: unsupported configuration" 1>&2 exit 1 fi echo "" echo "Cross compiling for $PLATFORM and $ARCH" ROOTDIR=$(cd $(dirname $0) && pwd -P) SOURCEDIR="$ROOTDIR/../../" DESTDIR="$ROOTDIR/tmp" export CC="$(xcrun -find -sdk ${PLATFORM} cc)" export CXX="$(xcrun -find -sdk ${PLATFORM} g++)" export CPPFLAGS="-arch ${ARCH} -isysroot $(xcrun -sdk ${PLATFORM} --show-sdk-path)" export CFLAGS="-arch ${ARCH} $MINVERSION -isysroot $(xcrun -sdk ${PLATFORM} --show-sdk-path)" export CXXFLAGS="-arch ${ARCH} $MINVERSION -isysroot $(xcrun -sdk ${PLATFORM} --show-sdk-path)" export LDFLAGS="-arch ${ARCH} $MINVERSION -isysroot $(xcrun -sdk ${PLATFORM} --show-sdk-path)" export pkg_configure_flags="$EXTRA_CONFIG" export pkg_make_flags="V=0 $pkg_make_flags" export pkg_prefix="$DESTDIR" export pkg_cross="${PLATFORM}" export pkg_cross_arch="${ARCH}" if [ $# -gt 0 ]; then $@ else env fi measurement-kit-0.7.1/build/ios/dependency000077500000000000000000000012371315356162600206010ustar00rootroot00000000000000#!/bin/sh set -e if [ "$1" = "" ]; then echo "usage: $0 spec" 1>&2 exit 1 fi ROOTDIR=$(cd $(dirname $0)/../.. && pwd -P) BUILDDIR=$ROOTDIR/build IOSDIR=$BUILDDIR/ios echo "" echo "Cross-compiling $1 for all platforms and archs" $IOSDIR/cross iphonesimulator i386 $BUILDDIR/dependency $1 $IOSDIR/cross iphonesimulator x86_64 $BUILDDIR/dependency $1 $IOSDIR/cross iphoneos armv7 $BUILDDIR/dependency $1 $IOSDIR/cross iphoneos armv7s $BUILDDIR/dependency $1 $IOSDIR/cross iphoneos arm64 $BUILDDIR/dependency $1 # Install spec so we know what version was used to build the archive install -d $IOSDIR/tmp/spec install -m644 $BUILDDIR/spec/$1 $IOSDIR/tmp/spec/$1 measurement-kit-0.7.1/build/ios/fetch-dep000077500000000000000000000001611315356162600203150ustar00rootroot00000000000000#!/bin/sh set -e ROOTDIR=$(cd $(dirname $0) && pwd -P) export pkg_prefix=$ROOTDIR/tmp $ROOTDIR/../fetch-dep "$@" measurement-kit-0.7.1/build/ios/library000077500000000000000000000016071315356162600201300ustar00rootroot00000000000000#!/bin/sh set -e ROOTDIR=$(cd `dirname "$0"` && pwd -P) RELEASE_URL=https://github.com/measurement-kit/measurement-kit/releases/download/v0.7.1/ios_binaries-0.7.1.tgz RELEASE_FILE=$(basename $RELEASE_URL) if wget $RELEASE_URL; then wget $RELEASE_URL.asc gpg --verify $RELEASE_FILE.asc tar xzf $RELEASE_FILE rm $RELEASE_FILE $RELEASE_FILE.asc $ROOTDIR/build-frameworks exit 0 fi echo "Downloading and verifying precompiled dependencies from github" ( set -e # just in case cd $ROOTDIR DEPS_URL=https://github.com/measurement-kit/dependencies/releases/download/2017-07-12/ios-dependencies-20170714T172936Z.tgz DEPS_FILE=$(basename $DEPS_URL) curl --progress-bar -LO $DEPS_URL curl --progress-bar -LO $DEPS_URL.asc gpg --verify $DEPS_FILE.asc tar -xzf $DEPS_FILE rm $DEPS_FILE $DEPS_FILE.asc ) $ROOTDIR/dependency mk $ROOTDIR/build-frameworks measurement-kit-0.7.1/build/ios/tmp/000077500000000000000000000000001315356162600173325ustar00rootroot00000000000000measurement-kit-0.7.1/build/ios/tmp/.gitignore000066400000000000000000000000731315356162600213220ustar00rootroot00000000000000# Directory used to compile, ignore everything inside it * measurement-kit-0.7.1/build/patch/000077500000000000000000000000001315356162600170375ustar00rootroot00000000000000measurement-kit-0.7.1/build/patch/pre-autogen/000077500000000000000000000000001315356162600212655ustar00rootroot00000000000000measurement-kit-0.7.1/build/patch/pre-autogen/geoip/000077500000000000000000000000001315356162600223705ustar00rootroot00000000000000measurement-kit-0.7.1/build/patch/pre-autogen/geoip/common/000077500000000000000000000000001315356162600236605ustar00rootroot00000000000000measurement-kit-0.7.1/build/patch/pre-autogen/geoip/common/000.patch000066400000000000000000000004711315356162600252020ustar00rootroot00000000000000diff --git a/Makefile.am b/Makefile.am index ad9b1ea..28c35c0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,10 +4,7 @@ ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = foreign SUBDIRS = \ - libGeoIP \ - apps \ - test \ - man + libGeoIP pkgconfigdir = $(libdir)/pkgconfig/ nodist_pkgconfig_DATA = geoip.pc measurement-kit-0.7.1/build/patch/pre-autogen/libevent/000077500000000000000000000000001315356162600230755ustar00rootroot00000000000000measurement-kit-0.7.1/build/patch/pre-autogen/libevent/common/000077500000000000000000000000001315356162600243655ustar00rootroot00000000000000measurement-kit-0.7.1/build/patch/pre-autogen/libevent/common/000.patch000066400000000000000000000072171315356162600257140ustar00rootroot00000000000000diff --git a/Makefile.am b/Makefile.am index 0f741bc..3a3eee0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -91,10 +91,6 @@ VERSION_INFO = 6:2:0 # is user-visible, and so we can pretty much guarantee that release # series won't be binary-compatible. -if INSTALL_LIBEVENT -dist_bin_SCRIPTS = event_rpcgen.py -endif - pkgconfigdir=$(libdir)/pkgconfig LIBEVENT_PKGCONFIG=libevent.pc libevent_core.pc libevent_extra.pc @@ -130,7 +126,6 @@ endif if INSTALL_LIBEVENT lib_LTLIBRARIES = $(LIBEVENT_LIBS_LA) -pkgconfig_DATA = $(LIBEVENT_PKGCONFIG) else noinst_LTLIBRARIES = $(LIBEVENT_LIBS_LA) endif @@ -143,8 +138,6 @@ CLEANFILES= DISTCLEANFILES= BUILT_SOURCES = include include/include.am -include sample/include.am -include test/include.am if BUILD_WIN32 diff --git a/configure.ac b/configure.ac index 7528d37..24b65dc 100644 --- a/configure.ac +++ b/configure.ac @@ -121,10 +121,6 @@ AC_ARG_ENABLE([function-sections], AC_ARG_ENABLE([verbose-debug], AS_HELP_STRING([--enable-verbose-debug, verbose debug logging]), [], [enable_verbose_debug=no]) -AC_ARG_ENABLE([clock-gettime], - AS_HELP_STRING(--disable-clock-gettime, do not use clock_gettime even if it is available), - [], [enable_clock_gettime=yes]) - AC_PROG_LIBTOOL @@ -141,10 +137,6 @@ dnl Checks for libraries. AC_SEARCH_LIBS([inet_ntoa], [nsl]) AC_SEARCH_LIBS([socket], [socket]) AC_SEARCH_LIBS([inet_aton], [resolv]) -if test "x$enable_clock_gettime" = "xyes"; then - AC_SEARCH_LIBS([clock_gettime], [rt]) - AC_CHECK_FUNCS([clock_gettime]) -fi AC_SEARCH_LIBS([sendfile], [sendfile]) dnl - check if the macro _WIN32 is defined on this compiler. @@ -342,6 +334,7 @@ AC_CHECK_FUNCS([ \ accept4 \ arc4random \ arc4random_buf \ + arc4random_addrandom \ eventfd \ epoll_create1 \ fcntl \ diff --git a/evutil_rand.c b/evutil_rand.c index 046a14b..3aef9cb 100644 --- a/evutil_rand.c +++ b/evutil_rand.c @@ -184,6 +184,24 @@ ev_arc4random_buf(void *buf, size_t n) arc4random_buf(buf, n); } +/* + * The arc4random included in libevent implements arc4random_addrandom(). + * + * OpenBSD libc/crypt/arc4random.c migrated to ChaCha20 since 1.25 and + * have removed arc4random_addrandom() since 1.26. Since then, other libcs + * followed suit (e.g. Android's own libc). But libevent's arc4random.c + * copy still implement arc4random_addrandom(). + * + * See also: + * + * - https://github.com/measurement-kit/libevent/commit/8b275d967d7ffd95d5cc12069aef35669126c6d9 + * - https://bugzilla.mozilla.org/show_bug.cgi?id=931354 + * - https://bug931354.bmoattachments.org/attachment.cgi?id=829728 + */ +#ifndef EVENT__HAVE_ARC4RANDOM_ADDRANDOM +#define EVENT__HAVE_ARC4RANDOM_ADDRANDOM 1 +#endif + #endif /* } !EVENT__HAVE_ARC4RANDOM */ void @@ -195,8 +213,10 @@ evutil_secure_rng_get_bytes(void *buf, size_t n) void evutil_secure_rng_add_bytes(const char *buf, size_t n) { +#if defined EVENT__HAVE_ARC4RANDOM_ADDRANDOM arc4random_addrandom((unsigned char*)buf, n>(size_t)INT_MAX ? INT_MAX : (int)n); +#endif } void diff --git a/openssl-compat.h b/openssl-compat.h index 69afc71..8e3556a 100644 --- a/openssl-compat.h +++ b/openssl-compat.h @@ -1,7 +1,7 @@ #ifndef OPENSSL_COMPAT_H #define OPENSSL_COMPAT_H -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER static inline BIO_METHOD *BIO_meth_new(int type, const char *name) { @@ -30,6 +30,6 @@ static inline BIO_METHOD *BIO_meth_new(int type, const char *name) #define TLS_method SSLv23_method -#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER */ #endif /* OPENSSL_COMPAT_H */ measurement-kit-0.7.1/build/patch/pre-autogen/libressl/000077500000000000000000000000001315356162600231045ustar00rootroot00000000000000measurement-kit-0.7.1/build/patch/pre-autogen/libressl/common/000077500000000000000000000000001315356162600243745ustar00rootroot00000000000000measurement-kit-0.7.1/build/patch/pre-autogen/libressl/common/000.patch000066400000000000000000000010621315356162600257130ustar00rootroot00000000000000From f9e21798fb795188a21ac7dd5ed0d9b6adf29f8c Mon Sep 17 00:00:00 2001 From: AntonioLangiu Date: Fri, 22 Apr 2016 16:29:36 +0200 Subject: [PATCH 505/505] build just needed subdir --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 48da18b..9164e20 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = crypto ssl tls include apps tests man +SUBDIRS = crypto ssl include ACLOCAL_AMFLAGS = -I m4 pkgconfigdir = $(libdir)/pkgconfig -- 2.8.1 measurement-kit-0.7.1/build/patch/pre-autogen/libressl/common/002.patch000066400000000000000000000011701315356162600257150ustar00rootroot00000000000000diff --git a/update.sh b/update.sh index 0853c6b..b734773 100755 --- a/update.sh +++ b/update.sh @@ -5,16 +5,8 @@ openbsd_branch=`cat OPENBSD_BRANCH` # pull in latest upstream code echo "pulling upstream openbsd source" -if [ ! -d openbsd ]; then - if [ -z "$LIBRESSL_GIT" ]; then - git clone https://github.com/libressl-portable/openbsd.git - else - git clone $LIBRESSL_GIT/openbsd - fi -fi -(cd openbsd - git checkout $openbsd_branch - git pull --rebase) +git clone --single-branch --depth 2 --branch $openbsd_branch \ + https://github.com/libressl-portable/openbsd.git # setup source paths CWD=`pwd` measurement-kit-0.7.1/build/patch/pre-autogen/libressl/common/003.patch000066400000000000000000000022631315356162600257220ustar00rootroot00000000000000diff --git a/m4/check-libc.m4 b/m4/check-libc.m4 index 3e4d3af..ab42f77 100644 --- a/m4/check-libc.m4 +++ b/m4/check-libc.m4 @@ -2,10 +2,26 @@ AC_DEFUN([CHECK_LIBC_COMPAT], [ # Check for libc headers AC_CHECK_HEADERS([err.h readpassphrase.h]) # Check for general libc functions -AC_CHECK_FUNCS([asprintf getpagesize inet_ntop inet_pton memmem readpassphrase]) +AC_CHECK_FUNCS([asprintf inet_ntop inet_pton memmem readpassphrase]) AC_CHECK_FUNCS([reallocarray recallocarray]) AC_CHECK_FUNCS([strlcat strlcpy strndup strnlen strsep strtonum]) AC_CHECK_FUNCS([timegm _mkgmtime]) + +dnl Note: in Android < 21 getpagesize() is defined inline. As such, the test +dnl for getpagesize() should include . +AC_MSG_CHECKING([for getpagesize]) +AC_LINK_IFELSE([AC_LANG_PROGRAM([ + #include +], [ + return getpagesize(); +])], [ + ac_cv_func_getpagesize="yes" + AC_MSG_RESULT([yes]) +], [ + ac_cv_func_getpagesize="no" + AC_MSG_RESULT([no]) +]) + AM_CONDITIONAL([HAVE_ASPRINTF], [test "x$ac_cv_func_asprintf" = xyes]) AM_CONDITIONAL([HAVE_GETPAGESIZE], [test "x$ac_cv_func_getpagesize" = xyes]) AM_CONDITIONAL([HAVE_INET_NTOP], [test "x$ac_cv_func_inet_ntop" = xyes]) measurement-kit-0.7.1/build/release000077500000000000000000000013021315356162600173020ustar00rootroot00000000000000#!/bin/sh set -e if [ $# -ne 2 ]; then echo "usage: $0 old-version new-version" 1>&2 exit 1 fi old_version=$1 new_version=$2 for file in configure.ac doc/api/common/version.md doc/index.md \ include/measurement_kit/common/version.h build/spec/mk \ measurement_kit.podspec build/ios/library \ build/ios/archive-library; do cp $file $file.old sed "s/$old_version/$new_version/g" $file.old > $file rm $file.old done mv ChangeLog.md ChangeLog.md.old echo "# MeasurementKit $new_version [`date +%Y-%m-%d`]" > ChangeLog.md echo "" >> ChangeLog.md cat ChangeLog.md.old >> ChangeLog.md rm ChangeLog.md.old measurement-kit-0.7.1/build/sign000077500000000000000000000001711315356162600166250ustar00rootroot00000000000000#!/bin/sh set -e while [ $# -gt 0 ]; do gpg -u 738877AA6C829F26A431C5F480B691277733D95B -b --armor $1 shift done measurement-kit-0.7.1/build/spec/000077500000000000000000000000001315356162600166725ustar00rootroot00000000000000measurement-kit-0.7.1/build/spec/Catch000066400000000000000000000004131315356162600176350ustar00rootroot00000000000000pkg_name=Catch pkg_repository=https://github.com/philsquared/Catch.git pkg_branch_or_tag=v1.10.0 pkg_steps=install pkg_install() { echo "Installing $pkg_name header $pkg_branch_or_tag in MK sources" cp single_include/catch.hpp ../../../include/private/ext } measurement-kit-0.7.1/build/spec/builtin_ca_bundle000066400000000000000000000010401315356162600222520ustar00rootroot00000000000000 pkg_name=builtin_ca_bundle pkg_repository="" pkg_branch_or_tag="2017-06-07" pkg_steps="install" pkg_install() { wget https://curl.haxx.se/ca/cacert-$pkg_branch_or_tag.pem ofile="src/libmeasurement_kit/net/builtin_ca_bundle.cpp" echo "Installing cacert-$pkg_branch_or_tag.pem in MK sources" ./build/bundle-ca $pkg_branch_or_tag cacert-$pkg_branch_or_tag.pem $ofile clang-format -i $ofile # Also save a copy that would be used for regress testing cp cacert-$pkg_branch_or_tag.pem test/fixtures/saved_ca_bundle.pem } measurement-kit-0.7.1/build/spec/citrus000066400000000000000000000004221315356162600201240ustar00rootroot00000000000000pkg_name=citrus pkg_repository=https://github.com/openbsd/src pkg_branch_or_tag=master pkg_steps=install pkg_install() { cp lib/libc/citrus/citrus_ctype.h ../../../include/private/portable cp lib/libc/citrus/citrus_utf8.c ../../../src/libmeasurement_kit/portable } measurement-kit-0.7.1/build/spec/geoip000066400000000000000000000005271315356162600177240ustar00rootroot00000000000000pkg_name=geoip pkg_repository=https://github.com/maxmind/geoip-api-c.git pkg_branch_or_tag=v1.6.11 # Fix for the "missing _rpl_malloc() symbol" issue when cross-linking # See export ac_cv_func_malloc_0_nonnull=yes export ac_cv_func_realloc_0_nonnull=yes measurement-kit-0.7.1/build/spec/http-parser000066400000000000000000000004761315356162600210750ustar00rootroot00000000000000pkg_name=http-parser pkg_repository=https://github.com/nodejs/http-parser.git pkg_branch_or_tag=v2.7.1 pkg_steps=install pkg_install() { echo "Installing $pkg_name files $pkg_branch_or_tag in MK sources" cp http_parser.h ../../../include/private/ext cp http_parser.c ../../../src/libmeasurement_kit/ext } measurement-kit-0.7.1/build/spec/json000066400000000000000000000003671315356162600175740ustar00rootroot00000000000000pkg_name=json pkg_repository=https://github.com/nlohmann/json.git pkg_branch_or_tag=v2.1.1 pkg_steps=install pkg_install() { echo "Installing $pkg_name header $pkg_tag in MK sources" cp src/json.hpp ../../../include/measurement_kit/ext } measurement-kit-0.7.1/build/spec/libevent000066400000000000000000000004511315356162600204250ustar00rootroot00000000000000pkg_name=libevent pkg_repository=https://github.com/libevent/libevent pkg_branch_or_tag=patches-2.1 pkg_tip=e7ff4ef2b4fc950a765008c18e74281cdb5e7668 export CPPFLAGS="$CPPFLAGS -I$pkg_prefix/$pkg_cross/$pkg_cross_arch/include" export LDFLAGS="$LDFLAGS -L$pkg_prefix/$pkg_cross/$pkg_cross_arch/lib" measurement-kit-0.7.1/build/spec/libressl000066400000000000000000000001541315356162600204340ustar00rootroot00000000000000pkg_name=libressl pkg_repository=https://github.com/libressl-portable/portable.git pkg_branch_or_tag=v2.5.5 measurement-kit-0.7.1/build/spec/mk000066400000000000000000000004521315356162600172250ustar00rootroot00000000000000pkg_name=measurement-kit pkg_branch_or_tag=v0.7.1 _dd=${pkg_prefix}/${pkg_cross}/${pkg_cross_arch} pkg_configure_flags="--disable-examples --disable-shared --disable-binaries --with-openssl=${_dd} --with-libevent=${_dd} --with-geoip=${_dd} $pkg_configure_flags" pkg_make_install_rule=install-strip measurement-kit-0.7.1/build/spec/strtonum000066400000000000000000000007221315356162600205110ustar00rootroot00000000000000 # Note: here the pkg_name is libressl such that we only need to clone once # the library rather than multiple times for each "package" based on it pkg_name=libressl pkg_repository=https://github.com/libressl-portable/portable.git pkg_branch_or_tag=v2.5.5 pkg_steps="autogen install" pkg_install() { echo "Installing strtonum.c $pkg_branch_or_tag in MK sources" cp openbsd/src/lib/libc/stdlib/strtonum.c \ ../../../src/libmeasurement_kit/portable } measurement-kit-0.7.1/build/spec/tls_verify000066400000000000000000000005441315356162600210060ustar00rootroot00000000000000pkg_name=tls_verify pkg_repository="" pkg_branch_or_tag=master pkg_steps="install" pkg_install() { echo "Installing tls/tls_verify.c $pkg_branch_or_tag in MK sources" prefix=https://raw.githubusercontent.com/libressl-portable/openbsd wget $prefix/$pkg_branch_or_tag/src/lib/libtls/tls_verify.c mv tls_verify.c src/libmeasurement_kit/ext } measurement-kit-0.7.1/build/tarball000077500000000000000000000014311315356162600173060ustar00rootroot00000000000000#!/bin/sh set -e if [ $# -ne 1 ]; then echo "usage: $0 tag" 1>&2 exit 1 fi tag=$1 if echo $tag | grep -q '^v'; then v=`echo $tag | sed 's/^v//g'` else v=$tag fi # Nested directories so we're sure also install-sh is installed because it # is not found in the parent or parent parent directory git archive --prefix=measurement-kit-$v/ $tag > _mk.tgz install -d a/b/c ( cd a/b/c tar -xf ../../../_mk.tgz rm ../../../_mk.tgz cd measurement-kit-$v ./autogen.sh --no-geoip # do not distribute the GeoIP database cd .. tar -czf measurement-kit-$v.tar.gz measurement-kit-$v gpg -u 738877AA6C829F26A431C5F480B691277733D95B -b --armor measurement-kit-$v.tar.gz ) mv a/b/c/measurement-kit-$v.tar.gz.asc . mv a/b/c/measurement-kit-$v.tar.gz . rm -rf a/b/c measurement-kit-0.7.1/build/valgrind/000077500000000000000000000000001315356162600175465ustar00rootroot00000000000000measurement-kit-0.7.1/build/valgrind/openssl.supp000066400000000000000000000030111315356162600221350ustar00rootroot00000000000000{ Memcheck:Addr4 fun:tls_check_name fun:_ZNSt17_Function_handlerIFvN2mk5ErrorEP11buffereventEZNS0_3net11connect_sslES3_P6ssl_stSsSt8functionIS4_ENS0_3VarINS0_7ReactorEEENSA_INS0_6LoggerEEEEUlS1_S3_E_E9_M_invokeERKSt9_Any_dataOS1_OS3_ fun:mk_bufferevent_on_event fun:bufferevent_run_deferred_callbacks_locked fun:event_process_active_single_queue fun:event_base_loop fun:_ZN2mk8libevent11poller_loopIXadL_Z9event_newEEXadL_Z10event_freeEEXadL_Z9event_addEEXadL_Z19event_base_dispatchEEEEvNS_3VarI10event_baseEEPNS0_6PollerE fun:_ZN2mk8libevent6Poller3runEv fun:_ZL31____C_A_T_C_H____T_E_S_T____* fun:_ZN5Catch8runTestsERKNS_3PtrINS_6ConfigEEE fun:main } { Memcheck:Addr4 fun:tls_check_name fun:_ZNSt17_Function_handlerIFvN2mk5ErrorEP11buffereventEZNS0_3net11connect_sslES3_P6ssl_stSsSt8functionIS4_ENS0_3VarINS0_7ReactorEEENSA_INS0_6LoggerEEEEUlS1_S3_E_E9_M_invokeERKSt9_Any_dataOS1_OS3_ fun:mk_bufferevent_on_event fun:bufferevent_run_deferred_callbacks_locked fun:event_process_active_single_queue fun:event_base_loop fun:_ZN2mk8libevent11poller_loopIXadL_Z9event_newEEXadL_Z10event_freeEEXadL_Z9event_addEEXadL_Z19event_base_dispatchEEEEvNS_3VarI10event_baseEEPNS0_6PollerE fun:_ZN2mk8libevent6Poller3runEv fun:_ZN2mk7Reactor23loop_with_initial_eventESt8functionIFvvEE fun:_ZL31____C_A_T_C_H____T_E_S_T____* fun:_ZN5Catch8runTestsERKNS_3PtrINS_6ConfigEEE fun:main } measurement-kit-0.7.1/build/valgrind/strlen.supp000066400000000000000000000066131315356162600217740ustar00rootroot00000000000000{ Memcheck:Cond fun:strlen fun:length fun:_ZSt13regex_replaceISt20back_insert_iteratorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEN9__gnu_cxx17__normal_iteratorIPKcS6_EENS1_12regex_traitsIcEEcET_SF_T0_SG_RKNS1_11basic_regexIT2_T1_EEPKSI_NSt15regex_constants15match_flag_typeE fun:regex_replace >, __gnu_cxx::__normal_iterator >, std::__cxx11::regex_traits, char, std::char_traits, std::allocator > fun:regex_replace, char, std::char_traits, std::allocator, std::char_traits, std::allocator > fun:process_input_filepaths_impl<&check_variable_expanded, &mk::nettests::readline_, &mk::nettests::randomize_input_> fun:_ZL30____C_A_T_C_H____T_E_S_T____37v fun:invoke fun:_ZN5Catch10RunContext20invokeActiveTestCaseEv fun:_ZN5Catch10RunContext14runCurrentTestERNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_ fun:_ZN5Catch10RunContext7runTestERKNS_8TestCaseE fun:_ZN5Catch8runTestsERKNS_3PtrINS_6ConfigEEE fun:_ZN5Catch7Session3runEv fun:run fun:main } { Memcheck:Cond fun:strlen fun:length fun:_ZSt13regex_replaceISt20back_insert_iteratorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEN9__gnu_cxx17__normal_iteratorIPKcS6_EENS1_12regex_traitsIcEEcET_SF_T0_SG_RKNS1_11basic_regexIT2_T1_EEPKSI_NSt15regex_constants15match_flag_typeE fun:regex_replace >, __gnu_cxx::__normal_iterator >, std::__cxx11::regex_traits, char, std::char_traits, std::allocator > fun:regex_replace, char, std::char_traits, std::allocator, std::char_traits, std::allocator > fun:process_input_filepaths_impl fun:_ZL30____C_A_T_C_H____T_E_S_T____37v fun:invoke fun:invoke fun:invokeActiveTestCase fun:runCurrentTest fun:runTest fun:_ZN5Catch8runTestsERKNS_3PtrINS_6ConfigEEE fun:run fun:run fun:main } { Memcheck:Cond fun:strlen fun:length fun:_ZSt13regex_replaceISt20back_insert_iteratorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEN9__gnu_cxx17__normal_iteratorIPKcS6_EENS1_12regex_traitsIcEEcET_SF_T0_SG_RKNS1_11basic_regexIT2_T1_EEPKSI_NSt15regex_constants15match_flag_typeE fun:regex_replace >, __gnu_cxx::__normal_iterator >, std::__cxx11::regex_traits, char, std::char_traits, std::allocator > fun:regex_replace, char, std::char_traits, std::allocator, std::char_traits, std::allocator > fun:process_input_filepaths_impl<&check_variable_expanded, &mk::nettests::readline_, &mk::nettests::randomize_input_> fun:_ZL29____C_A_T_C_H____T_E_S_T____0v fun:invoke fun:invokeActiveTestCase fun:_ZN5Catch10RunContext14runCurrentTestERNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_ fun:_ZN5Catch10RunContext7runTestERKNS_8TestCaseE fun:_ZN5Catch8runTestsERKNS_3PtrINS_6ConfigEEE fun:_ZN5Catch7Session3runEv fun:run fun:main } measurement-kit-0.7.1/circle.yml000066400000000000000000000002321315356162600166220ustar00rootroot00000000000000machine: services: - docker general: branches: only: - master - stable test: override: - ./build/ci/circle valgrind-clang measurement-kit-0.7.1/configure.ac000066400000000000000000000044641315356162600171370ustar00rootroot00000000000000# Part of measurement-kit . # Measurement-kit is free software. See AUTHORS and LICENSE for more # information on the copying conditions. # Autoconf requirements AC_INIT(measurement_kit, 0.7.1, bassosimone@gmail.com) # information on the package AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_MACRO_DIR([m4]) # Travis uses Ubuntu 12.04 where the default automake was 1.11 in which # by default tests were run in serial mode; as such, the LOG_COMPILER hack # used to run tests using Valgrind was not working because automake 1.11 # wasn't honouring the LOG_COMPILER definition in the Makefile. # # Force parallel tests to make sure we can run tests through Valgrind. AM_INIT_AUTOMAKE([parallel-tests 1.11]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) LT_INIT AC_CONFIG_HEADERS([config.h]) AM_CONDITIONAL([BUILD_TESTS], [test "yes" = "yes"]) # for now, build always AC_CANONICAL_HOST AC_PROG_INSTALL # Must be before AC_PROG_CXX (see http://stackoverflow.com/questions/11703709) MK_AM_ENABLE_COVERAGE MK_AM_ADD_COVERAGE_FLAGS_IF_NEEDED MK_AM_DISABLE_BINARIES MK_AM_DISABLE_EXAMPLES MK_AM_DISABLE_INTEGRATION_TESTS MK_AM_DISABLE_TRACEROUTE # See above comment AC_PROG_CXX if test "`uname`" != "Darwin"; then # Must set -pthread before testing for -levent_pthreads CFLAGS="$CFLAGS -pthread" CXXFLAGS="$CXXFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" elif test "$cross_compiling" != yes; then # On my macOS, /usr/local is not added automatically CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" fi MK_AM_CHECK_LIBC_FUNCS MK_AM_OPENSSL MK_AM_LIBEVENT MK_AM_GEOIP # checks for header files # checks for types # checks for structures # checks for ca-bundle MK_CHECK_CA_BUNDLE # checks for compiler characteristics CPPFLAGS="-I \$(top_srcdir)/include $CPPFLAGS" CFLAGS="-Wall -Wextra -pedantic $CFLAGS" CXXFLAGS="-Wall -Wextra -pedantic $CXXFLAGS" # Force compiling the http_parser in non-strict mode. This allows us to test # partially broken sites like mail.voila.fr that send spaces between the header # key and the separator (i.e. ':'). CPPFLAGS="-DHTTP_PARSER_STRICT=0 $CPPFLAGS" MK_AM_REQUIRE_C99 MK_AM_REQUIRE_CXX14 MK_AM_CXXFLAGS_ADD_WARNINGS # checks for library functions # checks for system services AC_CONFIG_FILES([Makefile]) AC_OUTPUT MK_AM_PRINT_SUMMARY measurement-kit-0.7.1/doc/000077500000000000000000000000001315356162600154065ustar00rootroot00000000000000measurement-kit-0.7.1/doc/api/000077500000000000000000000000001315356162600161575ustar00rootroot00000000000000measurement-kit-0.7.1/doc/api/common.md000066400000000000000000000035471315356162600200020ustar00rootroot00000000000000# NAME common — common functionality used by other modules # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include ``` # DESCRIPTION The `common` module contains contains the following submodules: - [aaa_base](common/aaa_base.md): include headers we always need - [callback](common/callback.md): alias for writing callback functions more compactly - [continuation](common/continuation.md): type of function used to restart a function that paused - [delegate](common/delegate.md): member function overridable at runtime - [error](common/error.md): definition of error class and of shared error codes - [error_or](common/error_or.md): maybe-like object containing either a result or an error - [every](common/every.md): call a functor every N seconds - [has_global_factory](common/has_global_factory.md): template decorator to add a global, singleton factory to a class - [lexical_cast](common/lexical_cast.md): lexical cast between scalar values - [maybe](common/maybe.md): maybe-like monad - [locked](common/locked.md): run function with mutex held - [logger](common/logger.md): log messages - [non_copyable](common/non_copyable.md): non copyable class - [non_movable](common/non_movable.md): non movable class - [parallel](common/parallel.md): allows to run continuations in parallel - [platform](common/platform.md): get platform name - [reactor](common/reactor.md): class for dispatching I/O events and timeouts - [settings](common/settings.md): class containing test settings - [settings_entry](common/settings_entry.md): an entry contained by the settings class - [utils](common/utils.md): generic utility functions - [var](common/var.md): shared smart pointer with null pointer checks - [version](common/version.md): MeasurementKit version macro # HISTORY The `common` module appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/common/000077500000000000000000000000001315356162600174475ustar00rootroot00000000000000measurement-kit-0.7.1/doc/api/common/aaa_base.md000066400000000000000000000005601315356162600215060ustar00rootroot00000000000000# NAME aaa_base — Headers we always want to include. # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include ``` # STABILITY 2 - Stable # DESCRIPTION This module just pulls basic C/C++ headers needed by all other modules. # HISTORY The `aaa_base` header appeared in MeasurementKit 0.3.0. measurement-kit-0.7.1/doc/api/common/callback.md000066400000000000000000000010311315356162600215200ustar00rootroot00000000000000# NAME Callback — Syntactic sugar for writing callbacks. # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { template using Callback = std::function; } ``` # STABILITY 2 - Stable # DESCRIPTION The `Callback` alias allows to more compactly writing callbacks and SHOULD be used to indicate one-shot callbacks instead of `std::function`. # HISTORY The `Callback` alias appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/common/continuation.md000066400000000000000000000011051315356162600225000ustar00rootroot00000000000000# NAME Continuation — Syntactic sugar for functions that resume a paused function. # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { template using Continuation = std::function)>; } ``` # STABILITY 2 - Stable # DESCRIPTION The `Continuation` alias allows to more compactly express a function that resumes another function that has paused waiting for explicit continuation. # HISTORY The `Continuation` alias appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/common/delegate.md000066400000000000000000000050001315356162600215360ustar00rootroot00000000000000# NAME Delegate — Function that can modify itself when used as a method. # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { template class Delegate_ { public: Delegate_(); template Delegate_(F); Delegate_(std::function); void operator=(std::function); template void operator=(F); void operator=(std::nullptr_t); operator bool(); template void operator()(Args&& ...); }; template using Delegate = Delegate_; } ``` # STABILITY 2 - Stable # DESCRIPTION The `Delegate` template class is a `std::function` like class that [can change itself without triggering memory errors](https://github.com/measurement-kit/measurement-kit/issues/111). The class is actually implemented using the `Delegate_` class that implements a `std::function<>` with the possibility of changing itself and by the `Delegate` alias that provides syntactic sugar for writing less when declaring delegates. Constructors allow to construct the `Delegate`. The empty constructor creates an empty function that raises `std::bad_function_call` if called. The templated constructor allows to assign a lambda expression to this `Delegate`. Finally, the function constructor allows to assign a `std::function<>` to this `Delegate`. Both the templated and the function constructor shall fail at compile time if it is not possible to initialize the `Delegate` using the lambda or the function. The assignment operators allow to reassign the underlying function wrapped by a `Delegate`. It is safe to call these operators to override the function that the `Delegate` wraps from within the body of the delegate itself. The function assignment operator overrides the underlying function with a newly specified `std::function<>`. The templated assignment operator overrides the underlying function with a lambda expression. The `nullptr` assignment operator resets the underlying function; calling again the `Delegate` would then result into a `std::bad_function_call` exception. Both the templated and the lambda assignments would fail at compile time if types are not compatible. The bool operator returns true if the underlying function is callable and false if attempting to call the delegate would raise `std::bad_function_call`. The call operator allows to call the `Delegate`. # HISTORY The `Delegate` template class appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/common/error.md000066400000000000000000000165221315356162600211300ustar00rootroot00000000000000# NAME Error — Represent and handle errors. # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { class Error : public std::exception { public: Error(); Error(int code); Error(int code, std::string reason); Error(int code, std::string reason, Error child); operator bool() const; bool operator==(int code); bool operator==(Error error); bool operator!=(int code); bool operator!=(Error error); std::string as_ooni_error(); const chat *what() const noexcept override; std::vector> child_errors; int code = 0; std::string reason; }; #define MK_DEFINE_ERR(code_, ClassName_, reason_) \ class ClassName_ : public Error { \ public: \ ClassName_() : Error(code_, reason_) {} \ ClassName_(std::string s) : Error(code_, reason_) { \ this->reason += " "; \ this->reason += s; \ } \ }; MK_DEFINE_ERR(0, NoError, "") MK_DEFINE_ERR(1, GenericError, "") MK_DEFINE_ERR(2, NotInitializedError, "") MK_DEFINE_ERR(3, ValueError, "") MK_DEFINE_ERR(4, MockedError, "") MK_DEFINE_ERR(5, JsonParseError, "") MK_DEFINE_ERR(6, JsonKeyError, "") MK_DEFINE_ERR(7, JsonDomainError, "") MK_DEFINE_ERR(8, FileEofError, "") MK_DEFINE_ERR(9, FileIoError, "") #define MK_ERR_NET(x) (1000 + x) #define MK_ERR_DNS(x) (2000 + x) #define MK_ERR_HTTP(x) (3000 + x) #define MK_ERR_TRACEROUTE(x) (4000 + x) #define MK_ERR_MLABNS(x) (5000 + x) #define MK_ERR_OONI(x) (6000 + x) #define MK_ERR_REPORT(x) (7000 + x) #define MK_ERR_NDT(x) (8000 + x) } ``` # STABILITY 2 - Stable # DESCRIPTION The `Error` class represents an error. It is a derived class of `std::exception` so that it could be thrown and catched as an exception. (In general in MeasurementKit we prefer passing errors to callbacks rather than throwing them as exceptions, but there are some cases where throwing makes sense.) The `Error` class has four constructors. The empty constructor constructs an error with error code equal to zero (a special value used to indicate that no error has actually occurred). The constructor with error code allows to set the error code that is wrapped by an error; a nonzero error code indicates failure. The constructor with error code and reason allows to set both error code and a reason string; at the moment the reason string MUST be a [OONI error string](https://github.com/TheTorProject/ooni-spec/blob/master/data-formats/df-000-base.md#error-strings), but this MAY change in the future. The constructor with error code, reason, and underlying error allows also to specify that the current error was triggered by another, underlying error. The bool operator returns true if the `Error` code is nonzero and false if instead the error code is zero. It can be used to quickly check whether an error occurred as in the following snippet of code: ```C++ func([=](Error err, Result result) { if (err) { callback(err); return; } process_result(result); }); ``` The equality and inequality operators allow to compare errors with error codes and with errors. Currently, the comparison is *only* performed on the grounds of the error code, hence different error classes having the same error code would be equal, as shown in the following snippet of code: ```C++ MK_DEFINE_ERR(7, FooError, ""); MK_DEFINE_ERR(7, FoobarError, ""); REQUIRE((FooError() == FoobarError())); ``` The `as_ooni_error()` method allows to obtain the [OONI error string](https://github.com/TheTorProject/ooni-spec/blob/master/data-formats/df-000-base.md#error-strings) corresponding to a specific MeasurementKit error. In the future the error returned by `as_ooni_error()` MAY be different from the error stored in the `reason` field. The `what()` method overrides the corresponding method of `std::exception`. It returns the same string that `as_ooni_error()` returns. The `child_errors` field is vector of smart pointers that MAY be set to indicate that the current error was triggered by one or more underlying errors. This should allow the programmer to properly layer errors. Thus, one could learn that, say, a specific call to an API failed, and that the reason why that failed was that it was not possible to establish a network connection, and that the reason why that was not possible is that the DNS lookup failed. The `code` and `reason` fields are, respectively, the integer error code uniquely identifying the error and the related textual description. The latter MAY NOT necessarily be equal to the value returned by `as_ooni_error()`. The `MK_DEFINE_ERR` macro allows to compactly define a derived class Error by specifying the error code, the class name, and the reason. In addition to the vanilla error, a derived error has one extra constructor allowing to pass additional textual context to be added to the reason. The `measurement_kit/common.hpp` header uses `MK_DEFINE_ERR` to define *at least* also the following generic error codes: - *NoError*: this class MUST have error code equal to zero and SHOULD be used to indicate that no error occurred - *GenericError*: this class MAY be used to indicate a generic error but it SHOULD NOT be widely used and specific errors SHOULD be preferred - *NotInitializedError*: this is the error that SHOULD be used when accessing a contained that requires initialization and was not primed - *ValueError*: this error SHOULD be returned when it is not possible to convert a specific value from one form to another (e.g. a string to integer) - *MockedError*: this error SHOULD be used in regress tests when mocking the failure of an API, unless specific other errors are required - *JsonParseError*: indicates that it was not possible to parse a JSON - *JsonKeyError*: indicates that a JSON object does not contain a specific key To make sure that errors belonging to different MeasurementKit libraries are disjoint, `measurement_kit/common.hpp` also defines offsets at which errors of each library SHOULD start, as well as useful macros that takes codes relative to a specific library and yields absolute error codes. Each MeasurementKit library is given room for up to 1,000 error codes. At least the following offsets SHOULD be defined by the `measurement_kit/common.hpp` header: - 0 for the *common* lib - 1,000 for the *net* lib - 2,000 for the *dns* lib - 3,000 for the *http* lib - 4,000 for the *traceroute* lib - 5,000 for the *mlabns* lib - 6,000 for the *ooni* lib - 7,000 for the *report* lib - 8,000 for the *ndt* lib # BUGS Since the only integral value to which `Error` could be converted is `bool` there are odd cases where the following statement: ```C++ REQUIRE(err == SomeError()); ``` may fail because the two errors are different but `Catch` may still print as reason for the failed error `1 == 1` because both classes evaluate to `true` (i.e. `1`) even though they internally contain two different errors. # HISTORY The `Error` class appeared in MeasurementKit 0.1.0. The `ErrorContext` class, the `MK_DEFINE_ERR` macro, and the macros to compute absolute error codes all appeared in MeasurementKit 0.2.0. The `ErrorContext` class was removed in MK v0.7.0. measurement-kit-0.7.1/doc/api/common/error_or.md000066400000000000000000000071441315356162600216300ustar00rootroot00000000000000# NAME ErrorOr — Maybe-like object containing type or error. # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { template class ErrorOr { public: ErrorOr(); ErrorOr(T); ErrorOr(Error); operator bool() const; const T &as_value() const; T &as_value(); Error as_error() const; const T &operator*() const; T &operator*(); const T *operator->() const; T *operator->(); }; } ``` # STABILITY 2 - Stable # DESCRIPTION The `ErrorOr` template class wraps either a type `T` or an `Error`. It is commonly used in MeasurementKit to return an error in synchronous functions as shown in the following snippet: ```C++ ErrorOr res = get_result(); if (!res) { callback(res.as_error()); return; } use_result(*res); ``` The first form of the constructor creates an `ErrorOr` object initialized with error equal to `NotInitializedError`. This constructor allows to write code like the following: ```C++ ErrorOr res; // ... /* Note that until assigned: REQUIRE_THROWS_AS(*res, NotInitializedError()); REQUIRE(res.as_error() == NotInitializedError()); */ // ... res = some_operation(); ``` The second form of the constructor initializes the `ErrorOr` template with a value. The third form of the constructor initialized the `ErrorOr` template with an error. The `operator bool()` method returns true if the underlying error object has error code equal to zero, false otherwise. In the former case, we say the `ErrorOr` contains a value, otherwise it contains an error. The `as_value()` method returns a reference to the (possibly `const`) underlying value, if the `ErrorOr` contains a value; otherwise, the contained error is thrown. The `as_error()` method returns the error field. Calling this method never throws, regardless of whether the `ErrorOr` contains an error or a value. This method is typically called to access the underlying error once `operator bool()` has been used to ascertain that the `ErrorOr` contains an error, as shown in the above snippet. The `operator*()` method is an alias for `as_value()`. The `operator->()` method returns a (possibly `const`) pointer to the underlying field, if the `ErrorOr` contains a value; otherwise, the contained error is thrown. This method could be useful to access fields of a structure directly. # EXAMPLE ```C++ #include using namespace mk; class Result { public: unsigned int foo = 17; double bar = 3.14; }; static ErrorOr generate_seventeen() { return 17; } static ErrorOr generate_result() { return Result{}; } static ErrorOr generate_error() { return MockedError(); } int main() { ErrorOr seventeen = generate_seventeen(); REQUIRE(!!seventeen); REQUIRE(*seventeen == 17); *seventeen = 42; REQUIRE(*seventeen == 42); ErrorOr result = generate_result(); REQUIRE(!!result); REQUIRE(result->foo == 17); REQUIRE(result->bar = 3.14); result->foo = 42; REQUIRE(result->foo == 42); ErrorOr error = generate_error(); REQUIRE(!error); REQUIRE_THROWS(*error); REQUIRE_THROWS(error->foo); REQUIRE(error.as_error() == MockedError()); } ``` # HISTORY The `ErrorOr` template class appeared in MeasurementKit 0.2.0. This template class was originally called `Maybe` but it was later renamed `ErrorOr` because there is [a namesake class with similar purpose in LLVM](http://llvm.org/docs/doxygen/html/classllvm_1_1ErrorOr.html). measurement-kit-0.7.1/doc/api/common/every.md000066400000000000000000000021251315356162600211230ustar00rootroot00000000000000# NAME every — call a functor every N seconds # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { template void every(double delay, Var reactor, Callback callback, StopPredicate stop_predicate, Callable callable); } ``` # STABILITY 2 - Stable # DESCRIPTION The `every` template function calls `callable` (equivalent to `std::function`) every `delay` seconds using the specified `reactor` as long as `stop_predicate` (equivalent to `std::function`) returns `false`. When `stop_predicate` returns `true`, the final `callback` (equivalent to `std::function`) will be called with a value of `NoError`. In case `delay` is negative, `callback` will be called with a value of `ValueError()`. In no event `callback` will be called immediately. Even in case of error, its execution will be scheduled as deferred with the `reactor`. # HISTORY The `every` template class appeared in MeasurementKit 0.7.0. measurement-kit-0.7.1/doc/api/common/has_global_factory.md000066400000000000000000000012431315356162600236130ustar00rootroot00000000000000# NAME HasGlobalFactory — Decorator to add global factory to a class # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { template typename class HasGlobalFactory { public: template static Var global(Args &&... args); }; } ``` # STABILITY 2 - Stable # DESCRIPTION Given class `T`, you can make `T` inherit from `HasGlobalFactory` to add the implementation of a global factory called `global()` to `T`. The `Var` returned by `global` will be a singleton. # HISTORY The `HasGlobalFactory` template class appeared in MeasurementKit 0.7.0. measurement-kit-0.7.1/doc/api/common/lexical_cast.md000066400000000000000000000030561315356162600224300ustar00rootroot00000000000000# NAME lexical_cast — Smart cast between different types. # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { template To lexical_cast(From f); template ErrorOr lexical_cast_noexcept(From f); } ``` # STABILITY 2 - Stable # DESCRIPTION The `lexical_cast` function template converts from scalar type `To` to scalar type `From`, throwing `ValueError` if conversion could not be performed. The `lexical_cast_noexcept` function template is like `lexical_cast` except that it returns `ErrorOr` rather than throwing exception. The underlying implementation of `lexical_cast` uses `std::stringstream` to convert back and forth from types; hence, the possible conversions are limited to the ones that are implemented by `std::stringstream`'s `<<` and `>>`. # EXAMPLE ```C++ #include int main() { int num = lexical_cast("1024"); REQUIRE_THROWS(lexical_cast("foobar")); ErrorOr eo = lexical_cast_noexcept("foobar"); REQUIRE(!eo); REQUIRE_THROWS(*eo); } ``` # BUGS Since `std::stringstream` represents `true` using `1` and `false` using `0`, the commonly established semantic that any nonzero value is `true` does not hold. # HISTORY The `lexical_cast` function template class appeared in MeasurementKit 0.2.0. There is [a function template with similar functionality in BOOST](http://www.boost.org/doc/libs/1_61_0/doc/html/boost_lexical_cast.html). measurement-kit-0.7.1/doc/api/common/locked.md000066400000000000000000000015501315356162600212330ustar00rootroot00000000000000# NAME locked — Run callable with lock held # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { template auto locked(std::mutex &mutex, F &&fun); template auto locked_global(F &&fun); } ``` # STABILITY 2 - Stable # DESCRIPTION Syntactic sugar templates that held the lock on some mutex and then call `fun` with the lock held. Any exception will be propagated. The `locked` template function uses a specific mutex. The `locked_global` function uses a global mutex. The return value of `fun`, if any, will be propagated. For example: ```C++ int x = locked_global([]() { return 17; }); ``` Both template functions take single ownership of the passed function. # HISTORY This family of template functions appeared in MeasurementKit 0.7.0. measurement-kit-0.7.1/doc/api/common/logger.md000066400000000000000000000205021315356162600212470ustar00rootroot00000000000000# NAME Logger — Log messages processor # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include // The numbers [0-31] are reserved for verbosity levels. #define MK_LOG_WARNING 0 #define MK_LOG_INFO 1 #define MK_LOG_DEBUG 2 #define MK_LOG_DEBUG2 3 #define MK_LOG_VERBOSITY_MASK 31 // Number above 31 have different semantics: #define MK_LOG_EVENT 32 // Event occurred (encoded as JSON) namespace mk { class Logger : public NonCopyable, public NonMovable { public: static Var make(); void logv(uint32_t level, const char *fmt, va_list ap); void log(uint32_t level, const char *fmt, ...); void warn(const char *fmt, ...); void info(const char *fmt, ...); void debug(const char *fmt, ...); void set_verbosity(uint32_t v); void increase_verbosity(); uint32_t get_verbosity(); void on_log(Delegate fn); void on_eof(Delegate<> fn); void on_event(Delegate fn); void on_progress(Delegate fn); void set_logfile(std::string path); void progress(double); void set_progress_offset(double offset); void set_progress_scale(double offset); static Var global(); ~Logger(); }; /* Functions using the default logger: */ void log(uint32_T level, const char *fmt, ...); void warn(const char *fmt, ...); void info(const char *fmt, ...); void debug(const char *fmt, ...); void set_verbosity(uint32_t v); void increase_verbosity(); uint32_t get_verbosity(); void on_log(Delegate fn); void set_logfile(std::string path); } ``` # DESCRIPTION The `MK_LOG_XXX` macros allow to set verbosity levels and other reserved values. Only the first four bits are used to represent levels of verbosity, while other bits are used for other purposes. The `Logger` class specifies how logs are processed. You can change the function that receives logs. You can change the verbosity level. And of course you can log messages as well. The `make()` factory creates a logger wrapped by a shared pointer. The `logv()`, `log()`, `warn()`, `info()`, and `debug()` methods allow to write log messages. Specifically, `logv()` and `log()` take an explicit logging level argument, while other functions provide it implicitly. Messages are only written if the current verbosity level is not lower than the verbosity level of the currently logged message. That is, ```C++ Var logger = Logger::make(); logger->set_verbosity(MK_LOG_INFO); logger->info("This message will be printed"); logger->debug("This one won't"); ``` The `set_verbosity()`, `increase_verbosity()` and `get_verbosity()` methods allow to manage the verbosity level of the logger. The default verbosity level is `MK_LOG_WARNING` meaning that messages with verbosity greater than that are not logged by default. The `on_log` method allow to either set or reset the function called for each logging message. Such function is a delegate (i.e. the delegate body can safely change the delegate itself) and takes in input the verbosity level of the message and the message itself. The default log function prints on the standard error output the severity (unless the severity is INFO, in which case nothing is printed) followed by the log message. For example: ``` warning: A warning message A info message debug: A debug message debug: A debug2 message ``` To disable the log callback, pass `nullptr` to it. The `on_eof()` method allows to register a function to be called when the logger is about to be destroyed. You can call this function multiple times to register multiple callbacks, if you wish. By default `MK_LOG_EVENT` messages are passed to the log callback. But you can route them to the event callback by specifying it using `on_event()`. In such case, those messages will be passed to the event callback only, meaning that the log callback will not be called for them and they will not be written on the logfile. This behavior is meant to transition between when events where passed to the log callback and a future where they will be either ignored or passed to the event callback. The `on_progress` method allows to register a delegate to receive progress notifications from measurement-kit tests. A progress notification is a tuple composed of a double (between 0.0 and 1.0) and a string: the double represents the overall percentage of completion whereas the string represents the operation currently in progress. The `set_logfile` method instructs the logger to write a copy of each log message into the specified log file. Setting the logfile has no impact on logs written using `on_log` and *viceversa*. By default no log file is specified. It is legal (albeit useless) to have a logger not attached to any log file and whose `on_log` callback is `nullptr`. The `progress` method is used to emit progress notifications. The `set_progress_offset` and `set_progress_scale` methods allow to define, respectively, the offset to be added to progress notifications and the scale value to multiply the progress notification for. By default the offset is 0.0 and the scale is 1.0. These two methods are useful to normalize the progress emitted by individual operations (which see _their_ progress as a number between 0.0 and 1.0) in the context of a more general progress; e.g., the `MultiNdt` test runs two NDT tests, one using a single TCP stream and the other using three TCP streams. Both NDT tests sees their progress as between 0.0 and 1.0 but the parent `MultiNdt` class sets the scale equal to 0.5 and the offset of the second NDT test equal to 0.5, so to normalize the progress emitted by the child NDT tests. The `global()` factory returns the default logger. The destructor calls the functions registered using `on_eof`. This module also includes syntactic sugar functions named like `Logger` methods that call the namesake method of the default logger. That is: ```C++ mk::debug("Foobar"); // == mk::Logger::global()->debug("Foobar"); ``` Internally, the logger implementation MUST be implemented to be thread safe, i.e. it MUST be safe to invoke concurrently the logger from multiple threads, *as far as* the consistency of the logger internals is concerned. Note that this *does not mean at all* that the logger delegate can safely access resources owned by another thread. In such case, it is the programmer's responsibility than any relevant shared resources are locked before they are used, i.e., you MUST use this pattern: ```C++ mk::on_log([=](uint32_t level, const char *message) { resource.acquire_lock(); // Then you can process the message }); ``` Also note that the implementation MAY use a shared internal buffer meaning that log messages SHOULD either immediately consumed or cached if delayed consumption is planned. Failure to do so would possibly lead to the latest produced log message printed more than once. Instead use this pattern: ```C++ mk::on_log([=](uint32_t level, const char *message) { resource.acquire_lock(); std::string copy{message}; resource.sched_deferred_consumption(level, copy); }); ``` Also, note that, being thread safe, the logger MUST lock its internals before emitting a log message. Thus, you MUST NOT call the logger from a logger callback because this MAY result in deadlock or internal buffer corruption, depending on the mutex implementation. Ideally, the log message should be printed on some file, or you should save it as described above and then schedule a delayed call to properly process the message, if processing it is going to be slow. You MUST NOT set up the logger from multiple thread contexts, because methods that set callbacks, change the logger behavior, etc., are not thread safe. # EXAMPLE ```C++ #include using namespace mk; int main() { Var logger = Logger::make(); logger->set_verbosity(MK_LOG_DEBUG); logger->on_log([](uint32_t level, const char *log_line) { printf("<%d> %s\n", level, log_line); }); logger->debug("Format string: %s", "but also arguments"); logger->info("Just like printf"); logger->warn("Use this for important messages"); } ``` # BUGS If the logfile could not be open, or written, the error is silently discarded (i.e. no exceptions thrown, no return values). # HISTORY The `Logger` class appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/common/maybe.md000066400000000000000000000022131315356162600210640ustar00rootroot00000000000000# NAME Maybe — The Maybe monad is back # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { template typename class Maybe { public: Maybe(); Maybe(T &&t); T &operator*(); operator bool() const; }; } // namespace mk ``` # STABILITY 2 - Stable # DESCRIPTION The `Maybe` monad either contains an instance of `T` or is empty. The first form of the constructor creates an empty monad. The second form of the constructor creates a monad that owns the value `t`. If you dereference a monad and the monad contains a value, such value is returned. Otherwise a runtime exception is thrown. To check whether the monad contains a value of not, evaluate it in a boolean context. If the result of such evaluation is true, the monad contains a type, otherwise it is empty. # HISTORY The `Maybe` template class was part of earlier version of MK and such implementation was later renamed `ErrorOr`, because it was more similar to an `ErrorOr` than to a proper `Maybe` monad. We have added back the `Maybe` monad with its proper semantic in MK v0.7.0. measurement-kit-0.7.1/doc/api/common/non_copyable.md000066400000000000000000000017231315356162600224440ustar00rootroot00000000000000# NAME NonCopyable — Forbids copyability # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { class NonCopyable { public: NonCopyable(NonCopyable &) = delete; NonCopyable &operator=(NonCopyable &) = delete; }; } ``` # DESCRIPTION Forbids copyability. You should in general forbid copyability when you hold low-level pointers that should be `free()`d just once. To do this, just inherit from `NonCopyable` as in: ```C++ /* Here inheriting from NonCopyable you guarantee that you cannot make by mistake copies of the raw pointer `bar`. Doing that would cause `delete` to be called more than once, which is a memory error. */ public class Foo : public mk::NonCopyable { public: Foo() { bar = new Bar; } ~Foo() { delete bar; } private: Bar *bar = nullptr; }; ``` # HISTORY `NonCopyable` appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/common/non_movable.md000066400000000000000000000024451315356162600222750ustar00rootroot00000000000000# NAME NonMovable — Forbids movability # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { class NonMovable { public: NonMovable(NonMovable &&) = delete; NonMovable &operator=(NonMovable &&) = delete; }; } ``` # DESCRIPTION Forbids movability. You should forbid movability for example when under the hood the object's `this` is passed to a C callback as an opaque pointer, thus binding the specific value of `this` to the registered low-level callback. To do this, just inherit from `NonMovable` as in: ```C++ /* Setting the class as non movable is crucial here because the constructor passes `this` to a low level API which would presumably use it to call `low_level_notification()`. Therefore, we should not allow to move this object, because moving implies destroying the previous object and moving its content to a new one. This would invalidate the `this` pointer passed to the low level API and thus after the move code of a delected object would be invoked. */ public class Foo : public mk::NonMovable { public: Foo() { low_level_api(this); } void low_level_notification() { /* do something */ } }; ``` # HISTORY `NonMovable` appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/common/parallel.md000066400000000000000000000020731315356162600215670ustar00rootroot00000000000000# NAME Parallel — allows running Continuations in parallel # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { void parallel(srd::vector> input, Callback cb); } ``` # STABILITY 2 - Stable # DESCRIPTION The `parallel` function runs all the continuations in the input vector in parallel and invokes the final callback when all the continuations have terminated their job (i.e. each continuation's callback was called). The overall error passed to the callback `cb` is `NoError` only if all the continuation's callbacks succeeded, `ParallelOperationError` otherwise. Check the `child_errors` field of the `Error` passed to `cb` to know whether each continuation failed (and why) or succeeded. # BUGS The `parallel` implementation assumes that all the continuations will run in the same thread, therefore the state used to decide when all continuations have completed is not thread safe. # HISTORY The `parallel` function appeared in MeasurementKit 0.3.0. measurement-kit-0.7.1/doc/api/common/platform.md000066400000000000000000000007401315356162600216160ustar00rootroot00000000000000# NAME platform — Get current platform # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include const char *mk_platform(void); ``` # STABILITY 2 - Stable # DESCRIPTION The `mk_platform` C-linkage function returns the name of the current platform. The name will be one of: - android - ios - linux - macos - unknown - windows # HISTORY The `platform.h` header appeared in MeasurementKit 0.7.0. measurement-kit-0.7.1/doc/api/common/reactor.md000066400000000000000000000205671315356162600214420ustar00rootroot00000000000000# NAME Reactor — Dispatcher of I/O events # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { #define MK_POLLIN /* Unspecified; used by pollfd() */ #define MK_POLLOUT /* Unspecified; used by pollfd() */ class Reactor { public: static Var make(); static Var global(); void call_later(double delay, Callback<> &&cb); void call_soon(Callback<> &&cb); void run_with_initial_event(Callback<> &&cb); void run(); void stop(); void pollfd( socket_t sockfd, short events, double timeout, Callback &&callback, ); // Backward compatibility aliases void loop() { run(); } void break_loop() { stop(); } void loop_with_initial_event(Callback<> &&func) { run_with_initial_event(std::move(func)); } void pollfd(socket_t sockfd, short events, Callback &&cb, double timeout = -1.0) { pollfd(sockfd, events, timeout, std::move(cb)); } } /* Functional interface (by default using the global reactor): */ void call_later( double delay, Callback<> callback, Var reactor = Reactor::global() ); void call_soon( Callback<> callback, Var reactor = Reactor::global() ); // Syntactic sugar void run(Var reactor = Reactor::global()) { reactor->run(); } void stop(Var reactor = Reactor::global()) { reactor->stop(); } void run_with_initial_event(Callback<> &&func, Var reactor = Reactor::global()) { reactor->run_with_initial_event(std::move(func)); } // Backward compatibility aliases void loop(Var reactor = Reactor::global()) { run(reactor); } void break_loop(Var reactor = Reactor::global()) { stop(reactor); } void loop_with_initial_event(Callback<> &&func, Var reactor = Reactor::global()) { run_with_initial_event(std::move(func)); } ``` # STABILITY 2 - Stable # DESCRIPTION The `Reactor` abstract interface dispatches I/O events. Most MeasurementKit objects refer to a specific `Reactor` object. The `make()` and `global()` factories return a reactor allocated on the heap whose lifecycle is manager using a `Var<>` smart pointer. Specifically, `make()` allocates a new reactor and `global()` returns a reference to the global reactor. You can schedule a callback to be called immediately using the `call_soon` method that takes such callback as its first argument. You can schedule a callback to be called after a specific number of seconds using `call_later`. The first argument is the number of seconds to wait before calling the callback. The second argument is the callback itself. You can ask the reactor to wait for I/O on a specific socket descriptor using `pollfd`. In general, beware that this MAY be less efficient than using the `Transport` API (see the `net` package) for doing asynchronous I/O. To do so, use the `pollfd` overloaded family of methods: The first overload of `pollfd` is the preferred form and takes the following arguments. The first argument is a socket file descriptor. The second argument is the bitmaks of events you want to monitor for; it can be `MK_POLLIN`, to wait for the socket being readable, `MK_POLLOUT` to wait for the socket being writable, or `MK_POLLIN | MK_POLLOUT` to wait for both. The third argument is the timeout after which you want to stop waiting for I/O. Pass a negative value to indicate that you don't want any timeout checking. The fourth argument is the callback to be called when either the socket is ready for I/O or there has been a timeout. The first argument passed to the callback indicates whether there was an error (typically `TimeoutError`) or not (in such case the error will be `NoError`). The second argument passed to the callback indicate whether the socket is readable (`MK_POLLIN`), writable (`MK_POLLOUT`), or both (`MK_POLLIN | MK_POLLOUT`). In second overload of `pollfd` the callback is the third argument and the timeout is optional and is the fourth argument. This overload is implemented by calling the previous overload with swapped third and fourth arguments. This overload is meant as a convenience when you don't want to specify any timeout. It also preserves backward compatibility with versions of MeasurementKit lower than v0.7.0. Other available methods (typically to be called in `main()`) are: The `run_with_initial_event` method runs the reactor and calls the specified callback when the reactor is running. This is a blocking method that does not return until you call the `stop` method. Calling this method when the reactor is already running causes an exception to be thrown. The `run` method runs the reactor. This is a blocking method that does not return until you call the `stop` method. Calling this method when the reactor is already running causes an exception to be thrown. The `stop` method stop the reactor. This is an idempotent method that you can call many times. This method MAY return while the reactor is still running. That is, it only tells the reactor to stop but it does not provide the guarantee that, when it returns, the reactor is already stopped. The `loop_with_initial_event`, `loop`, and `break_loop` methods are deprecated aliases for, respectively, `run_with_initial_event`, `run`, and `stop`. The `get_event_base` is a deprecated method that returns the underlying `event_base` used by the reactor. It is deprecated because it exposes in great detail our dependency on libevent. Ideally, this method should be a method of the specific implementation of the reactor, available only when you downcast from reactor to its specific implementation. In addition, this module exposes also syntactic sugar functions: The `call_soon`, `call_later`, `loop_with_initial_event`, `loop`, `loop_once`, `break_loop`, `run_with_initial_event`, `run`, and `stop` functions are syntactic sugar that call the respective method of the global reactor (i.e. the one obtained with `Reactor::make()`. # GUARANTEES 1. it is safe to call `global` and `global_remote` concurrently from multiple threads. 2. all reactor methods are thread safe. 3. the reactor MAY actually be a proxy for a real reactor multiplexing I/O running from a background thread. In such case, disposing of the foreground object has no effect on the callbacks scheduled in the real reactor. To guarantee this, the signature of functions taking callbacks is such that they must be moved (explicitly or implicitly), thus giving their ownership to the (possibly running in a background thread) reactor. As a result, once a callback is scheduled, there should be no shared state between different threads. We recommend, in such case, to move any state you might need into the callback closure, e.g.: ```C++ reactor->call_soon([state = std::move(state)]() { // Possibly running in the background I/O thread. Has single // ownership of the shared state. }); ``` # CAVEATS 1. the `pollfd` interface is typically less efficient that using the `Transport` based interface implemented in `net`. 2. callbacks MAY be called from another thread context. 3. there is currently no way to know whether the reactor will run the callbacks in the same or in another thread context. 4. calling `stop` before calling `run` has no effect and will typically lead to your program hanging for an infinite amount of time. When you want to run "initialization" actions in the context of the I/O loop you should use instead the following pattern: ```C++ int main(int argc, char **argv) { Reactor reactor = Reactor::make(); // Allocate objects on the stack before calling the blocking // `run_with_initial_event` method of `reactor`. Object obj{reactor}; Foo bar; // Capture by reference (`&`) because this method is blocking reactor->run_with_initial_event([&]() { obj.action([&]() { bar.baz(); reactor->stop(); }); }); } ``` # HISTORY The `Reactor` class appeared in MeasurementKit 0.1.0, named `Poller`. It was renamed `Reactor` in MeasurementKit 0.2.0. As of MK v0.2.0, the `Poller` still exists as a specific implementation of the `Reactor` interface described in this manual page. The `Reactor` was significantly improved as part of MK v0.4.0 and MK v0.7.0. measurement-kit-0.7.1/doc/api/common/settings.md000066400000000000000000000022721315356162600216340ustar00rootroot00000000000000# NAME Settings — Map from string to scalar type # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ namespace mk { class Settings : public std::map { public: using std::map::map; template T get(std::string key, T defval); template ErrorOr get_noexcept(std::string key, T defval); }; } ``` # STABILITY 1 - Experimental # DESCRIPTION `Settings` is an extended `std::map` able to map string to any scalar type. We use `SettingsEntry` to implement a generic scalar type container. In addition to the typical methods of `std::map`, `Settings` also features the `get()` and the `get_noexcept()` method. The `get()` method returns the value at `key` if available, otherwise the default value `defval`. An exception may be raised if it is not possible to convert the value associated to `key` to type `T`. The `get_noexcept()` method is like `get()` except that it does not throw exceptions and instead it returns a `ErrorOr` type. # HISTORY The `Settings` class appeared in MeasurementKit 0.1.0. Support for mapping to any type was added in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/common/settings_entry.md000066400000000000000000000031361315356162600230550ustar00rootroot00000000000000# NAME SettingsEntry — Generic scalar type # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ namespace mk { class SettingsEntry : public std::string { public: template SettingsEntry(In value); template Out as(); template ErrorOr as_noexcept(); }; } ``` # STABILITY 1 - Experimental # DESCRIPTION `SettingsEntry` holds a generic scalar type. Under the hood, `SettingsEntry` is a string and `std::stringstream` is used to convert to/from types; this is similar to what we also do with `mk::lexical_cast()`. The constructor takes in input a scalar type and internally serializes it as a string. Conversion errors should be detected at compile time, hence this method should not throw any exception. The `as()` method allows to convert the internally serialized value to the specified `Out` type. This would raise `ValueError` if either conversion is not possible or not all the internally serialized string is consumed by the conversion. The `as_noexcept()` method is just like `as()` except that it returns `ErrorOr` rather than throwing exception on error. # BUGS Since `std::stringstream` represents `true` using `1` and `false` using `0`, the commonly established semantic that any nonzero value is `true` does not hold. Additionally, this means that the string `"true"` is not going to be parsed as a true value and likewise `"false"` is not going to be parsed as a false value. This behavior is not what one whould expect. # HISTORY The `SettingsEntry` class appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/common/utils.md000066400000000000000000000051631315356162600211360ustar00rootroot00000000000000# NAME utils — Utility functions # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ namespace mk { void timeval_now(timeval *); double time_now(); void utc_time_now(struct tm *); ErrorOr timestamp(const struct tm *); timeval *timeval_init(timeval *, double); Error parse_iso8601_utc(std::string ts, std::tm *tmb); ErrorOr> slurpv(std::string); ErrorOr slurp(std::string); Error overwrite_file(std::string path, std::string content); bool startswith(std::string s, std::string p); bool endswith(std::string s, std::string p); } ``` # STABILITY 1 - Experimental # DESCRIPTION The `timeval_now` function fills the `timeval` structure passed as argument with the current time. The precision should be up to the microsecond on most Unix systems. The `time_now` function returns the current time as double. The double is obtained converting a `timeval` struct to double and hence should have precision of the microsecond on most Unix systems. The `utc_time_now()` function should fill the `tm` structure passed as argument with the current time in UTC. The `timestamp()` function should convert the `tm` structure passed as argument into a string properly formatted according to ISO8601. The return value is wrapped using `ErrorOr<>` because converting to string may fail. The `timeval_init()` function initializes the `timeval` structure passed as argument using the `double` passed as argument. This is often used to arm timers passed internally to libevent. For this reason, in accordance with libevent conventions, if the `double` argument is negative, `nullptr` is returned. Typical safe usage looks like this: ```C++ timeval tv, *tvp = timeval_init(&tv, delta); libevent_api(/* some args... */, tvp); ``` The `parse_iso8601_utc()` function parses the string `ts` formatted as ISO8601 (e.g. `"2012-01-02T03:04:05Z"`) into a `std::tm` structure, which MUST NOT be `nullptr`. On success, `NoError()` is returned, otherwise the code returns `ValueError()`. The slurpv() and slurp() functions read the content of the file specified as argument and return, respectively, a vector of chars containing the content of the file and a string containing the content of the file, on success, and an error in case of failure. The `overwrite_file()` function creates (or truncates) the file at `path` and writes `content` inside it. The return value is `NoError()` on success or an error on failure. The `startswith()` and `endswith()` functions tell you, respectively, whether `s` starts (or ends) with `p`. # HISTORY The `utils.hpp` header was added in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/common/var.md000066400000000000000000000044751315356162600205730ustar00rootroot00000000000000# NAME Var — Shared-pointer with null pointer check # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { template typename class Var : public std::shared_ptr { public: Var(T ptr); Var(); void reset(T *ptr); T *get(); T *operator->() const; T &operator*() const; template Var as(); static template Var make(Args &&... args); }; } ``` # STABILITY 2 - Stable # DESCRIPTION `Var` template class is a drop-in replacement for the standard library `std::shared_ptr` template. It reimplements common `std::shared_ptr` operations by checking that the pointee is not `nullptr`. Otherwise, a runtime exception is raised. The first form of the constructor *owns* `ptr` and manages its life cycle. The second form of the constructor initializes to `nullptr` the internal pointer; attempting to dereference a `Var<>` initialized by this form of the constructor raises a `std::runtime_error`. The `reset()` method releases the previously pointed object and then *owns* the object pointed by `ptr` and manages its life cycle. It is legal to pass `nullptr` to this function; in such case further attempts to access the pointee would result in `std::runtime_error` being raised. The `get()` and `operator->()` methods return the pointee if non null and throw `std::runtime_error` otherwise. The `operator*()` method returns a reference to `*ptr` where `ptr` is the pointee if the pointee is non null and throws `std::runtime_error` otherwise. The `as()` method casts the pointee to type `R` if possible. If conversion is not possible, the returned `Var<>` would point to a null pointer and hence attempting to dereference it would result in `std::runtime_error`. The static `make()` method is equivalent to: ```C++ Var t{new T{arguments...}}; ``` except that, like for `std::make_shared`, only one allocation is performed to allocate both the shared pointer control block and the pointee. # CAVEAT The `as()` method does not seem to preserve any custom deleter that may have been passed to the original `Var<>`; this seems reasonable since the new `Var<>` will delete another type of object (if the cast worked). # HISTORY The `Var` template class appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/common/version.md000066400000000000000000000032731315356162600214630ustar00rootroot00000000000000# NAME version — MeasurementKit version # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include #define MK_VERSION "0.7.1" #define MK_VERSION_FULL "v0.7.1-6-abcdef" #define MEASUREMENT_KIT_VERSION MK_VERSION /* Backward compat. */ const char *mk_version(void); const char *mk_version_full(void); const char *mk_openssl_version(void); const char *mk_libevent_version(void); ``` # STABILITY 2 - Stable # DESCRIPTION This header defines the `MK_VERSION` macro that allows the programmer to know MeasurementKit version number. The `MK_VERSION_FULL` macro contains the output of `git describe --tags` and is hence more precise than the version contained by `MK_VERSION`. Note that the two version numbers will be equal if the current build is a specific tag; otherwise, the version with git tag will contain more precise information. Specifically it will indicate the closest tag, the number of commits since that tag, and the HEAD from which the current release has been built. It also contains a *C linkage* function, `mk_version()` that can be used to programmatically retrieve the library version number. The function has C linkage so that it can be easily used from languages with foreign functions interface. There is also `mk_version_full()` that returns the more precise version containing the output of `git describe --tags`. It also contains *C linkage* functions that tell you the version of OpenSSL and libevent we are compiling measurement-kit with. # HISTORY The `version.h` header appeared in MeasurementKit 0.2.0. Support for knowing the precise git tag and dependencies versions was added during the v0.6 release cycle. measurement-kit-0.7.1/doc/api/dns.md000066400000000000000000000161621315356162600172730ustar00rootroot00000000000000# NAME dns — DNS module # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace dns { void query(QueryClass dns_class, QueryType dns_type, std::string query_name, Callback> callback, Settings settings = {}, Var reactor = Reactor::global()); void resolve_hostname(std::string hostname, Callback cb, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); } // namespace dns } // namespace mk ``` # STABILITY 2 - Stable # DESCRIPTION The `query()` function allows you to send DNS queries and receive the corresponding responses. The `dns_class` argument indicates the query class. At least the following query classes are defined: - *QueryClassId::IN*: this class represents the "internet" domain Note that you can also pass the query class as string; e.g., the following would compile and run as expected: ```C++ mk::dns::query("IN", ...); ``` The `dns_type` argument indicates the query type. The following query types are defined: - *QueryTypeId::A*: the `query_name` argument must be a domain name and the result would be the corresponding IPv4 address, if any. - *QueryTypeId::AAAA*: the `query_name` argument must be a domain name and the result would be the corresponding IPv6 address. if any. - *QueryTypeId::PTR*: the `query_name` argument should be an IP address expressed using the reverse `IN-ADDR` representation and the result would the corresponding domain name, if any (see `EXAMPLES` section for examples). - *QueryTypeId::REVERSE_A*: the `query_name` argument should be an IPv4 address and the result would be the corresponding domain name, if any. This is a nonstandard DNS query type and basically instructs the DNS library to create for you the reverse `IN-ADDR` representation of the `query_name` field and issue a `PTR` query. - *QueryTypeId::REVERSE_AAAA*: same as `REVERSE_A` except that here the input shall be a IPv6 address. Note that you can also pass the query type as string; e.g. the following would also work as expected: ```C++ mk::dns::query("IN", "A", "www.google.com", ...); ``` The `callback` argument is a lambda to be called when the DNS response is available or an error occurs. In case of success, error would be equal to `NoError()`. Otherwise, the error that occurred is reported. Among all the possible errors, the following are defined by MeasurementKit DNS implementation: - `FormatError`: invalid response format - `ServerFailedError`: server failure - `NotExistError`: the name does not exist - `NotImplementedError`: query not implemented - `RefusedError`: the server refuses to reply - `TruncatedError`: response truncated - `UknownError`: internal evnds error - `TimeoutError`: query timed out - `ShutdownError`: evdns library was shut down - `CancelError`: user cancelled query - `NoDataError`: no data in the response In case of success, the `Message` argument passed to the callback would contain details on the response. The `Message` structure contains at least the following fields: ```C++ class Message { public: double rtt = 0.0; std::vector queries; std::vector answers; }; ``` where `rtt` is the time elapsed since issuing the query until receiving the response; `queries` is the list of queries issued; `answers` is the list of answers received. The `Query` class contains at least the following fields: ```C++ class Query { public: QueryType type; QueryClass qclass; uint32_t ttl = 0; std::string name; }; ``` where `type` is the type of the query, `qclass` is the class of the query, `ttl` is the time to live, and `name` is the name for which the query was issued. The `Answer` class contains at least the following fields: ```C++ class Answer { public: QueryType type; QueryClass qclass; uint32_t ttl = 0; std::string ipv4; // For A records std::string ipv6; // For AAAA records std::string hostname; // For PTR, SOA and CNAME records std::string responsible_name; // For SOA records uint32_t serial_number; // For SOA records uint32_t refresh_interval; // For SOA records uint32_t retry_interval; // For SOA records uint32_t minimum_ttl; // For SOA records uint32_t expiration_limit; // For SOA records }; ``` where `type` and `qclass` represent respectively the query type and the query class, `ttl` is the response time to live, and the following fields are only set for specific query types. The optional `Settings` argument contains settings modifying the behavior of the `query` function. The following setting keys are available: - *"dns/attempts"*: how many attempts before erroring out (default is three) - *"dns/nameserver"*: address of the name server to use. If you don't specify this, the default name server is used. On Unix systems the default DNS server is obtained parsing `/etc/resolv.conf`; on mobile devices where such file is not available, the default DNS name server is `127.0.0.1` which typically is not correct. Hence with mobile devices you SHOULD typically supply the DNS server you would like to use. - *"dns/port"*: port of the name server to use. If you don't specify this, the default is `53`. - *"dns/randomize_case"*: whether to [randomize request case to make DNS poisoning more complex](https://lists.torproject.org/pipermail/tor-commits/2008-October/026025.html) (by default this is not done) - *"dns/timeout"*: time after which we stop waiting for a response (by default this is five seconds) The optional `reactor` argument is the reactor to use to issue the query and receive the corresponding response. The `resolve_hostname()` function should be used to perform dns queries for connection purposes and not to perform tests on a dns server. In both cases of success or failure, it will invoke the callback passing an instance of `ResolveHostnameResult`. The `ResolveHostnameResult` class is like: ```C++ struct ResolveHostnameResult { bool inet_pton_ipv4 = false; bool inet_pton_ipv6 = false; Error ipv4_err; dns::Message ipv4_reply; Error ipv6_err; dns::Message ipv6_reply; std::vector addresses; }; ``` where `inet_pton_ipv4` is `true` if `address` is an IPv4 address and similarly `inet_pton_ipv6` is `true` if `address` is an IPv6 address; `ipv4_err` and `ipv4_reply` are the values returned by resolving `address` as a FQDN into a list of addresses; `ipv6_err` and `ipv6_reply` have the same semantic of their IPv4 counterparts; `addresses` is the list of the addresses that `connect()` will try to connect to. This list will only contain a IPv4 (or IPv6) address if `address` is an IPv4 (or IPv6) address and it will contain IPv4 addresses before IPv6 addresses (if any) when `address` instead is a FQDN (fully qualified domain name). # EXAMPLE See files in `example/dns/`. # HISTORY The DNS module appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/ext.md000066400000000000000000000006561315356162600173100ustar00rootroot00000000000000# NAME ext — module containing third parties' code # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ // DO NOT INCLUDE THIS HEADER FILE DIRECTLY /*#include */ ``` # STABILITY 1 - Experimental # DESCRIPTION The `ext` module contains functionality implemented in headers provided by third parties. # HISTORY The `ext` module appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/http.md000066400000000000000000000007211315356162600174600ustar00rootroot00000000000000# NAME http — HTTP module # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include ``` # DESCRIPTION The `http` module contains HTTP related functionality. It is currently composed by the following submodules: - [parse_url](http/parse_url.md): URL parsing - [request](http/request.md): sending requests and receiving responses # HISTORY The `http` module appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/http/000077500000000000000000000000001315356162600171365ustar00rootroot00000000000000measurement-kit-0.7.1/doc/api/http/parse_url.md000066400000000000000000000020121315356162600214470ustar00rootroot00000000000000# NAME parse_url — URL parsing # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include mk::http::Url mk::http::parse_url(std::string url); mk::ErrorOr mk::http::parse_url_noexcept(std::string url); ``` # STABILITY 2 - Stable # DESCRIPTION The `parse_url()` function parses the `url` argument into a `Url` structure: ```C++ class Url { public: std::string schema; std::string address; int port = 80; std::string path; std::string query; std::string pathquery; }; ``` On error one of the following exceptions could be thrown: - `mk::http::UrlParserError`: error in URL parser - `mk::http::MissingUrlSchemaError`: missing schema in parsed URL - `mk::http::MissingUrlHostError`: missing host in parsed URL The `parse_url_noexcept()` is equal to `parse_url()` except that rather than throwing an exception of error it returns an `ErrorOr` wrapper. # HISTORY The `parse_url` module appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/http/request.md000066400000000000000000000200411315356162600211450ustar00rootroot00000000000000# NAME request — issue HTTP requests # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSYS ```C++ #include void request(Settings settings, Headers headers, std::string body, Callback> callback, Var reactor = Reactor::global(), Var = Logger::global()); void get(std::string url, Callback> callback, Headers headers = {}, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); void request_json_string( std::string method, std::string url, std::string data, http::Headers headers, Callback, nlohmann::json> cb, Settings settings, Var reactor, Var logger); void request_json_no_body( std::string method, std::string url, http::Headers headers, Callback, nlohmann::json> cb, Settings settings, Var reactor, Var logger); void request_json_object( std::string method, std::string url, nlohmann::json jdata, http::Headers headers, Callback, nlohmann::json> cb, Settings settings, Var reactor, Var logger); void request_connect(Settings settings, Callback> callback, Var reactor = Reactor::global(), Var logger = Logger::global()); void request_send(Var txp, Settings settings, Headers headers, std::string body, Callback callback); void request_recv_response(Var txp, Callback> callback, Var reactor = Reactor::global(), Var logger = Logger::global()); void request_sendrecv(Var txp, Settings settings, Headers headers, std::string body, Callback> callback, Var reactor = Reactor::global(), Var logger = Logger::global()); ErrorOr redirect(const Url &orig_url, const std::string &location); ``` # STABILITY 1 - Experimental # DESCRIPTION The `request()` function issues the asynchronous `HTTP` request specified by the `settings` argument. The following settings are available: - *http/max_redirects*: maximum number of redirects to follow, defaults to zero - *http/url*: the URL to use - *http/ignore_body*: does not save response body (this is currently not implemented) - *http/method*: the method to use (default: "GET") - *http/http_version*: specify HTTP version (otherwise `HTTP/1.1` is used) - *http/path*: path to use (if not specified the one inside the URL is used instead) The `body` argument is either the request body or an empty string to send no request body. The `callback` function is called when done; it receives the error that occurred — or `NoError()` — as first argument and the `Response` as second argument. Optionally you can also specify the `reactor` and the `logger` to be used. The `get()` function is a wrapper for `request()` that sets for you `http/url` using as input the `url` argument and `http/method` as `GET`. Unlike `request()` you cannot set the body, because `GET` requests SHOULD NOT carry a body. All other arguments have equal semantic. The `request_json_string()` function is a wrapper for `request()` that sends a JSON request (serialized as a string as the `data` argument) and gives back a JSON response (as a `nlohmann::json`). The `request_json_no_body()` function is a wrapper for `request()` that expects the response to be a JSON. The `request_json_object()` function is a wrapper for `request()` that sends a JSON request (represented by a `nlohmann::json`) and gives back a JSON response (again represented by a `nlohmann::json`). Both `request()` and `get()` support `SSL` if the URL schema is `https` and SOCKS5 proxying as described below for `request_connect()`. Also, both functions close the established connection when the response is received. To implement keep-alive semantic, use the following, lower-level functions: The `request_connect()` function establishes a TCP (and possibly SSL) connection towards an HTTP (or HTTPS) server. It uses as input the specified `settings` and, when done, it invokes `callback` with the error that occurred — or `NoError()` — as the first argument and the connected transport wrapped by a `Var` as the second argument. In case of error, the transport SHOULD be `nullptr`. You can also specify an optional `reactor` and `logger`. The `settings` that matter to this function are the following: - *http/url*: used to find out the address to connect to and whether to connect using TCP (if schema is `http`) or SSL (if schema is `https`). Additionally, if schema is `httpo` (for `HTTP onion`), this function MAY set SOCKS5 proxy settings ot use locally running instance of `tor`. - *net/tor_socks_port*: if this setting is present, this function would pass `127.0.0.1:${net/tor_socks_port}` as SOCKS5 proxy to `net/connect()`. - *net/socks5_proxy*: if this setting is present and *net/tor_socks_port* is not present, then this setting is passed verbatim to `net/connect()`. - all other settings that matter to `net/connect()`. The `request_send()` function send an HTTP request asynchronously over the `txp` transport, using `settings`, `headers`, and `body` to construct the request, and calls `callback` when done. The settings that matter to this function are `http/url`, `http/http_version`, `http/method`, and `http/path` — all already described above. The callback receives the error that occurred or `NoError()` in case of success. The `request_recv_response()` function receives an HTTP response asynchronously using the `txp` transport and calling `callback` when done. You can optionally specify a `reactor` and a `logger` to use. On error, the callback receives it as its first argument; otherwise, the first argument is `NoError()` and the second argument is the received HTTP response wrapped by a `Var`. The `request_sendrecv()` function combines the `request_send()` and the `request_recv_response()` functions into a single call. Beware that, in case of early error, the callback MAY be called immediately by any of the above functions. The following errors may occurr: - `UpgradeError`: received unexpected UPGRADE message - `ParserError`: error in HTTP parser - `UrlParserError`: error in URL parser - `MissingUrlSchemaError`: missing schema in parsed URL - `MissingUrlHostError`: missing host in parsed URL - `MissingUrlError`: no URL was passed to a function that required it - `HeaderParserInternalError`: the response headers parser encountered an error HTTP headers are represented by the `http::Headers` typedef that currently is alias for `std::map` where the comparison of header keys is case insensitive. The HTTP response object returned by several callbacks is like: ```C++ class Response { public: std::string response_line; unsigned short http_major = 0; unsigned short http_minor = 0; unsigned int status_code = 0; std::string reason; Headers headers; std::string body; }; ``` The `redirect()` function will construct a new URL from the existing URL and a location header, basically implementing MK redirection logic. # EXAMPLE See `example/http/request.cpp`. # BUGS - The `http/ignore_body` setting is not implemented. - The `Var` returned by the various callbacks MAY be pointing to `nullptr` and, moreover, there MAY be cases where `Var response` is pointing to a valid response but `response->request` is `nullptr`. # HISTORY The `request` module appeared in MeasurementKit 0.2.0. Support for calling JSON APIs was added in MK v0.7.0. measurement-kit-0.7.1/doc/api/mlabns.md000066400000000000000000000072201315356162600177560ustar00rootroot00000000000000# NAME mlabns — module for querying mlab name service (mlabns) # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include void mk::mlabns::query(std::string mlab_tool, mk::Callback callback, mk::Settings settings = {}, mk::Var reactor = mk::Reactor::global(), mk::Var logger = mk::Logger::global()); ``` # STABILITY 2 - Stable # DESCRIPTION The `query` function allows to query the mlab naming service (mlabns). The first argument is the tool for which you are querying mlabns (e.g. `ndt`). The second argument is a callback function called when done, with an error — or `NoError()` in case of success — passed as the first argument and the reply passed as second argument. You can also pass the following, optional settings: - *"mlabns/base_url"*: base URL of the mlab-ns service. By default this URL is `https://mlab-ns.appspot.com/`. - *"mlabns/policy"*: one of `"random"`, `"metro"`, or `"country`". The random policy asks mlabns to return a random server for the specified tool. The metro policy asks mlabns a server close to the city code passed as *mlabns/metro*. The country policy asks mlabns to return a suitable server in the country where the requesting client is located. - *"mlabns/metro"*: used together with *mlabns/policy* equal to *metro*, this setting specifies which city should the returned server be close to. For example, *ath* (for Athens) or *trn* (for Turin). - *"mlabns/family"*: when this setting is unspecified, mlabns returns results valid for both IPv4 and IPv6. Set *mlabns/family* to *ipv4* or *ipv6* to restrict the results respectively only to IPv4 or IPv6. Optionally you can also pass a nondefault `reactor` and `logger`. The `Reply` structure is like: ```C++ class Reply { public: std::string city; // City where server is. std::string url; // URL to access server using HTTP. std::vector ip; // List of IP addresses of server. std::string fqdn; // FQDN of server. std::string site; // Code of the city where the server is (e.g. `ath`). std::string country; // Country where sliver is. }; ``` In addition to `NoError()`, the following errors could be returned by the callback: - *mk::mlabns::InvalidPolicyError*: you passed in an invalid policy setting - *mk::mlabns::InvalidAddressFamilyError*: you passed in an invalid address family setting - *mk::mlabns::InvalidMetroError*: you passed in an invalid metro setting - *mk::mlabns::InvalidToolNameError*: you passed in an invalid tool name # EXAMPLE ```C++ #include #include using namespace mk; mlabns::query( "ndt", [](Error error, mlabns::Reply reply) { if (error) { throw error; } std::cout << "< city: " << reply.city << "\n"; std::cout << "< url: " << reply.url << "\n"; std::cout << "< ip: [\n"; for (auto s : reply.ip) { std::cout << "< " << s << "\n"; } std::cout << "< ]\n"; std::cout << "< fqdn: " << reply.fqdn << "\n"; std::cout << "< site: " << reply.site << "\n"; std::cout << "< country: " << reply.country << "\n"; /* ... */ }, { {"mlabns/metro", "ath"}, {"mlabns/policy", "metro"}, {"mlabns/family", "ipv4"}, }); ``` # HISTORY The `mlabns` module appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/ndt.md000066400000000000000000000061551315356162600172750ustar00rootroot00000000000000# NAME ndt — Network Diagnostic Tool client # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace ndt { class NdtTest : public NetTest { public: using NetTest::NetTest; }; } // namespace ndt } // namespace mk void mk::ndt::run(Callback callback, Settings settings = {}, Var logger = Logger::global(), Var reactor = Reactor::global()); void mk::ndt::run_with_specific_server(std::string address, int port, Callback callback, Settings settings = {}, Var logger = Logger::global(), Var reactor = Reactor::global()); ``` # STABILITY 1 - Experimental # DESCRIPTION The `NdtTest` class is a subclass of `mk::NetTest` that runs a NDT test. Hence you can run a NDT test as follows: ```C++ #include using namespace mk::ndt; NdtTest() .set_options("test_suite", MK_NDT_DOWNLOAD) .increase_verbosity() .run(); ``` More options than the one displayed above are available; see the documentation of `mk::NetTest` for more information on how to run a NetTest and on what options are available. The `run()` function runs a NDT test and calls the `callback` specified as its first argument when done, passing it the error that occurred — or `NoError()` in case of success. The behavior of the function may be futher specified by passing it the following `settings`: - *"address"*: address (or domain name) of the NDT server. If this argument is not specified, mlabns is used to find out a suitable server. - *"port"*: port of the NDT server as integer. Only used if *address* is specified. - *"test_suite"*: integer mask indicating which tests to run among all the available tests as defined by the following `define`s: ```C++ #define MK_NDT_UPLOAD 2 // Run NDT's download test #define MK_NDT_DOWNLOAD 4 // Run NDT's upload test ``` If you don't specify a *test_suite* setting, both the download and the upload NDT tests will be run. Additionally, you can also specify an optional `reactor` and an optional `logger`. The `run_with_specific_server()` function is a wrapper that sets *address* and *port* in its settings according to its first two arguments and then calls `run()`. All other arguments have the same semantic as their `run()` equivalents. # EXAMPLE Runs NDT test in the context of the default runner and breaks out of the event loop when the NDT test is complete, whatever the test result. ```C++ #include using namespace mk; mk::loop_with_initial_event([]() { ndt::run([](Error /*err*/) { break_loop(); }); }); ``` You can also achieve the same results more compactly and in a more abstract way by using the `mk::NetTest` interface as shown above. # BUGS Only NDT's download and upload tests are implemented. # HISTORY The `ndt` module appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/net.md000066400000000000000000000011241315356162600172650ustar00rootroot00000000000000# NAME net — Networking module # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include ``` # DESCRIPTION The `net` module contains the following networking functionality: - [buffer](net/buffer.md): Buffer for incoming/outgoing data - [connect](net/connect.md): Functions to establish connections - [error](net/error.md): Network-level errors - [transport](net/transport.md): Abstract interface for connected sockets - [utils](net/utils.md): Utility functions # HISTORY The `net` module appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/net/000077500000000000000000000000001315356162600167455ustar00rootroot00000000000000measurement-kit-0.7.1/doc/api/net/buffer.md000066400000000000000000000132221315356162600205400ustar00rootroot00000000000000# NAME Buffer — Buffer containing data. # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace net { class Buffer { public: Buffer(); Buffer(evbuffer *b); Buffer(std::string); Buffer(const void *, size_t); Buffer &operator<<(evbuffer *source); Buffer &operator>>(evbuffer *dest); Buffer &operator<<(Buffer &source); Buffer &operator>>(Buffer &source); size_t length(); void for_each(std::function fn); void discard(size_t count); void discard(); std::string read(size_t upto); std::string read(); std::string peek(size_t upto); std::string peek(); std::string readn(size_t n); ErrorOr readline(size_t maxline); void write(std::string in); Buffer &operator<<(std::string in); void write(const char *in); Buffer &operator<<(const char *in); void write(const void *buf, size_t count); ErrorOr read_uint8(); void write_uint8(uint8_t); ErrorOr read_uint16(); void write_uint16(uint16_t); ErrorOr read_uint32(); void write_uint32(uint32_t); void write_rand(size_t count); void write(size_t count, std::function func); } // namespace net } // namespace mk ``` # DESCRIPTION The `Buffer` type contains a list of strings either read from a socket or to be written into a socket. It MAY be implemented using libevent's `evbuffer`. The constructors allow to initialize, respectively, an empty `Buffer`, a buffer from an existing libevent's `evbuffer` (this operation MAY be zero copy if the `Buffer` is implemented using libevent's `evbuffer`), a C++ string, and a C style buffer (i.e. `void *` and `size_t`). There are insertion and extraction operators from/to respectively a libevent's `evbuffer` and a Buffer. Insertion and extraction to/from `Buffer` is always zero copy, while insertion and extraction to/from libevent's `evbuffer` MAY be zero copy if the `Buffer` is implemented using libevent's `evbuffer`. The `length()` method returns the number of bytes in the `Buffer`. The `for_each()` function allows to call a function on every string contained by the `Buffer` object. To stop iterating earlier, the called function returns `false`. Otherwise all the buffered strings are visited. This is useful to inspect the content of the `Buffer` without triggering copies; e.g.: ```C++ size_t total = 0; buffer.for_each([&](const void *ptr, size_t size) { process_data((char *)ptr, size); total += size; return (total <= 1024); /* Do not process more than 1,024 bytes */ }); buffer.discard(total); ``` Note that you MUST NOT modify the `Buffer` while iterating over it. The example above shows the optimal pattern to discard data from the buffer after you have finished iterating over it. The `discard()`, `read()`, and `peek()` families of functions read from the `Buffer`. As the name implies, the `discard()` functions discard data from the `Buffer`; if the amount of bytes to discard is not specified, the whole content of the buffer is discared. The `read()` functions extract data from the buffer and returns is serialized as string; if the amount of bytes to read is not specified, the whole content of the buffer would be extracted. The `peek()` functions are like `read()` expect that the buffer content would not be discared; as such, they are optimal to inspect (portions of) the buffer content to decide whether special actions should be carried out. For example: ```C++ std::string data = buffer.peek(4); if (data.size() < 4) { return -2; /* I.e. try again */ } if (data == "HELO") { std::string helo = buffer.read(HELO_MESSAGE_LENGTH); if (helo.size() < HELO_MESSAGE_LENGTH) { return -2; /* I.e. try again */ } /* Now process HELO's message content... */ return 0; } /* Other cases... */ ``` The `readn()` function returns either a N bytes string (where N is the number of bytes passed as argument) or the empty string. This is useful to parse protocol messages having a fixed width. For example, part of the previous example could be rewritten as: ```C++ if (data == "HELO") { std::string helo = buffer.readn(HELO_MESSAGE_LENGTH); if (helo == "") { return -2; /* I.e. try again */ } /* Now process HELO's message content... */ return 0; } ``` The `readline()` function reads a line no longer than the number of bytes passed as its first argument. It returns the read line on success and an error in case of failure. The `Buffer` class contains write and insert operators that allow to queue respectively a C++ string, a C string, and a C-style buffer. The `Buffer` class also contains functionalities to read and write integers of typical sizes (16 and 32 bits). In such case integers are automatically converted from the host to network representation when writing and from network to host representation when reading. Because read operations could fail, they return `ErrorOr` rather than just `T`. The `write_rand()` method writes the specified number of random bytes into the buffer. The `write(size, callback)` allocates a buffer of size `size` and calls the callback specified as second argument to fill it. Such callback MAY return less than `size` bytes to indicate that less than `size` bytes have been initialized by it. This is useful, for example, to allocate a buffer large as the maximum message size but allowing, at the same time, to send smaller messages. # HISTORY The `Buffer` class appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/net/connect.md000066400000000000000000000067251315356162600207320ustar00rootroot00000000000000# NAME connect — Routines to connect to remote hosts # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include void mk::net::connect(std::string address, int port, Callback> callback, Settings settings = {}, Var logger = Logger::global(), Var reactor = Reactor::global()); using ConnectManyCb = Callback>>; void mk::net::connect_many(std::string address, int port, int num, ConnectManyCb callback, Settings settings = {}, Var logger = Logger::global(), Var reactor = Reactor::global()); ``` # STABILITY 2 - Stable # DESCRIPTION The `connect()` function creates a connection to the remote `address` (which typically is a FQDN) and `port` and calls `callback` when done. On failure, an error is passed to the callback as its first argument, while a valid, but not connected, `Var` is passed as its second argument. On success, the first callback argument is `NoError` and the second argument is a `Transport` instance wrapped by a `Var<>` smart pointer. Optionally you can also specify `settings`, a specific `logger` and a specific `reactor`. If `address` is a FQDN, this implementation of `connect()` will try all the addresses obtained by resolving `address` before declaring the connect attempt failed. In doing that, `connect()` would give preference to IPv4 addresses over IPv6 addresses. Conversely, if `address` is already an IPv4 or IPv6 address, this function would not attempt to resolve it and would try to connect it directly. The behavior of `connect()` and of `Transport` s created using `connect()` can be modified using the following `settings`: - *"net/ca_bundle_path"* (string): path of the CA bundle to be used to verify SSL certificates. The default value is selected by `./configure` inspecting the local system when compiling. If the path is the empty string and we link against libressl (as is typically the case for mobile devices) we load libressl default CA from memory (i.e. you don't need anymore to include a CA file when setting up an application using measurement-kit). - *"net/ssl_allow_dirty_shutdown"* (bool): if true, this setting treats EOF received on the socket without receiving a clean SSL shutdown message as a normal EOF. If false, this situation is reported as `SslDirtyShutdownError`. By default, this flag is false. - *"net/dumb_transport"*: if this key is present a dumb transport is created (i.e. a transport that is not connected to any socket). - *"net/socks5_proxy"* (string): address and port (separated by colon) of the SOCKS5 proxy to be used for establishing the requested connection (this feature is still experimental as of v0.2.0). - *"net/ssl"* (bool): whether to establish a SSL connection (default: false). - *"net/timeout"* (double): timeout for connect and I/O operations (default: `5.0` seconds). - *"net/allow_ssl23"* (bool): whether to enable SSLv2 and SSLv3 (default: false) The `connect_many()` function is similar to `connect()`. The main different is that `num` parallel connections are established and passed to the callback on success. Of course, this function would return `NoError()` only if all the parallel connect attempts were successful, and it would close all the open connections if only some connect attempts were successful. # HISTORY The `connect` submodule appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/net/error.md000066400000000000000000000005531315356162600204230ustar00rootroot00000000000000# NAME Error — A network error. # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include // ERROR CODES DEFINED IN ``` # DESCRIPTION Errors that occurr in the `net` library of MeasurementKit. # HISTORY Net specific errors appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/net/transport.md000066400000000000000000000204071315356162600213260ustar00rootroot00000000000000# NAME Transport — TCP-like connection # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace net { class Transport { public: virtual ~Transport(); /* * As emitter: */ virtual void emit_connect() = 0; virtual void emit_data(Buffer buf) = 0; virtual void emit_flush() = 0; virtual void emit_error(Error err) = 0; virtual void on_connect(Callback<>) = 0; virtual void on_data(Callback) = 0; virtual void on_flush(Callback<>) = 0; virtual void on_error(Callback) = 0; virtual void close(Callback<>) = 0; /* * As recorder: */ virtual void record_received_data() = 0; virtual void dont_record_received_data() = 0; virtual Buffer &received_data() = 0; virtual void record_sent_data() = 0; virtual void dont_record_sent_data() = 0; virtual Buffer &sent_data() = 0; /* * As writable: */ virtual void write(const void *, size_t) = 0; virtual void write(std::string) = 0; virtual void write(Buffer) = 0; /* * As SOCKS5: */ virtual std::string socks5_address() = 0; virtual std::string socks5_port() = 0; /* * As pollable: */ virtual void set_timeout(double timeo) = 0; virtual void clear_timeout() = 0; /* * As connectable: */ virtual double connect_time() = 0; virtual void set_connect_time_(double) = 0; virtual std::vector connect_errors() = 0; virtual void set_connect_errors_(std::vector) = 0; virtual dns::ResolveHostnameResult dns_result() = 0; virtual void set_dns_result_(dns::ResolveHostnameResult) = 0; protected: virtual void adjust_timeout(double timeo) = 0; virtual void shutdown() = 0; virtual void start_reading() = 0; virtual void stop_reading() = 0; virtual void start_writing() = 0; }; } // namespace net } // namespace mk /* * Syntactic sugar: */ void write(Var txp, Buffer buf, Callback cb); void readn(Var txp, Var buff, size_t n, Callback cb, Var reactor = Reactor::global()); void read(Var t, Var buff, Callback callback, Var reactor = Reactor::global()); ``` # DESCRIPTION The `Transport` is a TCP like connection to another endpoint. You typically construct a transport using the `net::connect()` factory method. ## As event emitter A `Transport` is an event emitter class, meaning that it defines functions to emit and intercept specific events. The following events are defined: - *connect*: emitted when the connection is established (this is currently only used when you connect a SOCKS5 transport) - *data*: emitted when data was received from the network - *flush*: emitted when the output buffer is empty - *error*: emitted when a error occurs By default the handlers of all these events do nothing. You can set handlers using the `on_EVENT()` methods. You can emit events using the `emit_EVENT()` methods. The `close()` method initiates a close operation. Doing that puts the transport in a state where further emitted events are not delivered. Moreover, once closed, the transport would not attempt to change the state of the underlying I/O mechanism (i.e. it will not invoke any method described below as part of the "pollable" interface of a `Transport`). Once `close()` is in progress, further attempts to `close()`, will raise an exception. The callback passed as the first argument will be invoked by the destructor of `Transport`. We recommend always making sure that a `Transport` was closed correctly, as shown by this code snippet: ```C++ /* Some code */ transport->close([=]() { /* Continuation code after transport has been closed */ }); ``` This will guarantee that you notice if a `Transport` is not actually closed because there are still references to `Var` around. ## As data recorder In addition the `Transport` also allows to record the received and the sent data, using specific methods. ## As writable The `write()` family of methods allow to write respectively a C style buffer, a C++ string, and a `Buffer` object. All these functions fill the send buffer, and a corresponding *flush* event would be emitted when it is empty. ## As SOCKS5 The `socks5_address()` and `socks5_port()` methods return respectively the SOCKS5 address and port being used, if any. Otherwise the empty string is returned. ## As pollable descriptor This set of methods defines how the transport interfaces with the underlying async I/O implementation. Since this is how the transport implementation should interface with the lower level of abstraction most methods in here are `protected`. The `set_timeout()` and `clear_timeout()` methods respectively set the timeout to be used for I/O operations, as a floating point number of seconds `timeo`, and clear such timeout. The read timeout fires when no data is received after `timeo` seconds, likewise the write timeout fires if a pending write operation does not complete within `timeo` seconds. By default, measurement-kit sets a 30 seconds timeout. Clearing the timeout causes I/O operation to wait for a number of seconds possibly equal to the lifespan of the universe, in the best (or is it worst?) case scenario. The `adjust_timeout()` method is called by `set_timeout()` or `clear_timeout()` to enforce setting the timeout. This method MUST NOT be called by the generic code after the transport has been closed. Passing a negative value implies that the timeout is to be cleared. The `shutdown()` method implementation depends on the underlying I/O mechanism. It is automatically called as part of `close()`. The implementation SHOULD ensure that this method is idempotent. The `start_reading()` and `stop_reading()` methods respectively enable and disable reading from the internal socket. The implementation MUST automatically enable (disable) reading when you set (clear) the `on_data()` callback. This method MUST NOT be called by the generic code after the transport has been closed. The `start_writing()` method initiates an asynchronous write operation that is terminated by emitting the `FLUSH` event when the output buffer becomes empty. The implementation MUST automatically start writing when you call any `write()` method. This method MUST NOT be called by the generic code after the transport has been closed. ## As connectable This set of methods allow to get various connect-time values, like the time required to connect (which approximates the minimum RTT), the errors experienced when connecting (for example, the DNS may return more than one address and some of them may be unreachable, but others work), and the result of the DNS query for the provided hostname. It also contains semi-hidden methods to set such values when connecting. ## Syntactic sugar The `write()` function is syntactic sugar that schedules an asynchronous write operation on a transport and calls the provided callback when either an error occurs or the underlying buffer has been flushed. The `readn()` function is syntactic sugar that starts an asynchronous read operation on a transport and only returns whether either `n` bytes have been read or an error occurred. The `read()` function is a wrapper that calls the `readn()` function with `n` equal to `1`. # BUGS We typically pass around the `Transport` as a `Var`. Since `Var` is a shared pointer, this means that a `Transport` may not be closed, after the `close()` method is called, unless all `Var`s pointing to it are cleared. For this reason, we added a callback to `close()`, so you know the code is not working correctly if the program stalls when it would be supposed to continue after `close()`. This is a bit rough but it currently works. In the future, it will be interesting to experiment with weak shared pointers such that we have a single permanent shared reference in the `Reactor` and the user only has access to a weak shared pointer that becomes a real shared pointer only when the object is temporarily needed (and that handles the case where the original object is expired so it's not possible to temporarily acquire it). # HISTORY The `Transport` class appeared in MeasurementKit 0.1.0. The `read()`, `readn()`, and `write()` functions were added in v0.2.0. measurement-kit-0.7.1/doc/api/net/utils.md000066400000000000000000000047411315356162600204350ustar00rootroot00000000000000# NAME utils — Utility functions # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace net { class Endpoint { public: std::string hostname; uint16_t port = 0; }; bool is_ipv4_addr(std::string s); bool is_ipv6_addr(std::string s); bool is_ip_addr(std::string s); ErrorOr parse_endpoint(std::string s, uint16_t default_port); std::string serialize_endpoint(Endpoint e); Error make_sockaddr( std::string address, std::string port, sockaddr_storage *ss, socklen_t *len ) noexcept; Error make_sockaddr( std::string address, uint16_t port, sockaddr_storage *ss, socklen_t *len ) noexcept; }} ``` # DESCRIPTION The `is_ipv4_addr`, `is_ipv6_addr`, `is_ip_addr` functions return true if the input is, respectively, IPv4, IPv6 and IPv4 or IPv6. The `parse_endpoint` function parses the string `s` — which should contain an IP address or an hostname, followed by a colon and by a port — into an `Endpoint` structure. The return value is an `ErrorOr` template wrapping the `Endpoint` structure on success and a `ValueError` error if the parsing fails. This function follows this algorithm: 1. parse `s` as `host ":" port` where `host` and `port` are defined as defined by the HTTP standards, returns the `Endpoint` on success, and `ValueError` on failure 2. if step 1 fails, appends `:` followed by `default_port` to `s` and calls the functionality at step 1 again with the resulting string The `host` MAY either be a domain name, or an IPv4 or IPv6 address. If `host` is an IPv6 address and `s` also contains the port, the `host` MUST be quoted using `[` and `]` as in `[::1]`. If `s` only contains an IPv6 address, then the square brackets MAY be omitted. The `serialize_endpoint` function transforms the endpoint `e` into a string. As such, it is the dual operation of `parse_endpoint`. The `make_sockaddr` functions fills a `sockaddr_storage` structure and its length from a string possibly containing an IPv4 or IPv6 address and a port (either as a string or as an integer). The return value is `NoError` on success and an error on failure. # BUGS In theory, `parse_endpoint` should correctly deal with link scope addresses such as `[fe80::1%lo0]:80`. However, it was only possible to test this functionality with macOS, therefore it MAY NOT work correctly on Linux systems. # HISTORY Module added in MeasurementKit 0.4.0. measurement-kit-0.7.1/doc/api/nettests.md000066400000000000000000000013131315356162600203500ustar00rootroot00000000000000# NAME nettests — library containing all implemented network tests # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include ``` # CONTENTS - [BaseTest](nettests/base_test.md) - [DnsInjectionTest](nettests/dns_injection.md) - [HttpHeaderFieldManipulationTest](nettests/http_header_field_manipulation.md) - [HttpInvalidRequestLineTest](nettests/http_invalid_request_line.md) - [MeekFrontedRequestsTest](nettests/meek_fronted_requests.md) - [TcpConnectTest](nettests/tcp_connect.md) # DESCRIPTION The `nettests` module contains contains all the implemented network tests. # HISTORY The `nettests` module appeared in MeasurementKit 0.4.0. measurement-kit-0.7.1/doc/api/nettests/000077500000000000000000000000001315356162600200305ustar00rootroot00000000000000measurement-kit-0.7.1/doc/api/nettests/base_test.md000066400000000000000000000164601315356162600223320ustar00rootroot00000000000000# NAME BaseTest — Base network test class # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace nettests { class BaseTest { public: BaseTest &on_logger_eof(Delegate<>); BaseTest &on_log(Delegate); BaseTest &on_event(Delegate); BaseTest &on_progress(Delegate); BaseTest &set_verbosity(uint32_t); BaseTest &increase_verbosity(); BaseTest &add_input(std::string); BaseTest &add_input_filepath(std::string); BaseTest &set_input_filepath(std::string); BaseTest &set_output_filepath(std::string); template BaseTest &set_options(std::string, T); BaseTest &on_entry(Delegate); BaseTest &on_begin(Delegate<>); BaseTest &on_end(Delegate<> cb); BaseTest &on_destroy(Delegate<> cb); void run(); void start(Callback<>); Var runnable; }; ``` # STABILITY 2 - Stable # DESCRIPTION `BaseTest` is the abstract base class of all tests. Tests should subclass this class. `BaseTest` defines the abstract domain specific language used to run tests. The `on_logger_eof` method sets the delegate called when the logger bound to the `BaseTest` test will be destroyed. The `on_log` method sets the delegate called whenever the test would emit a log message. The first argument would be the severity and the second the log line; see `Logger` for more info. The `on_event` method sets the delegate called whenever the test produces an intermediate result consumable by the caller; e.g., the `NDT` test would produce `download-speed` events every 0.5 s. In general, events emitted through this method SHOULD be like: ```JSON { "type": "type_name" } ``` That is, they SHOULD be JSON objects containing the `type` key bound to a string value indicating the event type. All other fields would be event dependent. The `on_progress` method allows to set the delegate called to indicate the caller that the test is making progress. The first argument is a number (comprised between zero and one) indicating the percentage of completion of the test. The second argument is a string describing to the user the current operation being performed by the test. The `set_verbosity` and the `increase_verbosity` methods allow to, respectively, set an increase the verbosity of the logger bound to this test. The `add_input` method adds one specific input to the list of inputs to be processed by this test. If the test does not take input, the input added using this method will be ignored. You can call this method multiple times to manually add multiple input. Input added with this method is treated exactly like input read from input files. The `add_input_filepath` adds one file path to the input paths list, which by default is empty. Tests that require input will fail if no input file path is specified and no input was provided using `add_input`, while tests that do not require input will ignore input if it is provided by the caller. If an input file path cannot be openned or read, measurement-kit will emit a warning message, but the test will not fail. If an input file path contains the string "${probe_cc}" this is replaced with the two letter country code of the network the user is running the test from in lower case (that is, if you are in Italy — country code `IT` — the string "${probe_cc}" is replaced with `it`). The `set_input_filepath` method clears previously set input file paths and then sets the path provided as argument as the unique input file path. The `set_output_filepath` method allows to set the output file path (i.e. the file where the test should write the results of the test). If you don't specify the output file path, the test will generate an output file path appropriate for the test itself. If you want to disable writing output to disk, you should pass the test the `no_file_report` setting instead, by setting its value to the string "0". The `set_options` method allows to specify test options. Note that all options values SHOULD be passed as string (future versions of measurement-kit MAY disable the possibility of passing test values as arbitrary scalar values, and the values are currently converted to strings internally anyway). The following options are defined: - *max_runtime*: the value of this variable is converted as double and, if non-negative, used to compute the max test runtime. After such amount of time has passed, the test will stop running automatically. By default, there is no maximum runtime constraint for tests. - *randomize_input*: the value of this variable is converted to bool and, if true, instructs measurement-kit to randomize the input. By default, input is randomized. The `on_entry` method allows to specify the delegate called when a test entry is about to be written to disk. The first argument receives the entry object serialized as JSON. Note that the entry format MUST be compatible with [OONI specification](https://github.com/TheTorProject/ooni-spec/tree/master/data-formats). The `on_begin` and `on_end` methods allow to specify delegates called respectively when the test is about to begin and when the test is about to end. They may be useful to start and stop filtering for tests related events, for example. You MAY specify multiple `on_end` callbacks if you wish; they will be executed sequentially at end of test. The `on_destroy` method allows to register delegates called when the test object is about to be destroyed. These delegates will be invoked sequentially by `~BaseTest`. This is the correct place to free the resources allocated for the purpose of allowing other test callbacks to run in other languages (e.g. Java and Python). The `run` method runs the test synchronously. It will not return until the test has terminated. Note that measurement-kit MAY run the test in the current thread or in a background thread. The `start` method starts the test on a background thread. The callback passed as argument will be called when the test is terminated. The `runnable` public attribute contains the `Runnable` instance that will be scheduled when you call either `run` or `start`. Note that the `runnable` attribute is a smart pointer. The pointee is guaranteed to be a valid `runnable` object since the `BaseTest` is created until the `run` or `start` methods are called; afterwards, the pointee MAY be `nullptr`. Thus attempting to call `start` or `run` again MAY result in an exception being thrown. The domain-specific-language initialization style, combined with either `run` or start`, allows to express the intention of running a specific test in a very compact and declarative way: ```C++ FooTest() .set_options("foo", false) .set_options("/tmp/file.njson") .run(); ``` Because `start` executes the test in a background thread and `run` MAY do the same, *make sure you lock shared resources* inside the callback; i.e.: ```C++ FooTest() .set_options("foo", false) .set_options("/tmp/file.njson") .run([=]() { shared_resource.lock(); // Do something with shared resource }); ``` # HISTORY The `NetTest` class appeared in MeasurementKit 0.1.0 in the `common` namespace. It was moved in the `nettests` namespace, significantly refactored, and renamed as `BaseTest` in 0.4.0. measurement-kit-0.7.1/doc/api/nettests/dns_injection.md000066400000000000000000000034161315356162600232040ustar00rootroot00000000000000# NAME DnsInjection — OONI dns-injection test # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace nettests { class DnsInjection : public OoniTest {}; } // namespace nettests } // namespace mk ``` # DESCRIPTION The `DnsInjection` class allows to run OONI dns-injection test. In addition to `OoniTest`, this class honours the following options: - *"backend"* (string): address and port (separated by colon) of the server where a DNS server is *not* actually running such that, if we receive a response, such response has necessarily been injected. Also, this test requires an input file. # EXAMPLE ```C++ // Run sync test mk::ooni::DnsInjection() .set_options("backend", "127.0.0.1:53") .set_input_filepath("test/fixtures/hosts.txt") .set_output_filepath("results.njson") .increase_verbosity() .on_log([](const char *s) { // If needed, acquire the proper locks // Process incoming log line }) .run(); // Run async test mk::ooni::DnsInjection() .set_options("backend", "127.0.0.1:53") .set_input_filepath("test/fixtures/hosts.txt") .set_output_filepath("results.njson") .increase_verbosity() .on_log([](const char *s) { // If needed, acquire the proper locks // Process incoming log line }) .run([]() { // If needed, acquire the proper locks // Handle test completion }); ``` # CAVEATS Callbacks MAY be called from a background thread. It is your responsibility to acquire the proper locks before manipulating shared objects. # HISTORY The `DnsInjection` class appeared in MeasurementKit 0.1.0. It was moved from the `ooni` to the `nettests` namespace in MeasurementKit 0.4.0. measurement-kit-0.7.1/doc/api/nettests/http_header_field_manipulation.md000066400000000000000000000015101315356162600265610ustar00rootroot00000000000000# NAME HttpHeaderFieldManipulation — OONI http-header-field-manipulation test # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace nettests { class HttpHeaderFieldManipulation : public BaseTest {}; } // namespace nettests } // namespace mk ``` # DESCRIPTION The `HttpHeaderFieldManipulation` class allows one to run the OONI http-header-field-manipulation test. In addition to those from `BaseTest`, this class honours the following options: - *"backend"* (string): the endpoint of the backend helper which is expected to echo back the HTTP request as a JSON object. This test does not require an input file. # EXAMPLE ```C++ // Run sync test mk::ooni::HttpHeaderFieldManipulation() .increase_verbosity() .run(); ``` measurement-kit-0.7.1/doc/api/nettests/http_invalid_request_line.md000066400000000000000000000034531315356162600256230ustar00rootroot00000000000000# NAME HttpInvalidRequestLine — OONI http-invalid-request-line test # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace nettests { class HttpInvalidRequestLine : public OoniTest {}; } // namespace nettests } // namespace mk ``` # DESCRIPTION The `HttpInvalidRequestLine` class allows to run OONI http-invalid-request-line test. In addition to `OoniTest`, this class honours the following options: - *"backend"* (string): URL of the server where an `echo` backend is running, such that we can evaluate what is echoed back and search for tampering. This test does not require an input file. # EXAMPLE ```C++ // Run sync test mk::ooni::HttpInvalidRequestLine() .set_options("backend", "http://127.0.0.1/") .set_input_filepath("test/fixtures/hosts.txt") .set_output_filepath("results.njson") .increase_verbosity() .on_log([](const char *s) { // If needed, acquire the proper locks // Process incoming log line }) .run(); // Run async test mk::ooni::HttpInvalidRequestLine() .set_options("backend", "http://127.0.0.1/") .set_input_filepath("test/fixtures/hosts.txt") .set_output_filepath("results.njson") .increase_verbosity() .on_log([](const char *s) { // If needed, acquire the proper locks // Process incoming log line }) .run([]() { // If needed, acquire the proper locks // Handle test completion }); ``` # CAVEATS Callbacks MAY be called from a background thread. It is your responsibility to acquire the proper locks before manipulating shared objects. # HISTORY The `HttpInvalidRequestLine` class appeared in MeasurementKit 0.1.0. It was moved from the `ooni` to the `nettests` namespace in v0.4.0. measurement-kit-0.7.1/doc/api/nettests/meek_fronted_requests.md000066400000000000000000000016441315356162600247540ustar00rootroot00000000000000# NAME MeekFrontedRequestsTest — OONI meek-fronted-requests test # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace nettests { class MeekFrontedRequestsTest : public BaseTest {}; } // namespace nettests } // namespace mk ``` # DESCRIPTION The `MeekFrontedRequestsTest` class allows one to run the OONI meek-fronted-requests test. In addition to those from `BaseTest`, this class honours the following options: - *"expected_body"* (string): the HTTP payload we are expecting from the inner Meek-fronted server. (The libmeasurementkit default is at `mk::ooni::constants::MEEK_SERVER_RESPONSE`.) This test *does* require an input file. # EXAMPLE ```C++ // Run sync test mk::ooni::MeekFrontedRequestsTest() .set_input_filepath("test/fixtures/meek_fronted_requests.txt") .increase_verbosity() .run(); ``` measurement-kit-0.7.1/doc/api/nettests/tcp_connect.md000066400000000000000000000025751315356162600226620ustar00rootroot00000000000000# NAME TcpConnect — OONI tcp-connect test # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace nettests { class TcpConnect : public OoniTest {}; } // namespace nettests } // namespace mk ``` # DESCRIPTION The `TcpConnect` class allows to run OONI tcp-connect test. This test requires an input file. # EXAMPLE ```C++ // Run sync test mk::ooni::TcpConnect() .set_input_filepath("test/fixtures/hosts.txt") .set_output_filepath("results.njson") .increase_verbosity() .on_log([](const char *s) { // If needed, acquire the proper locks // Process incoming log line }) .run(); // Run async test mk::ooni::TcpConnect() .set_input_filepath("test/fixtures/hosts.txt") .set_output_filepath("results.njson") .increase_verbosity() .on_log([](const char *s) { // If needed, acquire the proper locks // Process incoming log line }) .run([]() { // If needed, acquire the proper locks // Handle test completion }); ``` # CAVEATS Callbacks MAY be called from a background thread. It is your responsibility to acquire the proper locks before manipulating shared objects. # HISTORY The `TcpConnect` class appeared in MeasurementKit 0.1.0. It was moved from the `ooni` to the `nettests` namespace in v0.4.0. measurement-kit-0.7.1/doc/api/ooni.md000066400000000000000000000011271315356162600174460ustar00rootroot00000000000000# NAME ooni — OONI tests # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include ``` # DESCRIPTION The `ooni` module contains the following submodules: - [collector_client](ooni/collector_client.md): routines to interact with OONI's collector client - [error](ooni/error.md): OONI specific errors - [orchestrate](ooni/orchestrate.md): OONI's orchestrator - [tcp_connect](ooni/tcp_connect.md): OONI's TCP connect test - [utils](ooni/utils.md): Useful functions # HISTORY The `ooni` module appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/ooni/000077500000000000000000000000001315356162600171235ustar00rootroot00000000000000measurement-kit-0.7.1/doc/api/ooni/bouncer.md000066400000000000000000000045771315356162600211170ustar00rootroot00000000000000# NAME bouncer -- Routines to interact with OONI's bouncer # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include class BouncerReply { public: nlohmann::json response; static ErrorOr> create(std::string, Var); ErrorOr get_collector(); ErrorOr get_collector_alternate(std::string type); ErrorOr get_name(); ErrorOr get_test_helper(std::string name); ErrorOr get_test_helper_alternate(std::string name, std::string type); ErrorOr get_version(); private: nlohmann::json get_base(); }; void mk::ooni::bouncer::post_net_tests(std::string base_bouncer_url, std::string test_name, std::string test_version, std::list helpers, Callback> cb, Settings settings, Var reactor, Var logger); ``` # STABILITY 1 - Experimental # DESCRIPTION This header contains routines to interact with OONI's bouncer. The `post_net_tests` function allows to query the OONI's bouncer. The first argument is the `bouncer_url`. The second argument is the name of the test for which you need a collector. The third argument is the version of the test. The fourth argument is a list of strings containing the name of the test helpers you need. The fifth argument is a callback function called when done, with an Error or `NoError()` in case of success. In that case it will receive also a `BouncerReply` object. The `BouncerReply` class can be used to interact with an OONI's bouncer response without using directly the received JSON. The `BouncerReply` class has getter methods to access the values of the Bouncer response. The names of the methods are self explanatory. They don't throw exceptions. A new instance of this class can be created with the static constructor method `create()` giving a valid JSON and a Logger to it. This static method doesn't throw exceptions and returns an `ErrorOr` that can contain an `Error` of type: ``` - BouncerCollectorNotFoundError() - BouncerTestHelperNotFoundError() - BouncerInvalidRequestError() - BouncerGenericError() - BouncerValueNotFoundError() ``` # HISTORY The `bouncer` module appeared in MeasurementKit 0.4.0. measurement-kit-0.7.1/doc/api/ooni/collector_client.md000066400000000000000000000101761315356162600227760ustar00rootroot00000000000000# NAME collector_client -- Routines to interact with OONI's collector # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include std::string testing_collector_url(); std::string production_collector_url(); void mk::ooni::submit_report(std::string filepath, std::string collector_base_url, Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); void mk::ooni::submit_report(std::string filepath, std::string collector_base_url, std::string collector_front_domain, Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); void mk::ooni::connect(Settings settings, Callback> callback, Var reactor = Reactor::global(), Var logger = Logger::global()); void mk::ooni::create_report(Var txp, report::Entry entry, Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); void mk::ooni::update_report(Var txp, std::string report_id, report::Entry, entry, Callback callback, Settings settings = {}, Var = Reactor::global(), Var = Logger::global()); void mk::ooni::close_report(Var txp, std::string report_id, Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); ``` # STABILITY 2 - Stable # DESCRIPTION This header contains routines to interact with OONI's collector. The `testing_collector_url()` function returns the testing collector URL, and the `production_collector_url()` returns the production one. The `submit_report()` function submits the report at `filepath` using the collector identifier by `collector_base_url` and calls `callback` when done. You can also optionally specify `settings`, a `reactor`, and a `logger`. It is possible to submit reports via cloudfronting by specifying `collector_front_domain`. In this case a connection will be opened to `collector_front_domain` and the `Host` header will be set to point to the domain contained inside of `collector_base_url`. For example if you want to use cloudfronting via `a0.awsstatic.com` to speak to the canonical ooni bouncer (`https://das0y2z2ribx3.cloudfront.net`), you should do: ``` collector::submit_report("/path/to/report", "https://das0y2z2ribx3.cloudfront.net", "a0.awsstatic.com", [=](Error err) { // Handle errors }); ``` The `connect()` function connects to the address specified by the *"collector_base_url*" setting and calls `callback` when done. Optional `reactor` and `logger` could also be passed to this function. The `create_report()` function takes in input the first entry of a report and a transport connected to a collector, and creates the corresponding report on the collector. The `callback` function is called when done. Optional `settings`, `reactor` and `logger` can be specified. Beware that this function only creates the report but does not submit the actual `entry` to the report; only the specific metadata contained in `entry` would be used and submitted by this function. The callback returns as first argument the error that occureed — or `NoError()` — and as second argument the report-id identifying the report. The `update_report()` function takes in input a `entry`, a `txp` transport connected to a collector and a `report_id`, and updates the corresponding report by submitting the given report entry. The `callback` function is called when done. Optional `settings`, `reactor` and `logger` can be specified. The `close_report()` function takes in input a `txp` transport connected to a collector and a `report_id`, and closes the corresponding report. The `callback` function is called when done. Optional `settings`, `reactor` and `logger` can be specified. # HISTORY The `collector_client` module appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/ooni/error.md000066400000000000000000000004671315356162600206050ustar00rootroot00000000000000# NAME error — OONI errors # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include ``` # STABILITY 2 - Stable # DESCRIPTION This header contains OONI specific errors. # HISTORY The `error` submodule appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/ooni/orchestrate.md000066400000000000000000000310571315356162600217760ustar00rootroot00000000000000# NAME orchestrate -- code to talk to OONI's orchestrator # LIBRARY MeasurementKit (`libmeasurement_kit`, `-lmeasurement_kit`). # SYNOPSIS ```C++ #include namespace mk { namespace ooni { namespace orchestrate { std::string production_registry_url(); std::string testing_registry_url(); std::string production_events_url(); std::string testing_events_url(); class Auth { public: std::string auth_token; std::string expiry_time; bool logged_in = false; std::string username; std::string password; static std::string make_password(); Error load(const std::string &filepath) noexcept; Error loads(const std::string &data) noexcept; Error dump(const std::string &filepath) noexcept; std::string dumps() noexcept; bool is_valid(Var) const noexcept; }; class Client { public: Var logger = Logger::global(); Settings settings = {}; std::string available_bandwidth; std::string device_token; std::string events_url = production_events_url(); std::string language; std::string network_type; std::string geoip_country_path; std::string geoip_asn_path; std::string platform; std::string probe_asn; std::string probe_cc; std::string probe_family; std::string registry_url = production_registry_url(); std::string software_name = "measurement_kit"; std::string software_version = MK_VERSION; std::vector supported_tests; void register_probe( std::string &&, Callback &&callback) const; void find_location( Callback &&callback) const; void update(Auth &&, Callback &&callback) const; void list_tasks( Auth &&, Callback &&> &&callback) const; }; class Task { public: std::string events_url = production_events_url(); std::string task_id; void get(Auth &&, Callback &&callback) const; void accept(Auth &&, Callback &&callback) const; void reject(Auth &&, Callback &&callback) const; void done(Auth &&, Callback &&callback) const; }; } // namespace orchestrate } // namespace ooni } // namespace mk ``` # STABILITY 1 - Experimental # DESCRIPTION The orchestrator client communicates with OONI's orchestrator. That is a set of services telling clients which tests it is most optimal to run, and with what inputs. This allows OONI to maximize censorship coverage given the probe's current geographic location and internet service provider. More specifically, the OONI orchestrator is composed of the [registry](https://github.com/TheTorProject/proteus/tree/master/proteus-registry) and the [events](https://github.com/TheTorProject/proteus/tree/master/proteus-events) services. The `production_registry_url`, `testing_registry_url`, `production_events_url`, and `testing_events_url` functions return, respectively, the production and testing URLs of the orchestrator's registry and events web services used by OONI. The `Auth` class contains authentication information. This class is passed around by most APIs, because the JWT authentication token may be modified as a result of every call to the API. The following methods are available: The `make_password()` method is a static method that creates a random password for you. This may be useful to you when you are about to call the `Client::register_probe()` method, as described below. The `load` method loads authentication information from the specified file. The `loads` methods loads authentication information encoded in JSON from the specified string. The `dump` method stores authentication information into the specified file. The `dumps` method returns authentication information encoded as JSON. The `is_valid` method returns true if we're logged in and the authentication token is not expired, false otherwise. You can pass around the `Auth` object as long as you need it. Then you can save it on persistent storage using either `dump` or `dumps`, and you can reload it again using either `load` or `loads`. The `Client` class is the one you use to start interacting with the orchestrator services. Once you have constructed a client with the default constructor, you can configure it by setting these attributes: The `logger` attribute can be override to use a custom logger. By default, the global MeasurementKit logger is used. The `settings` attribute allows to specify optional settings. By default, an empty settings object is used, meaning that defaults will always be used. The `available_bandwidth` attribute indicates how much bandwidth you would like to use for automatic tests run through orchestration. By default, this attribute is empty, meaning that no bandwidth quota will be enforced. The `device_token` attribute uniquely identifies the app inside a device, and is only meaningful in the mobile context. This token is generated by the mobile OS for the current application and is used to identify it. See also [iOS](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW13) and [Android](https://firebase.google.com/docs/cloud-messaging/android/client#sample-register) documentation. The `events_url` attribute contains the URL used to query the `events` web service of the orchestrator. By default, this attribute is set to the production events service URL used by OONI. The `language` attribute tells the orchestrator the language used by this probe. By default this attribute is unspecified. The `network_type` attribute tells the orchestrator the type of the network the probe is connected to (i.e. Wi-Fi or mobile). By default this attribute is unspecified. The `geoip_country_path` and `geoip_asn_path` are used by the orchestrator client to guess the country and autonomous system number, if they are not provided by the API user (see below). By default these attributes are empty, meaning that MK will fail to geolocate the user. The `platform` attribute tells the orchestrator the platform in which the probe runs (e.g., `android`, `ios`). If not set, this attribute will be filled automatically by MeasurementKit when the actual request for the orchestrator is prepared. The `probe_asn` attribute tells the orchestrator the autonomous system number (ASN) of the ISP that the probe is connected to. If not set, this attribute will be filled automatically by MeasurementKit when the actual request for the orchestrator is prepared. The `probe_cc` attribute tells the orchestrator the country code of the country in which the probe currently is. If not set, this attribute will be filled automatically by MeasurementKit when the actual request for the orchestrator is prepared. The `probe_family` attribute allows to bind a set of different probes to a common family of probes. This attribute is currently reserved for future use. The `registry_url` attribute contains the URL used to query the `registry` web service of the orchestrator. By default, this attribute is set to the production registry service URL used by OONI. The `software_name` attribute is the name of the application using MeasurementKit OONI's orchestrator. By default is `measurement_kit` and you most certainly want to change it to the name of your application. The `software_version` attribute is the version of the application using MeasurementKit OONI's orchestrator. By default is the current version of MeasurementKit and you most certainly want to change it to the version of your application. The `supported_tests` attribute is the vector of test names supported by OONI that the application would like to support. If not set, this field is filled by MeasurementKit with the list of implemented tests when preparing the request for the orchestrator. Once the orchestrator client is configured, you can use its methods to send requests to the orchestrator server. The following methods are available: The `register_probe` method registers the current probe with the orchestrator system. The first argument is the password to use to identify the probe; if the password is empty, `Auth::make_password()` will be used to generate a password automatically. The second argument is a callback. The callback receives two parameters: the error that occurred (if any), and an authentication structure that contains authentication information (your username; the password you chose or a random password, depending on how you used the API; a JWT authentication token). The `find_location` method uses MeasurementKit internal functionality to query for the current autonomous system number and country code. You can optionally use this function to fill the `probe_asn` and `probe_cc` fields of client. The first argument passed to the callback is the error that occurred, if any, The second argument is the probe's ASN. The third argument is the probe country code. The `update` method updates the orchestrator's system knowledge of the state of a probe (e.g. network type, location, ISP). If the probe is not registered yet, this method will fail. The first parameter is an authentication structure whose content is used to login with the orchestrator services and call the proper `update` API. The second argument is a callback taking two arguments. The first callback argument is the error that occurred, if any. The second callback argument is a possibly-updated authentication structure. The `list_tasks` method assumes that a probe is already registered and gets the list of tasks to run. The first argument is an authentication structure. The second argument is a callback. The callback receives three parameters: whether there was an error, a possibly updated `Auth` structure, and the list of tasks. Each task is an instance of the `Task` class. The `list_tasks` callback receives as argument already configured `Task` instances. In particular, this means that the following attributes are set: The `events_url` attribute should point to the URL to be used to contact the `events` web service of the orchestrator. By default this is initialized by the orchestrator code to point to the production events URL. The `task_id` attribute should contain the ID of the task. By default this is initialized by the orchestrator code to be the ID of the task as returned by the orchestrator services. The `Task` instance could then be used to perform the following operations: The `get` method retrieves from the `events` web service the JSON data associated to the task. The semantic of this data depends on the type of task. The arguments are an authentication structure and a callback. The callback receives three parameters. The `Error` parameter indicates whether there was an error. The `Auth` parameter is a possibly updated authentication structure. The `string` parameter is a serialized JSON containing task data. The `accept` method accepts the task. The arguments are an authentication structure and a callback. The callback takes two parameters. The `Error` parameter indicates whether there was an error. The `Auth` parameter is a possibly-updated authentication structure. The `reject` method rejects the task. The arguments are an authentication structure and a callback. The callback takes two parameters. The `Error` parameter indicates whether there was an error. The `Auth` parameter is a possibly-updated authentication structure. The `done` method informs the orchestrator that a task is done. The arguments are an authentication structure and a callback. The callback takes two parameters. The `Error` parameter indicates whether there was an error. The `Auth` parameter is a possibly-updated authentication structure. # GUARANTEES 1. It is safe to let the orchestrator client die, even with slow operations like `register_probe` or `update` pending. 2. Callbacks are always delayed, even in case of immediate errors. # CAVEATS 1. The implementation will schedule any slow operation on a background thread used for I/O. As a consequence, depending on the thread from which you schedule slow operations, their final callbacks MAY be called from another thread context. 2. Slow operations operates on a copy of the internal state, so attribute changes performed after a slow operation is started will have no effect on such slow operations. # EXAMPLE See `example/ooni/oorchestrate.cpp`. # BUGS As of MK v0.7.0-alpha, the only implemented operations are `register_probe` and `update`. All other operations throw `NotImplementedError`. # HISTORY The `orchestrate` module appeared in MeasurementKit 0.7.0. measurement-kit-0.7.1/doc/api/ooni/templates.md000066400000000000000000000047231315356162600214510ustar00rootroot00000000000000# NAME templates — OONI test templates # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include void mk::ooni::dns_query(Var entry, dns::QueryType, dns::QueryClass, std::string query_name, std::string nameserver, Callback, Settings = {}, Var = Reactor::global(), Var = Logger::global()); void mk::ooni::http_request(Var entry, Settings settings, http::Headers headers, std::string body, Callback> cb, Var reactor = Reactor::global(), Var logger = Logger::global()); void mk::ooni::tcp_connect(Settings settings, Callback> cb, Var reactor = Reactor::global(), Var logger = Logger::global()); ``` # STABILITY 1 - Experimental # DESCRIPTION This submodule contains OONI test templates. The `dns_query()` function takes in input an `entry`, a query type, a query class, a name to query for, the address and port of a nameserver (separated by colon), a `callback` returning an error — or `NoError()` — as first argument and a DNS message as second argument, and optional `settings`, `reactor`, and `logger`. This function will run the specified DNS query and fill the result `entry` according to OONI conventions. The `http_request()` function takes in input an `entry`, `settings` to be passed to `http::request()`, HTTP `headers` and `body`, a `callback` returning an error — or `NoError()` — as first argument and a HTTP response as second argument, and optional `settings`, `reactor`, and `logger`. This function will run the specified HTTP request and fill the result `entry` according to OONI conventions. The `tcp_connect()` function takes in input `settings` to be passed to `net::connect()`, a `callback` returning an error — or `NoError()` — as first argument and a `Transport` as second argument, and optional `settings`, `reactor`, and `logger`. This function will attempt to connect() to the endpoint specified through `settings` and fill the result `entry` according to OONI conventions. Specifically this function honors the following settings: - *"host"* (string): host to connect to - *"port"* (int) port to connect to # HISTORY The `templates` submodule appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/ooni/utils.md000066400000000000000000000054161315356162600206130ustar00rootroot00000000000000# NAME util — Useful functions # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace ooni { void ip_lookup( Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global() ); void resolver_lookup( Callback callback, Settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global() ); report::Entry represent_string(const std::string &s); } // namespace ooni } // namespace mk ``` # STABILITY 2 - Stable # DESCRIPTION The `ip_lookup` function returns the public IP address of the host where MeasurementKit is running. It does so by querying a remote service. As of version 0.4.0 such service is `geoip.ubuntu.com`. The `callback` passed as first argument is invoked when either the IP address has ben resolved or an error occurred. In case of success the first argument of such callback will receive `NoError` and the second argument will receive the IP public IP address of the local machine; otherwise, the first argument will be the error that occurred and the second argument will be an empty string. The caller can also specify as optional `ip_lookup` arguments: additional settings, a reactor and a logger. The `resolver_lookup` function retrieves the address of the DNS resolver used by the host where MeasurementKit is running. It does so by querying a remote service. As of version 0.4.0 such service is `whoami.akamai.net`. The first argument passed to `resolver_lookup` is a callback invoked when the DNS resolver IP address is found or an error occurred. On success, the first argument passed to the callback will be `NoError` and the second argument will be the IP address of the DNS resolver. On failure, the first argument is the error that occurred and the second argument is an empty string. The caller can also optionally pass to `resolver_lookup` extra settings, a reactor and a logger. Note that the IP address returned by this function MAY NOT be the IP address of the DNS name server configured by the client, especially for large ISPs. For example, if you use `8.8.8.8` as your DNS name server, this function will return an IP address owened by Google but different from `8.8.8.8`. The `represent_string` function represent the `s` passed as argument such that it can be serialized as JSON. Is the string is ASCII or UTF-8, it is not changed. Otherwise, this function returns a JSON object where the `format` key maps to the `base64` string and the `data` key maps to the base64 representation of the original string. # HISTORY The `ooni::util` submodule was documented firstly in MeasurementKit 0.4.0. measurement-kit-0.7.1/doc/api/report.md000066400000000000000000000013721315356162600200170ustar00rootroot00000000000000# NAME report — Results of a test # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include ``` # DESCRIPTION In OONI, a test consists of one or more test cases. Each test case produces as result an entry. All such entries make a report. The `report` module contains the following submodules: - [base_reporter](report/base_reporter.md): base class for all reporters - [entry](report/entry.md): contains the results of a single test case - [error](report/error.md): errors generated by this module - [report](report/report.md): represents a report - [file reporter](report/file_reporter.md): reporter for writing on disk # HISTORY The `report` module appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/report/000077500000000000000000000000001315356162600174725ustar00rootroot00000000000000measurement-kit-0.7.1/doc/api/report/base_reporter.md000066400000000000000000000030421315356162600226470ustar00rootroot00000000000000# NAME base_reporter — Base class for reporters # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace report { class BaseReporter : public NonCopyable, public NonMovable { public: virtual Continuation open(Report) { return do_open_([=](Callback cb) { cb(NoError()); }); } virtual Continuation write_entry(Entry e) { return do_write_entry_(e, [=](Callback cb) { cb(NoError()); }); } virtual Continuation close() { return do_close_([=](Callback cb) { cb(NoError()); }); } protected: Continuation do_open_(Continuation cc); Continuation do_write_entry_(Entry, Continuation cc); Continuation do_close_(Continuation cc); }; } // namespace report } // namespace mk ``` # STABILITY 2 - Stable # DESCRIPTION The `BaseReporter` class is the base class for all reporters. By default its `open`, `write_entry`, and `close` methods do nothing and return success. This behavior is to be override by derived classes. Derived classes MUST implement their `open`, `write_entry`, and `close` overriden methods using the `do_open_`, `do_write_entry_` and `do_close_` methods provided by the base class. Such three methods implement the idempotent semantic that allows to retry `Report` operations succeeding for some `BaseReports` and failing for others. # HISTORY The `BaseReporter` class appeared in MeasurementKit 0.3.0. measurement-kit-0.7.1/doc/api/report/entry.md000066400000000000000000000022331315356162600211550ustar00rootroot00000000000000# NAME entry — Report entry # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace report { class Entry : private nlohmann::json { public: using nlohmann::json::json; static Entry array(); template operator ErrorOr(); Entry &operator=(Entry value); Entry &operator[](std::string key); void push_back(Entry); std::string dump(); bool operator==(std::nullptr_t right); bool operator!=(std::nullptr_t right); }; } // namespace report } // namespace mk ``` # STABILITY 1 - Experimental # DESCRIPTION The `Entry` class inherits publicly from `nlohmann::json` (pulled from `ext`) and behaves like a JSON object (i.e. an object with both dictionary and list semantics, depending on the context). # BUGS Currently the `Entry` object is quite difficult to manipulate; we should perhaps just implement it as an alias for `nlohmman::json` to simplify its use (as opposed to creating a wrapper for each method of such base class to which we are interested). # HISTORY The `entry` module appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/report/error.md000066400000000000000000000052751315356162600211560ustar00rootroot00000000000000# NAME error — Errors generated by the report module # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace report { MK_DEFINE_ERR(MK_ERR_REPORT(0), ReportAlreadyOpenError, "") MK_DEFINE_ERR(MK_ERR_REPORT(1), ReportNotOpenError, "") MK_DEFINE_ERR(MK_ERR_REPORT(2), ReportAlreadyClosedError, "") MK_DEFINE_ERR(MK_ERR_REPORT(3), ReportEofError, "") MK_DEFINE_ERR(MK_ERR_REPORT(4), ReportIoError, "") MK_DEFINE_ERR(MK_ERR_REPORT(5), ReportLogicalError, "") MK_DEFINE_ERR(MK_ERR_REPORT(6), DuplicateEntrySubmitError, "") } // namespace report } // namespace mk ``` # STABILITY 2 - Stable # DESCRIPTION The `report` module can generate the following errors: - *ReportAlreadyOpenError*: you called `open` on a `BaseReporter` more than once - *ReportNotOpenError*: you called `write_entry` on a `BaseReport` that has not been openned - *ReportAlreadyClosedError*: you called `write_entry` on a `BaseReport` that has already been closed - *ReportEofError*: writing the report on file yields EOF - *ReportIoError*: writing the report on file yields a I/O error - *ReportLogicalError*: it is not possible to serialize input data into the report when writing it to file - *DuplicateEntrySubmitError*: the previous call to the `write_entry` of a `BaseReporter` received an entry that is exacly equal to the one passed in the current call to `write_entry` Note that the `BaseReporter` logic may hide many of these errors when it makes sense to do so in order to make code idempotent. For example, if you call `open` on a `BaseReporter` that is already open, the result would be `NoError` rather than `ReportAlreadyOpenError`. This is to guarantee idempotence when you a have a `Report` with many `BaseReporter`s registered and you want to be able to retry `open` after if failed only on some `BaseReporters`. To detect the case where, e.g., `open` was called twice, you should check for the child errors of the returned no error. For example: ```C++ report.open([=](Error err) { if (err) { size_t idx = 0; for (Var child_err: err.child_errors) { if (!child_err and child_err.child_errors.size() >= 1 and child_err.child_errors[0] == ReportAlreadyOpenError()) { debug("- %d's open was called more than once", idx); continue; } } // Note: given that `open` is idempotent, here you can // safely retry by calling `open` again return; } // Operations to be performed on success... }); ``` # HISTORY The `error` file appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/report/file_reporter.md000066400000000000000000000020701315356162600226540ustar00rootroot00000000000000# NAME file_reporter — Writes report on a file # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace report { class FileReporter : public BaseReporter { public: static Var make(std::string path); Continuation open(Report) override; Continuation write_entry(Entry e) override; Continuation close() override; private: BaseReporter() {} }; } // namespace report } // namespace mk ``` # STABILITY 2 - Stable # DESCRIPTION The `FileReporter` class is a `BaseReporter` that writes the report onto the file passed as first argument of the `make` factory. If the file passed as first argument is `-` then the report will be written on the standard output rather than on a file named `-`. A report file will consist of zero or more entries. Each entry is a JSON document serialized on a single line of text. Newlines could either be `\n` or `\r\n`. # HISTORY The `FileReporter` class appeared in MeasurementKit 0.2.0. measurement-kit-0.7.1/doc/api/report/report.md000066400000000000000000000121221315356162600213250ustar00rootroot00000000000000# NAME report — Structure representing a report # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace report { class Report { public: const std::string software_name = "measurement_kit"; const std::string software_version = MEASUREMENT_KIT_VERSION; const std::string data_format_version = "0.2.0"; std::string test_name; std::string test_version; std::string probe_ip; std::string probe_asn; std::string probe_cc; tm test_start_time; Settings options; Report(); void add_reporter(Var reporter); void fill_entry(Entry &entry) const; Entry get_dummy_entry() const; void open(Callback callback); void write_entry(Entry entry, Callback callback); void close(Callback callback); }; } // namespace report } // namespace mk ``` # STABILITY 2 - Stable # DESCRIPTION The `Report` class contains the results of a test. In turn, a test is composed of one or more measurements. Each measurement produces a report entry. It is the test responsibility to instantiate the `Report`, to properly fill all the public attributes of the `Report`, to `open()` the report at the beginning of the test, to `write_entry()` whenever a new entry is produced, to `close()` the report at the end of the test. A `Report` can be associated to one or more reporter objects inheriting from the `BaseReporter` class. Such reporters define the behavior of a `Report` when it is openned, when a entry is submitted, when the report is closed. The default `BaseReporter` class does nothing, but there are more specialized classes, e.g. `FileReporter` that writes the report onto a specified file, and `ooni::OoniReporter` that submits the report to the OONI collector service. The `add_reporter` method allows to associate an implementation of the `BaseReporter` interface to the current report. This method can be called more than once; each time it is called it appends the specified reporter object to the list of reporters to be used by this class. Note that you SHOULD NOT add reporters once you have `open()`ed the report. The `fill_entry` method takes in input a `Entry` and fills its generic fields by copying the public `Report` fields that the test owning the report should have initialized. The `get_dummy_entry` method instantiates an empty `Entry`, initializes it by calling `fill_entry`, and then returns it. This is used by OONI's reporter to pass an empty entry representing the whole report to OONI's collector. The `open` method opens the report by calling the `open` method of each registered reporter. This method MUST be idempotent, i.e. if a reporter's `open` succeeds and you call again the report's `open`, the `open` of the reporter would not be called again. This allows you to safely call again `open` if *some* of the reporters did not open correctly, without affecting the state of the reporters that did open correctly. The `write_entry` method writes the entry by calling the corresponding method of each registered reporter. Also this method is idempotent, i.e. also in this case you can call `write_entry` again if some reporters failed without writing more than once the same entry for the reporters that succeeded. The `close` method closes the report by calling the corresponding method of each registered repoter. Also this method is idempotent, i.e. if not all reporters correctly closed, you can call it again and the `close` would be retried only for the reports that failed to close. The `open`, `write_entry`, and `close` methods are asynchronous and you MUST wait for them to complete and call the `callback` provided as argument. In case of success, `NoError()` is passed to the callback; otherwise, the error passed to the callback indicates what went wrong. Specifically, since each of these three operations runs in parallel the indicated operation to all the registered reporters, in case of failure the error should be of type `ParallelOperationError`. To investigate more in depth what went wrong and what succeded, you can use this code snippet to inspect the child errors of the returned error: ```C++ report.open([=](Error err) { if (err) { size_t idx = 0; for (Var child_err: err.child_errors) { if (!child_err) { debug("- %d succeeded", idx); continue; } debug("- %d failed: %s", idx, child_err->explain().c_str()); idx += 1; } // Note: given that `open` is idempotent, here you can // safely retry by calling `open` again return; } // Operations to be performed on success... }); ``` # BUGS You cannot overlap calls to `open`, `write_entry` or `close`. That is, you MUST NOT call any of the three above method while any of the three above methods is pending. You MUST first way for the pending method to complete, which is signalled by the corresponding callback being called. # HISTORY The `Report` class appeared in MeasurementKit 0.3.0. measurement-kit-0.7.1/doc/api/traceroute.md000066400000000000000000000010511315356162600206530ustar00rootroot00000000000000# NAME traceroute — Traceroute module # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include ``` # STABILITY 1 - Experimental # DESCRIPTION The `traceroute` module contains the following submodules: - [android](traceroute/android.md): Code to run traceroute for Android - [error](traceroute/error.md): Traceroute specific errors - [interface](traceroute/interface.md): Generic traceroute interface # HISTORY The `traceroute` library appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/traceroute/000077500000000000000000000000001315356162600203345ustar00rootroot00000000000000measurement-kit-0.7.1/doc/api/traceroute/android.md000066400000000000000000000020571315356162600223020ustar00rootroot00000000000000# NAME android — Android implementation of traceroute interface. # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace traceroute { class AndroidProber : public Prober {}; } // namespace traceroute } // namespace mk ``` # STABILITY 1 - Experimental # DESCRIPTION This is the Android implementation of traceroute interface. This implementation is meant to run on Android but can run on all Linux systems. # EXAMPLE ```C++ auto prober = mk::traceroute::Prober(true, 11829); prober.send_probe("8.8.8.8", 33434, ttl, payload, 1.0); // send a probe prober.on_result([&prober, &ttl, &payload](ProbeResult r) { /* Do something when send_probe gives a result */ }); prober.on_timeout([&prober, &ttl, &payload]() { /* do something when send_probe has a timeout */ }); prober.on_error([&prober, &ttl, &payload](Error err) { /* handle error that occurred */ }); ``` # HISTORY The `android` submodule appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/traceroute/error.md000066400000000000000000000020271315356162600220100ustar00rootroot00000000000000# NAME Error — A traceroute error. # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include ``` # STABILITY 1 - Experimental # DESCRIPTION The following traceroute errors are defined: - *mk::traceroute::SocketCreateError*: socket creation error - *mk::traceroute::SetsockoptError*: Setsockopt error - *mk::traceroute::ProbeAlreadyPendingError*: a probe is already pending - *mk::traceroute::PayloadTooLongError*: payload is too long - *mk::traceroute::StorageInitError*: error in storare initialization - *mk::traceroute::BindError*: bind error - *mk::traceroute::EventNewError*: event_new() error - *mk::traceroute::SendtoError*: sendto() error - *mk::traceroute::NoProbePendingError*: no probe is pending - *mk::traceroute::ClockGettimeError*: clock_gettime() error - *mk::traceroute::EventAddError*: event_add() error - *mk::traceroute::SocketAlreadyClosedError*: socket is already closed # HISTORY Traceroute specific errors appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/api/traceroute/interface.md000066400000000000000000000057701315356162600226270ustar00rootroot00000000000000# NAME interface - Interface of the traceroute module. # LIBRARY MeasurementKit (libmeasurement_kit, -lmeasurement_kit). # SYNOPSIS ```C++ #include namespace mk { namespace traceroute { class Interface { public: void send_probe(std::string addr, int port, int ttl, std::string payload, double timeout); void on_result(Callback cb); void on_timeout(Callback<> cb); void on_error(Callback cb); }; } // namespace traceroute } // namespace mk ``` # STABILITY 1 - Experimental # DESCRIPTION This is the interface of the traceroute module. Specific implementations should implement this interface. The `send_probe()` method sends a single UDP packet to the specified `addr` and `port`, with the specified `ttl` and `payload` and waits up to `timeout` seconds for a response (either valid or for a ICMP error). The `on_result()` method allows to set the callback called when a response (either valid or a ICMP error) is returned. The `ProbeResult` struct is like: ```C++ class ProbeResult { public: std::string interface_ip; // Host that replied int ttl = 0; // Response TTL double rtt = 0.0; // Round trip time bool is_ipv4 = true; // Are we using IPv4? unsigned char icmp_type = 255; // Raw ICMP/ICMPv6 type unsigned char icmp_code = 255; // Raw ICMP/ICMPv6 code ssize_t recv_bytes = 0; // Bytes recv'd bool valid_reply = false; // Whether reply is valid std::string reply; // Reply packet data ProbeResultMeaning get_meaning(); }; ``` where `interface_ip` is the address of the host that send the ICMP response, `ttl` is the response TTL, `rtt` is the time elapsed since sending the UDP packet until receiving the response or the ICMP error, `is_ipv4` indicates whether the response is ICMPv4 or ICMPv6, `icmp_type` and `icmp_code` are the raw ICMPv4 or ICMPv6 type and code values received, `recv_bytes` is the number of bytes received, `valid_reply` is `true` if we received a response and `false` if we received a ICMP error, and `reply` contains the reply if `valid_reply` is `true`. The `get_meaning()` method maps the raw ICMP type and code into the following structure, thus abstracting the differences between ICMPv4 and ICMPv6: ```C++ enum class ProbeResultMeaning { OTHER = 0, // Another meaning NO_ROUTE_TO_HOST = 1, // No route to host ADDRESS_UNREACH = 2, // E.g., link down PROTO_NOT_IMPL = 3, // UDP not implemented PORT_IS_CLOSED = 4, // Port is closed TTL_EXCEEDED = 5, // TTL is too small ADMIN_FILTER = 6, // E.g., firewall rule GOT_REPLY_PACKET = 7, // We got a real reply packet }; ``` The `on_timeout()` method allows to set the callback called when a timeout occurs. The `on_error()` method allows to set the callback called when a network error (distinct from receiving a ICMP error) occurs. # HISTORY The `interface` submodule appeared in MeasurementKit 0.1.0. measurement-kit-0.7.1/doc/build/000077500000000000000000000000001315356162600165055ustar00rootroot00000000000000measurement-kit-0.7.1/doc/build/android.md000066400000000000000000000043061315356162600204520ustar00rootroot00000000000000# Cross-compiling MK dependencies for Android We have [a specific repository](https://github.com/measurement-kit/android-libs) for compiling MeasurementKit for Android. This file explains how you can get the Android NDK and how to use it to cross compile dependencies for Android. ## Installing the NDK ### On Linux The first step to compile measurement-kit for Android is to download the NDK (Native Development Kit) from [developer.android.com]( https://developer.android.com/tools/sdk/ndk/index.html). We have tested this repository with version 10e of the NDK. Then copy the downloaded file to `$HOME/Android` and from inside this directory run the downloaded file to unpack the NDK: $ pwd /home/simone/Android $ ./android-ndk-r10e-linux-x86_64.bin ### On macOS using brew You can install it with brew. Just type the following: $ brew install android-ndk but from our experience we recommend to [install it using Android studio]( https://developer.android.com/ndk/guides/index.html#download-ndk) since this is the most reliable way to get a working ndk-build. On macOS, Android studio installs the ndk-build at `~/Library/Android/sdk/ndk-bundle/ndk-build`. ## Cross compiling MeasurementKit dependencies for Android The `./dependency` script allows to create the required custom toolchains and to cross-compile the dependencies for all the architectures available for Android. If you run the script without arguments, it will print the options it accepts and the available Android architectures for which you can cross compile: $ ./build/android/dependency usage: ./build/android/dependency NDK_DIR spec To cross-compile you need to tell the script where did you install the NDK and which dependency `spec` you want to build. For example, on macOS you can use the following command line: $ ./build/android/dependency ~/Library/Android/sdk/ndk-bundle libevent to build libevent. In the above examples we have shown the path to the Android NDK on macOS. If you followed the instructions for Linux, you should have written instead: $ ./build/android/dependency $HOME/Android/android-ndk-r10e/ [spec] See also [the documentation of the core script used to build dependencies](dependency.md). measurement-kit-0.7.1/doc/build/dependency.md000066400000000000000000000065551315356162600211600ustar00rootroot00000000000000# Building dependencies ## Overview The objective of building dependencies is to obtain two signed tarballs, one for iOS and one for Android, that can be downloaded during the respective build processes, so to avoid compiling all dependencies each time. Dependencies are built using the `./build/dependency` script whose wrappers for Android and iOS are, respectively, `./build/android/dependency` and `./build/ios/dependency`. The `dependency` script reads the proper package build specifications from `./build/spec`, downloads the sources, possibly applies patches, and builds the dependency. The wrapper scripts set environment variable such that the build dependency can be integrated into the iOS or Android build process. ## Cross-compiling dependencies To cross compile a dependency (e.g. `libressl`) for Android you can use this command: ``` ./build/android/dependency /path/to/ndk libressl ``` Where `/path/to/ndk` is the path where the NDK has been installed, `$HOME/Library/Android/sdk/ndk-bundle` on macOS if you have installed the NDK using Android studio. See [Android specific documentation](android.md) for more information. The result would be a tarball in the repository toplevel directory for each Android architecture of interest. You should create the digital signature of the tarball using: ``` ./build/sign $tarball ``` Similarly, for iOS do: ``` ./build/ios/dependency libressl ``` Assuming all the dependencies have been compiled, you can cross compile MeasurementKit for iOS as it was a dependency using this command: ``` ./build/ios/dependency mk ``` and for Android: ``` ./build/android/dependency /path/to/ndk mk ``` This may not necessarily be the best way to cross compile MK for a specific platform, however it is a supported option. ## Submitting and fetching dependencies You should upload the tarballs and their signature in the [measurement-kit/dependencies](https://github.com/measurement-kit/dependencies) repository. Use the latest release for that (depending on the maturity stage such release may either be considered stable or unstable). Then, you can download such dependencies using the `./build/fetch-dep` script and, in particular, its iOS and Android wrappers. For example, the following command ``` ./build/android/fetch-dep -ps jni ``` will download all Android related files (i.e. files containing the string `jni` into their name) from the latest release, verify their digital signature and install them locally just like they have been compiled now. Similarly, you should use this command for iOS ``` ./build/ios/fetch-dep -ps iphone ``` that downloads only files containing `iphone` in their name. Some dependencies, such as libevent, require that you either have compiled other dependencies (such as libressl) or that you have fetched them just when compiling as explained above. ## Creating the dependencies archives To create the dependencies archives (i.e. the archives actually processed by the MK build process), just download all the platform related already compiled and published dependencies, e.g. ``` ./build/android/fetch-dep -ps jni ``` Then create a single archive containing all the compiled artifacts: ``` ./build/android/archive-deps ``` This will create an archive and it signature, and you should upload both to the [measurement-kit/dependencies](https://github.com/measurement-kit/dependencies) repository, in the latest release. measurement-kit-0.7.1/doc/coding-style.md000066400000000000000000000112551315356162600203350ustar00rootroot00000000000000# Coding style This document details coding style issues. ## Formatting source code As regards the way in which code should be formatted, we use `clang-format` for this task. Just run: ```bash clang-format -i $files ``` to have `$files` formatted according to the project's style. ## Code patterns We organize similar bits of code using specific patterns. ### Deferred operations In measurement-kit we have several places where a slow operation must be called and its result (or error) must be processed after some time. One such example is the delayed function call, where the programmer wants a function to be called after a specified amount of time. Another, similar example is the DNS query, where the programmer wants to resolve a domain name to one, or more, IP addresses. In these cases, and in similar cases, measurement-kit API must expose a function that receives the requested parameters and calls a function when the operation is complete. To represent a function to be called later, we use the `Callback` template, which actually is just an alias for ```C++ template using Callback = std::function; ``` so you can write `Callback` as opposed to `std::function`, which is not only shorter but it also express clearly that the function is expected to be called sometime later (and typically not directly by the function to which it is passed). For example, ```C++ /// Calls the callback after timeout seconds have passed. /// \param timeout Number of seconds of delay. /// \param callback Callback. /// \note This function implicitly uses the default poller. void call_later(double timeout, Callback<> callback); ``` Internally, this could be implemented using a closure object (1) created when `call_later()` is called, (2) used to hold `timeout`, `callback` and other bits of state needed to implement `call_later()`, and (3) destroyed when `callback` has been called. That is, ```C++ class CallLater { public: CallLater(double t, Callback<> f); void handle_cb(); private: double timeout; Callback<> cb; event_system_handle_t *call = nullptr; ~CallLater(); }; extern "C" { static void c_callback(void *p) { static_cast(p)->handle_cb(); } } // extern "C" CallLater::CallLater(double t, Callback<> f) { timeout = t; cb = f; call = event_system_call_later(t, c_callback, this); } void CallLater::handle_cb() { cb(); delete this; } CallLater::~CallLater() { event_system_free_handle(call); } void call_later(double timeout, Callback<> callback) { new CallLater(timeout, callback); } ``` The structure of the implementation should help to understand why we do not expose `CallLater` directly and instead only expose `call_later()`. The destructor of `CallLater` shall be private because the closure shall delete itself when it is complete, hence better to prevent the programmer to call the destructor herself. But then, assuming we expose `CallLater`, to issue a delayed call the programmer would need to write this: ```C++ new DelayedCall(3.14, []() { // Do something }); ``` Which is kind of strange because you allocate on the heap an object that has the ownership of itself, whose pointer you cannot delete, and that has no other methods that you could call. Once it is clear how the code works this is OK, but for casual hackers reading the code it may be confusing. To make the above less confusing we could restructure the code to work differently and require the programmer to write: ```C++ new DelayedCall(3.14, [](DelayedCall *call) { // Do something delete call; }); ``` But that's annoying because the programmer needs to remember to delete the delayed call object. Since this is something to be done in any case, it would probably be better to let the library do that. So, we concluded that the most abstract approach (and the simpler one for a library user) is to just expose the `call_later` function. In fact, being this approach abstract, we can decide to implement it also in the following, more compact way: ```C++ struct CallLater { Callback<> callback; event_system_handle_t *call = nullptr; }; extern "C" { static void c_callback(void *p) { auto context = static_cast(p); context->callback(); event_system_free_handle(context->call); delete context; } } // extern "C" void call_later(double timeout, Callback<> callback) { auto context = new CallLater; context->callback = std::move(callback); context->call = event_system_call_later(timeout, c_callback, context); } ``` The advantage of this second version of the code is that it is more compact, and hence that would be our preferred choice. measurement-kit-0.7.1/doc/index.md000066400000000000000000000054051315356162600170430ustar00rootroot00000000000000Welcome to Measurement Kit **v0.7.1** documentation! # How to generate documentation We use [mkdocs](http://www.mkdocs.org/) to generate HTML documentation from markdown files. To regenerate documentation, you need to have a recent version of Python installed. Specifically, the following commands shows how you can generate the HTML files from the markdown. You must run them from the toplevel directory (i.e. the one that contains the `AUTHORS` file): ``` virtualenv __venv__ source __venv__/bin/activate pip install mkdocs mkdocs build ``` # Public API MeasurementKit is composed of several libraries. Follow the links below to find out more on a specific library API. - [common](api/common.md): common functionality - [dns](api/dns.md): dns library - [ext](api/ext.nd): third party headers - [http](api/http.md): http library - [mlabns](api/mlabns.md): m-lab name service library - [ndt](api/ndt.md): network diagnostic tool library - [net](api/net.md): low-level networking library - [nettests](api/nettests.md): drive running network tests - [ooni](api/ooni.md): open observatory of network interference library - [portable](api/portable.md): portable C library headers - [report](api/report.md): library for managing test results - [traceroute](api/traceroute.md): traceroute library If you're new to MeasurementKit and all you want is to use it to run network tests, start from [nettests](api/nettests.md). Each library is contained in its own header file named after the module and stored inside the `measurement_kit` directory in the include path. Therefore, to pull `dns` module's definitions, write: ```C++ #include ``` All MeasurementKit code is contained in the `mk` namespace. There are child namespaces for each module except `common`. In fact, definitions contained in `common.hpp` are so common that they live in the `mk` namespace alone to save the user a few types. For example, to use the `Error` class of the `common` module, type: ```C++ #include // ... mk::Error error; ``` (In general, you don't need to include `common.hpp` directly, because any other Measurement Kit header includes `common.hpp`.) For all other submodules, the definitions live inside a sub-namespace named after the module. So, for example, to access class `Buffer` in the `net` module, you need to type: ```C++ #include // ... mk::net::Buffer buffer; ``` Of course, to write less in C++ files, you can use a `using namespace` declaration to pull everything from the `mk` namespace. For example: ```C++ #include using namespace mk; // ... Error error; net::Buffer buffer; ``` The above example also shows that `Error` (and other `common.hpp` definitions) are automatically pulled by `net.hpp`. measurement-kit-0.7.1/doc/tutorial/000077500000000000000000000000001315356162600172515ustar00rootroot00000000000000measurement-kit-0.7.1/doc/tutorial/android.md000066400000000000000000000021141315356162600212110ustar00rootroot00000000000000# Android Tutorial Measurement Kit is written in C++. Android applications are written in Java. For an Android application to use Measurement Kit, there is need to write JNI (Java Native Interface) code. We already wrote JNI code for Measurement Kit. This code is hosted by the [measurement-kit-android]( https://github.com/measurement-kit/measurement-kit-android) GitHub repository. If your objective is to develop Android applications based on Measurement Kit, you are really looking for that repository. It also contains a tutorial explaining how to integrate Measurement Kit into your Android app. This tutorial, instead, explains how you could write your own JNI code based on Measurement Kit cross compiled for Android. To understand this, you first need to understand how to cross compile Measurement Kit for Android. Then, you need to understand how to write your own JNI wrappers for Measurement Kit API. ## How to cross compile for Android We have not written this section of the tutorial yet. ## Writing your own JNI wrappers We have not written this section of the tutorial yet. measurement-kit-0.7.1/doc/tutorial/ios.md000066400000000000000000000274041315356162600203740ustar00rootroot00000000000000# iOS tutorial This tutorial explains how to integrate Measurement Kit into your iOS Objective-C application. You need to understand how to generate (or obtain) Measurement Kit frameworks. And how to integrate your code with Measurement Kit code. Throughout this tutorial we assume that you are running MacOSX 10.11 El Capitain (i.e. the version of OSX with which we tested the code presented in this tutorial) and Xcode 9.2. Other versions of both may work, especially if close to the ones we tested. ## How to generate (or obtain) the frameworks We have published [specification for Measurement Kit]( https://github.com/CocoaPods/Specs/tree/master/Specs/measurement_kit ) on [CocoaPods](https://cocoapods.org/). We have not yet published a specification to directly get the binaries, however. Hence, for now you will need the command line tools installed on your build system to build the Pod. To install Xcode command line tools on your system, run: xcode-select --install Next, you need to install CocoaPods. To this end, run this command: sudo gem install cocoapods As a third step, create a new Xcode project, following these steps: - open Xcode and select "Create a new XCode project" - select "Create a single view application" - fill in the product name - make sure that the selected language is Objective-C - select the place where to save the application Then, you shall use the terminal and `cd` to the directory containing the `.xcodeproj` file. There, create a file called `Podfile` and write inside it the following content: ```ruby target '' do pod 'measurement_kit' end ``` (Instead, if you want to install measurement_kit directly from its git repository, write the following inside the `Podfile`: ```ruby target '' do pod 'measurement_kit', :git => 'https://github.com/measurement-kit/measurement-kit.git', :branch => 'master' end ``` ) Save and quit, then type: pod install --verbose This will run for a long time. It will download Measurement Kit from GitHub and cross-compile it for the iOS emulator and devices. When this command terminates, new files will appear in your application directory, including a `.xcworkspace` file that, from now on, you shall use to open your application. Basically it is an Xcode project container, which references both the application `.xcodeproj` and the compiled Pods. As for the compiled Pods, they are inside the `Pods` directory. In particular, if you're curious, under the following path Pods/measurement_kit/mobile/ios/Frameworks/ you will find all the frameworks needed to integrate Measurement Kit with your application. (In general, you can use the `.xcworkspace` file to manage you project, but you may also want instead to use directly the frameworks, even though this is not the expected usage.) ## How to integrate Measurement Kit code Open the `.xcworkspace` file using Xcode. For example clicking over it, or with `open` if you are using the command line. You will find that your workspace contains two projects. One named `Pods` will contain the compiled frameworks. The other, named after your project, unsurprisingly contains exactly your project. Here, for simplicity, we are not going to change the view. Rather we are going to run a Measurement Kit test just after the application has started (i.e. in the `didFinishLaunchingWithOptions` method of the `AppDelegate.m` file). As a first step, we need to rename the file `AppDelegate.mm`. In fact, Measurement Kit is written in C++. So, we need to tell Xcode that the app delegate should be compiled using Objective-C++ (`.mm`) rather than using Objective-C (`.m`). To rename the file, click on its name for a long time until it becomes editable, then rename it. We are going to implement OONI's tcp-connect test. So, you need to include Measurement Kit OONI's functionality. To this end, modify the top of your `AppDelegate.mm` file such that it looks like this: ```Objective-C #import "AppDelegate.h" #include @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. return YES; } // more code below... ``` We have basically just added `measurement_kit/ooni.hpp` header to the auto-generated file. Such header contains all MeasurementKit definitions useful to run OONI tests. Then, try to build the project to ensure that everything works. To implement the test, we need to add more code to the currently-empty implementation of `didFinishLaunchingWithOptions`. To do that, we need to understand the ingredients required for running the test. The tcp-connect tests is a test that attempts to connect to a list of domain names of IP addresses. And measures, for each domain name or IP address, whether the connection suceeded or not. The first step would be to gather the device DNS resolver. For the sake of simplicity, here we're going to use `8.8.8.8` as a resolver. As a second step, you need to add to the application a file telling the tcp-connect test which hosts to test. To this end, create a new file named `inputs.txt` in the "Supporting Files" folder of your project in Xcode. To create a new file, right click on "Supporting Files" and then select "New File" from the drop-down menu. Then select "Empty", and name the file "inputs.txt". Write some domain names inside this file, for example: ``` ooni.torproject.org nexa.polito.it measurement-kit.github.io ``` Now you need to obtain the path of this file in the final application. To this end, append the following code snippet near the end of the above loop, just below the TODO comment indicated above: ```Objective-C // Get path of input file: NSBundle *bundle = [NSBundle mainBundle]; NSString *path = [bundle pathForResource:@"inputs" ofType:@"txt"]; const char *input_path = [path UTF8String]; NSLog(@"path of input file: %@", path); ``` We are now ready to invoke the tcp-connect test. Add the following code just below the code you just added: ```Objective-C mk::ooni::TcpConnect() .increase_verbosity() .set_options("port", 80) .set_options("dns/nameserver", "8.8.8.8") .set_input_filepath(input_path) .run(); ``` This will run the tcp-connect test in synchronous mode. That is, the current thread will be blocked until the test completes. Running a synchronous test, however, is not so good for a mobile application because it blocks the UX for the whole duration of the test. To instruct Measurement Kit to run the test asynchronously (i.e. to run the test in the background and notify us when done) we can modify the code above as follows: ```Objective-C mk::ooni::TcpConnect() .increase_verbosity() .set_options("port", 80) .set_options("dns/nameserver", "8.8.8.8") .set_input_filepath(input_path) .run([]() { // TODO This code runs in a background thread and is // called when the tcp-connect test is complete }); ``` Basically, the C++14 lambda passed to `run()` is called from a background thread when the test is complete. Now, to do something useful in that lamba, let's simulate sending a message to the UX using `dispatch_async`. Let's create the message before running the test. Let's edit the C++14 lambda capture list to retain a reference to `message`. And finally let's use `dispatch_async` to dispatch the message when we are done. ```Objective-C NSString *message = @"message-0xdeadidea"; mk::ooni::TcpConnect() .increase_verbosity() .set_options("port", 80) .set_options("dns/nameserver", "8.8.8.8") .set_input_filepath(input_path) .run([message]() { // Caution: code called from a background thread dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"test complete: %@", message); }); }); NSLog(@"test in progress: %@", message); ``` The "test in progress" message is there so that it's clear from the logs that the test is run asynchronously (i.e. that the `run()` returns immediately and the C++14 lambda is only called when the test is complete). To complete our example, let's also capture the test logs and insert them into an array, which will be printed once the test is complete. This simulates the case where you store separate logs for different tests. ```Objective-C NSString *message = @"message-0xdeadidea"; NSMutableArray *logs = [[NSMutableArray alloc] init]; NSLock *mtx = [[NSLock alloc] init]; mk::ooni::TcpConnect() .increase_verbosity() .set_options("port", 80) .set_options("dns/nameserver", "8.8.8.8") .set_input_filepath(input_path) .on_log([logs, mtx](const char *s) { // Caution: code called from a background thread // Caution: `s` points to a static buffer, so I must copy it [mtx lock]; [logs addObject:[NSString stringWithUTF8String:s]]; [mtx unlock]; }) .run([message, logs, mtx]() { // Caution: code called from a background thread dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"test complete: %@", message); [mtx lock]; for (NSString *line in logs) { NSLog(@"> %@", line); } [mtx unlock]; }); }); NSLog(@"test in progress: %@", message); ``` I've also added a lock to ensure that the logs object is always accessed safely. In this example, that is way overkill. But I wanted to show you the most general case (i.e. the one in which the view is allowed to access the `logs` object while tests are running). Also, the reason why I copy `s` is that actually `s` is just a pointer in a static buffer, hence it must be copied. Storing only the pointer is not very useful, since the buffer is overwritten every time a new log line is generated. The final example code is the following: ```Objective-C #import "AppDelegate.h" #include @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Get path of input file: NSBundle *bundle = [NSBundle mainBundle]; NSString *path = [bundle pathForResource:@"inputs" ofType:@"txt"]; const char *input_path = [path UTF8String]; NSLog(@"path of input file: %s", input_path); NSString *message = @"message-0xdeadidea"; NSMutableArray *logs = [[NSMutableArray alloc] init]; NSLock *mtx = [[NSLock alloc] init]; mk::ooni::TcpConnect() .increase_verbosity() .set_options("port", 80) .set_options("dns/nameserver", "8.8.8.8") .set_input_filepath(input_path) .on_log([logs, mtx](const char *s) { // Caution: code called from a background thread // Caution: `s` points to a static buffer, so I must copy it [mtx lock]; [logs addObject:[NSString stringWithUTF8String:s]]; [mtx unlock]; }) .run([message, logs, mtx]() { // Caution: code called from a background thread dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"test complete: %@", message); [mtx lock]; for (NSString *line in logs) { NSLog(@"> %@", line); } [mtx unlock]; }); }); NSLog(@"test in progress: %@", message); return YES; } // more code here... ``` As a final remark, to test this sample application on a real device I also needed to disable bitcode, since the frameworks compiled using Cocoa Pods do not use bitcode. measurement-kit-0.7.1/doc/tutorial/unix.md000066400000000000000000000217661315356162600205720ustar00rootroot00000000000000# Unix tutorial This tutorial explains how to compile, install and use Measurement Kit on Unix. ## Optional: running tutorial in a vagrant If you want to run this tutorial in a Vagrant, take advantage of the [Vagrantfile](../../Vagrantfile) and copy it somewhere on the file system. Then enter into the directory containing the Vagrantfile and run: ``` vagrant up yakkety ``` To spin up an Ubuntu 16.10 machine. Then run: ``` vagrant ssh yakkety ``` At this point you are inside the Vagrant. ## Getting the sources To this end, you can either clone the git repository or go straight into the download page and grab the latest sources. ### Cloning the git repository To clone the repository, you need git installed. Then run: ``` git clone https://github.com/measurement-kit/measurement-kit ``` The result is a directory called `measurement_kit`. Enter into this directory and run the following command to prepare the sources for being compiled: ``` ./autogen.sh ``` This script will perform the following operations: 1. update the `.gitignore` file 2. generate a list of files to be compiled in `./include.am` 3. get the latest [GeoIP](https://www.maxmind.com) databases 4. run `autoreconf -i` to initialize the [GNU build system]( https://en.wikipedia.org/wiki/GNU_build_system) used by Measurement Kit For this step to succeed, you certainly need to have installed: - the usual, standard Unix tools (grep, sed, etc.) - wget (for downloading GeoIP) - gzip (for uncompressing GeoIP) - autoconf, automake, and libtool (for `autoreconf -i`) ### Downloading the sources archive Go to the [github releases page](https://github.com/measurement-kit/measurement-kit/releases) and download the archive of the latest release. **Note**: you want to download a file called `measurement-kit-$version.tar.gz` and not a file labelled by GitHub as "Source code", because the latter is equivalent to performing a `git clone`, for which you should follow the above instructions. Once you have downloaded the sources archive, you should verify its digital signature, extract the sources from it, and optionally download the [GeoIP](https://www.maxmind.com) databases, as described below. #### Verifying the sources archive In addition to the `measurement-kit-$version.tar.gz` file, you should also download its PGP signature, `measurement-kit-$version.tar.gz.asc`. Typically, releases are signed by `Simone Basso ` with a PGP key having this fingerprint: ``` 7388 77AA 6C82 9F26 A431 C5F4 80B6 9127 7733 D95B ``` To verify the PGP signature, you need `gpg` installed. Then, fetch the aforementioned public key with: ``` gpg --recv-keys 738877AA6C829F26A431C5F480B691277733D95B ``` Finally, verify the digital signature with: ``` gpg --verify measurement-kit-$version.tar.gz.asc ``` The result should indicate that the signature is good. #### Extracting from the sources archive Once you have verified the digital signature, uncompress the archive: ``` tar -xzf measurement-kit-$version.tar.gz ``` This will create a directory called `measurement-kit-$version`, in which you should now enter. #### Downloading GeoIP databases If you plan to run regress tests, at this point you should also download the [GeoIP](https://www.maxmind.com) databases with: ``` ./build/get-geoip ``` This script will use wget and gzip to fetch and unpack the latest GeoIP databases in the current working directory. ## Configure, make, make install You should now be in the top level directory of the sources containing an executable script called `./configure`. The bare-bone procedure to compile and install Measurement Kit is the following: ``` ./configure make make install # typically you need to run this step as root ``` In the following, we describe each step in detail. ### configure The job of the configure script is to make sure that Measurement Kit will build on your system. Specifically, the configure script should check for at least for: - A compiler suite implementing C90 and C++14; e.g. [clang]( http://clang.llvm.org/) or [gcc](https://gcc.gnu.org/). - A C++14 standard library such as [libc++](http://libcxx.llvm.org/) or [libstdc++](https://gcc.gnu.org/libstdc++/). - [libevent](https://github.com/libevent/libevent). - [geoip](https://github.com/maxmind/geoip-api-c). - either [openssl](https://github.com/openssl/openssl) or (preferred) [libressl](https://github.com/libressl-portable/portable). We routinely compile and test Measurement Kit on: - Ubuntu 16.10 Yakkety Yak - Void Linux - macOS 10.12 sierra For cross compiling the library on mobile devices, as of Measurement Kit v0.4.0 we use: - libevent 2.0.22 (branch `patches-2.0`) - geoip 1.6.9 - libressl 2.4.4 To run the configure script, simply type: ``` ./configure ``` If a dependency is missing, the script will stop and tell you how you could install such dependency with the proper `apt-get install` command (for Debian-like systems) and `brew install` command (for macOS; note that `brew` in not installed by default on macOS, and you need to [install it manually](http://brew.sh/)). In addition to those two options, it will also tell you how you could take advantage of our cross build system for mobile devices to compile the dependency yourself (not recommended, better relying on your distribution package manager). You can pass options to configure to change its behavior. To see all available options, run `./configure --help`. These are some of the most commonly used options: - `--enable-coverage`: build for running coverage tests - `--disable-examples`: do not compile examples - `--disable-binaries`: only build `libmeasurement_kit` and do not build the `measurement_kit` executable - `--disable-integration-tests`: only build unit tests and do not build integration tests - `--disable-traceroute`: do not build code for running traceroute scans on Android - `--with-openssl=PATH`: path where openssl (or libressl) is installed - `--with-libevent=PATH`: path where libevent is installed - `--with-geoip=PATH`: path where geoip is installed - `--prefix=PATH`: path where to install Measurement Kit On Linux, you do not need to tell configure where dependencies are installed: typically they are installed in canonical places. On macOS, in my experience you should at least tell configure where libevent is installed, i.e.: ``` ./configure --with-libevent=/usr/local ``` Note that this tells configure that headers are to be found under `/usr/local/include` and libraries under `/usr/local/lib`. Also, the configure script will check if your are using brew and search for an installed openssl even if that is not available under `/usr/local`. As regards `--prefix`, passing to configure `--prefix=/foo` means that: - binaries will be installed under `/foo/bin` - headers will be installed under `/foo/include` - libs will be installed under `/foo/lib` If you are building on Linux and you want to use libc++ rather than the GNU C++ library, make sure you install `clang`, `libc++` (including its headers, typically in a `-dev` package), `libc++abi` (including heders). Then export the following variables *before* running `./configure`: ``` export CXX=clang++ export CC=clang export CXXFLAGS="-stdlib=libc++" ``` ### make If configure succeeds, Measurement Kit is now configured to build on your system. To compile, make sure make is installed, and then run: ``` make ``` Then, you may want to run Measurement Kit tests: ``` make check ``` If all tests pass, Measurement Kit should work well on your system. ### make install As a final step, to install Measurement Kit under `/usr/local` (or under the directory passed to configure using `--prefix`), you need to become *root* and type: ``` make install ``` On Linux you may also need to update the dynamic linker with: ``` ldconfig ``` Also this command must be run as root. **Note** If you compiled dependencies using Measurement Kit own cross compile tool, `make install` will not install them. In such case you need to locate the headers and libraries under `./builtin` and copy them manually under `/usr/local/include` and `/usr/local/lib` (or, more generally, `$prefix/include` and `$prefix/lib`). Beware not to copy `*.la` files in this process, because this may prevent Measurement Kit from working correctly, as the `*.la` files compiled using our cross compile tool hardcode inside them the `./builtin` prefix, not `/usr/local` (or `$prefix`). ## Using Measurement Kit To start using Measurement Kit, you should get yourself familiar with its [nettests API](../api/nettests.md), which is the most high level API exported by the library. To this end, we suggest you to study the [examples using such API](../../example/nettests). These examples are compiled as part of running `make`, unless you have instructed configure otherwise. Anyway, each example should also include, as a comment, the correct command line to compile it. Remember that, if you have installed Measurement Kit in a non standard place with `./configure --prefix=$PREFIX`, you need to pass to the compiler also these flags: ``` -I$PREFIX/include -L$PREFIX/lib ``` measurement-kit-0.7.1/example/000077500000000000000000000000001315356162600162745ustar00rootroot00000000000000measurement-kit-0.7.1/example/common/000077500000000000000000000000001315356162600175645ustar00rootroot00000000000000measurement-kit-0.7.1/example/common/fapply.cpp000066400000000000000000000014731315356162600215700ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/common/fapply.hpp" #include static inline void fapply_example() { auto r = mk::fapply([](int x, int y, int z) { return x + y + z; }, 0, 7, 4); if (r != 11) { throw std::runtime_error("invalid result"); } } static inline void fapply_with_callback_example() { auto r = 0; mk::fapply_with_callback( [](int x, int y, int z, mk::Callback &&cb) { cb(x + y + z); }, [&r](int v) { r = v; }, 0, 7, 4); if (r != 11) { throw std::runtime_error("invalid result"); } } int main() { fapply_example(); fapply_with_callback_example(); } measurement-kit-0.7.1/example/common/fcompose.cpp000066400000000000000000000037661315356162600221170ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/common/fcompose.hpp" #include #include static inline void fcompose_sync_example() { auto f = mk::fcompose(mk::fcompose_policy_sync(), [](int x, int y, int z) { return x + y + z; }, [](int sum) { return std::make_tuple(std::string{"result"}, std::to_string(sum)); }, [](std::string &&prefix, std::string &&result) { std::cout << prefix << ": " << result << "\n"; }); f(0, 4, 7); } static inline void fcompose_async_example() { // Simulate deferred callbacks using r->call_soon(). auto r = mk::Reactor::global(); auto f = mk::fcompose( mk::fcompose_policy_async(), [r](int x, int y, int z, mk::Callback &&cb) { r->call_soon([ x = std::move(x), y = std::move(y), z = std::move(z), cb = std::move(cb) ]() { cb(x + y + z); }); }, [r](int s, mk::Callback &&cb) { r->call_soon([ s = std::move(s), cb = std::move(cb) ]() { cb("result", std::to_string(s)); }); }, [r](std::string &&p, std::string &&re, mk::Callback<> &&cb) { r->call_soon([ p = std::move(p), re = std::move(re), cb = std::move(cb) ]() { std::cout << p << ": " << re << "\n"; cb(); }); }); r->run_with_initial_event( [r, f]() mutable { f(0, 4, 7, [r]() { r->stop(); }); }); } int main() { fcompose_sync_example(); fcompose_async_example(); } measurement-kit-0.7.1/example/dns/000077500000000000000000000000001315356162600170605ustar00rootroot00000000000000measurement-kit-0.7.1/example/dns/ping.cpp000066400000000000000000000070371315356162600205300ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include "private/dns/ping.hpp" #include #include static const char *kv_usage = "usage: ./example/dns/ping [-v] [-c class] [-e engine] [-i interval]\n" " [-m max_runtime] [-N nameserver]\n" " [-r retries] [-T timeout] [-t type] domain\n"; using namespace mk; int main(int argc, char **argv) { Settings settings; settings["dns/engine"] = "libevent"; settings["dns/retries"] = 1; settings["dns/timeout"] = 1.0; std::string query_class = "IN"; std::string query_type = "A"; double interval = 1.0; Maybe max_runtime = 10.0; Var reactor = Reactor::make(); Var logger = Logger::make(); for (int ch; (ch = getopt(argc, argv, "c:e:i:m:N:r:T:t:v")) != -1;) { switch (ch) { case 'c': query_class = optarg; break; case 'e': settings["dns/engine"] = optarg; break; case 'i': interval = lexical_cast(optarg); break; case 'm': *max_runtime = lexical_cast(optarg); break; case 'N': settings["dns/nameserver"] = optarg; break; case 'r': settings["dns/retries"] = optarg; break; case 'T': settings["dns/timeout"] = optarg; break; case 't': query_type = optarg; break; case 'v': logger->increase_verbosity(); break; default: std::cout << kv_usage; exit(1); /* NOTREACHED */ } } argc -= optind, argv += optind; if (argc != 1) { std::cout << kv_usage; exit(1); /* NOTREACHED */ } std::string domain = argv[0]; reactor->run_with_initial_event([&]() { logger->info("Entering into the loop"); dns::ping_nameserver(query_class, query_type, domain, interval, max_runtime, settings, reactor, logger, [=](Error err, Var m) { std::cout << query_class << " " << query_type; if (err) { std::cout << " " << err.explain() << "\n"; return; } std::cout << " " << m->rtt; for (auto &s : m->answers) { if (query_type == "A") { std::cout << " " << s.ipv4; } else if (query_type == "AAAA") { std::cout << " " << s.ipv6; } else { std::cout << "Unexpected query type\n"; } } std::cout << "\n"; }, [=](Error error) { logger->info("Exiting from the loop: %d", error.code); reactor->stop(); }); }); } measurement-kit-0.7.1/example/dns/query.cpp000066400000000000000000000041531315356162600207340ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include #include static const char *kv_usage = "usage: measurement_kit dns_query [-N nameserver] [-v] [-c class] [-t type] domain\n"; using namespace mk; int main(int argc, char **argv) { std::string nameserver = ""; std::string query_class = "IN"; int ch; std::string query_type = "A"; while ((ch = getopt(argc, argv, "c:N:t:v")) != -1) { switch (ch) { case 'c': query_class = optarg; break; case 'N': nameserver = optarg; break; case 't': query_type = optarg; break; case 'v': increase_verbosity(); break; default: std::cout << kv_usage; exit(1); } } argc -= optind; argv += optind; if (argc != 1) { std::cout << kv_usage; exit(1); } std::string domain = argv[0]; Settings settings; if (nameserver != "") { settings["dns/nameserver"] = nameserver; } loop_with_initial_event([&query_class, &query_type, &domain, &settings]() { std::cout << query_class << " " << query_type << "\n"; dns::query(query_class.data(), query_type.data(), domain, [&query_type](Error e, Var m) { if (e) { std::cout << "Error: " << e.code << "\n"; break_loop(); return; } for (auto &s : m->answers) { if (query_type == "A") { std::cout << s.ipv4 << "\n"; } else if (query_type == "AAAA") { std::cout << s.ipv6 << "\n"; } else { std::cout << "Unexpected query type\n"; } } break_loop(); }, settings); }); return 0; } measurement-kit-0.7.1/example/http/000077500000000000000000000000001315356162600172535ustar00rootroot00000000000000measurement-kit-0.7.1/example/http/request.cpp000066400000000000000000000051531315356162600214530ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include #include using namespace mk; static const char *kv_usage = "usage: measurement_kit http_request [-v] [-B /ca/bundle/path] [-b body]\n" " [-H 'key: value'] [-m method] [-R max-redirect] url\n"; static bool set_header(http::Headers &headers, const std::string option) { auto kv = mk::split>(option, ":"); if (kv.size() != 2) { std::cout << "invalid header: " << option << "\n"; return false; } auto key = kv[0]; auto value = kv[1]; // TODO: it would be nice to have {r,l}trim() in common.hpp while (value.size() > 0 && value[0] == ' ') { value = value.substr(1); } headers[key] = value; return true; } int main(int argc, char **argv) { Settings settings; std::string body; http::Headers headers; int ch; while ((ch = getopt(argc, argv, "B:b:H:m:R:v")) != -1) { switch (ch) { case 'B': settings["net/ca_bundle_path"] = optarg; break; case 'b': body = optarg; break; case 'H': if (!set_header(headers, optarg)) { exit(1); // NOTREACHED } break; case 'm': settings["http/method"] = optarg; break; case 'R': settings["http/max_redirects"] = lexical_cast(optarg); break; case 'v': increase_verbosity(); break; default: std::cout << kv_usage; exit(1); } } argc -= optind, argv += optind; if (argc != 1) { std::cout << kv_usage; exit(1); } settings["http/url"] = argv[0]; loop_with_initial_event([&]() { http::request( settings, headers, body, [](Error error, Var response) { if (error) { std::cout << "Error: " << error.explain() << "\n"; break_loop(); return; } std::cout << response->response_line << "\n"; for (auto &pair : response->headers) { std::cout << pair.first << ": " << pair.second << "\n"; } std::cout << "\n" << response->body << "\n"; break_loop(); }); }); return 0; } measurement-kit-0.7.1/example/libevent/000077500000000000000000000000001315356162600201045ustar00rootroot00000000000000measurement-kit-0.7.1/example/libevent/discard.cpp000066400000000000000000000031351315356162600222230ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/libevent/listen.hpp" #include #include #include #include #include #include #include using namespace mk; using namespace mk::libevent; using namespace mk::net; static const char *kv_usage = "usage: ./example/libevent/discard [-v] [-p port]\n"; int main(int argc, char **argv) { int port = 54321; char ch; while ((ch = getopt(argc, argv, "p:v")) != -1) { switch (ch) { case 'p': port = lexical_cast(optarg); break; case 'v': increase_verbosity(); break; default: std::cout << kv_usage; exit(1); } } argc -= optind, argv += optind; if (argc != 0) { std::cout << kv_usage; exit(1); } const std::string addr = "127.0.0.1"; loop_with_initial_event([&addr, &port]() { listen4(addr, port, [](bufferevent *bev) { Var transport(Connection::make(bev, Reactor::global(), Logger::global())); transport->on_data([transport](Buffer) { /* nothing */ }); transport->on_error([transport](Error) { transport->on_error(nullptr); transport->on_data(nullptr); transport->close([](){}); }); }); }); } measurement-kit-0.7.1/example/libevent/listen.cpp000066400000000000000000000031541315356162600221110ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/libevent/listen.hpp" #include #include #include #include #include #include #include using namespace mk; using namespace mk::libevent; using namespace mk::net; static const char *kv_usage = "usage: ./example/libevent/listen [-v] [-p port]\n"; int main(int argc, char **argv) { int port = 54321; char ch; while ((ch = getopt(argc, argv, "p:v")) != -1) { switch (ch) { case 'p': port = lexical_cast(optarg); break; case 'v': increase_verbosity(); break; default: std::cout << kv_usage; exit(1); } } argc -= optind, argv += optind; if (argc != 0) { std::cout << kv_usage; exit(1); } const std::string addr = "127.0.0.1"; loop_with_initial_event([&addr, &port]() { listen4(addr, port, [](bufferevent *bev) { Var transport = Connection::make(bev, Reactor::global(), Logger::global()); transport->on_data([transport](Buffer data) { transport->write(data); }); transport->on_error([transport](Error) { transport->on_error(nullptr); transport->on_data(nullptr); transport->close([](){}); }); }); }); } measurement-kit-0.7.1/example/mlabns/000077500000000000000000000000001315356162600175505ustar00rootroot00000000000000measurement-kit-0.7.1/example/mlabns/query.cpp000066400000000000000000000051201315356162600214170ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include #include using namespace mk; static const char *kv_usage = "usage: measurement_kit mlabns [-46v] [-C /path/to/ca/bundle] [-m metro]\n" " [-p policy] ndt|neubot|ooni|...\n"; static void print_setting(Settings &settings, std::string key) { key = "mlabns/" + key; std::string value = settings.get(key, ""); std::cout << "> " << key << ": " << value << "\n"; } int main(int argc, char **argv) { int ch; Settings settings; while ((ch = getopt(argc, argv, "46C:m:p:v")) != -1) { switch (ch) { case '4': settings["mlabns/address_family"] = "ipv4"; break; case '6': settings["mlabns/address_family"] = "ipv6"; break; case 'C': settings["net/ca_bundle_path"] = optarg; break; case 'm': settings["mlabns/metro"] = optarg; break; case 'p': settings["mlabns/policy"] = optarg; break; case 'v': increase_verbosity(); break; default: std::cout << kv_usage; exit(1); } } argc -= optind; argv += optind; if (argc != 1) { std::cout << kv_usage; exit(1); } std::string tool = argv[0]; print_setting(settings, "address_family"); print_setting(settings, "metro"); print_setting(settings, "policy"); std::cout << "> tool: " << tool << "\n"; loop_with_initial_event([=]() { mk::mlabns::query( tool, [](Error error, mk::mlabns::Reply reply) { if (error) { std::cout << "< error: " << (int)error << "\n"; break_loop(); return; } std::cout << "< city: " << reply.city << "\n"; std::cout << "< url: " << reply.url << "\n"; std::cout << "< ip: [\n"; for (auto &s : reply.ip) { std::cout << "< " << s << "\n"; } std::cout << "< ]\n"; std::cout << "< fqdn: " << reply.fqdn << "\n"; std::cout << "< site: " << reply.site << "\n"; std::cout << "< country: " << reply.country << "\n"; break_loop(); }, settings); }); return 0; } measurement-kit-0.7.1/example/net/000077500000000000000000000000001315356162600170625ustar00rootroot00000000000000measurement-kit-0.7.1/example/net/connect.cpp000066400000000000000000000045141315356162600212230ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include #include using namespace mk::net; using namespace mk; static const char *kv_usage = "usage: ./example/net/connect [-Tv] [-p port] [-t timeout] domain\n"; int main(int argc, char **argv) { int port = 80; Settings settings; int ch; while ((ch = getopt(argc, argv, "p:Tt:v")) != -1) { switch (ch) { case 'p': port = lexical_cast(optarg); break; case 'T': settings["net/socks5_proxy"] = "127.0.0.1:9050"; break; case 't': settings["net/timeout"] = lexical_cast(optarg); break; case 'v': increase_verbosity(); break; default: std::cout << kv_usage; exit(1); } } argc -= optind, argv += optind; if (argc != 1) { std::cout << kv_usage; exit(1); } std::string domain = argv[0]; loop_with_initial_event([&domain, &port, &settings]() { connect(domain, port, [](Error err, Var txp) { std::cout << "Overall connect result: " << err.as_ooni_error() << "\n"; auto resolve_result = txp->dns_result(); std::cout << "input was valid ipv4: " << resolve_result.inet_pton_ipv4 << "\n"; std::cout << "input was valid ipv6: " << resolve_result.inet_pton_ipv6 << "\n"; std::cout << "ipv4 resolve error: " << resolve_result.ipv4_err.as_ooni_error() << "\n"; std::cout << "ipv6 resolve error: " << resolve_result.ipv6_err.as_ooni_error() << "\n"; std::cout << "list of addresses returned:\n"; for (auto addr : resolve_result.addresses) { std::cout << " - " << addr << "\n"; } std::cout << "errors returned by the various connects:\n"; for (auto e : txp->connect_errors()) { std::cout << " - " << e.as_ooni_error() << "\n"; } txp->close([]() { break_loop(); }); }, settings); }); return 0; } measurement-kit-0.7.1/example/net/transport.cpp000066400000000000000000000064271315356162600216330ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include #include #include #include #include #include #include #include using namespace mk; using namespace mk::net; static const char *kv_usage = "usage: ./example/net/transport [-Sv] [-P address:port] url\n"; static void print_line(std::string line) { std::string s; for (auto chr : line) { if (chr == '\r' || chr == '\n') { break; } s += chr; } debug("< %s", s.c_str()); } int main(int argc, char **argv) { Settings settings; char ch; while ((ch = getopt(argc, argv, "P:Sv")) != -1) { switch (ch) { case 'P': settings["net/socks5_proxy"] = optarg; break; case 'S': settings["net/ssl"] = true; break; case 'v': increase_verbosity(); break; default: std::cout << kv_usage; exit(1); } } argc -= optind; argv += optind; if (argc != 1) { std::cout << kv_usage; exit(1); } http::Url url = http::parse_url(argv[0]); loop_with_initial_event([&]() { connect(url.address, url.port, [&](Error error, Var tx) { if (error) { debug("* error: %d", (int)error); break_loop(); return; } Var incoming(new Buffer); Var reading_meta(new bool(true)); tx->set_timeout(10); tx->write("GET " + url.pathquery + " HTTP/1.0\r\n"); debug("> GET %s HTTP/1.0", url.pathquery.c_str()); tx->write("Accept: */*\r\n"); debug("> Accept: */*"); tx->write("Connection: close\r\n"); debug("> Connection: close"); tx->write("Host: " + url.address + "\r\n"); debug("> Host: %s", url.address.c_str()); tx->write("\r\n"); debug(">"); tx->on_error([=](Error error) { if (error != EofError()) { debug("* error: %d", (int)error); } else { debug("* EOF"); } tx->close([]() { break_loop(); }); }); tx->on_data([=](Buffer data) { *incoming << data; while (*reading_meta) { ErrorOr line = incoming->readline(1024); if (!line) { tx->emit_error(line.as_error()); return; } if (*line == "") { return; } print_line(*line); if (*line == "\r\n" || *line == "\n") { *reading_meta = false; break; } } debug("<+%llu-bytes", (unsigned long long)incoming->length()); }); }, settings); }); } measurement-kit-0.7.1/example/nettests/000077500000000000000000000000001315356162600201455ustar00rootroot00000000000000measurement-kit-0.7.1/example/nettests/multithread.cpp000066400000000000000000000154371315356162600232050ustar00rootroot00000000000000// Public domain 2017, Simone Basso #include // Import nlohmann::json #include // Import mk::nettests #include #include #include #include #include #include /* * Run multi-ndt test in a multi threaded app. This example uses more * features from the `mk::nettests` namespace than the simple one. * * Compile with: * * c++ -Wall -o multithread multithread.cpp -lmeasurement_kit */ int main(void) { /* * Lay out basic framwork for simulating a multi threaded app (e.g. a iOS * or Android, a macOS app using dispatch_async). * * All the lambdas in this section use `[&]` because they refer to * objects having the same life cycle of the main() function. */ std::atomic again{true}; std::mutex mutex; std::deque> queue; auto schedule = [&](std::function func) { std::unique_lock lock{mutex}; queue.push_back(std::move(func)); }; auto run = [&]() { while (again) { std::function func; { std::unique_lock lock{mutex}; if (queue.size() > 0) { func = std::move(queue.front()); queue.pop_front(); } } if (!func) { std::this_thread::sleep_for(std::chrono::milliseconds(250)); continue; } try { func(); } catch (const std::exception &exc) { fprintf(stderr, "warn: unhandled exception: %s\n", exc.what()); /* SUPPRESS */; } } }; /* * Schedule the test and report all events back to the main thread * to simulate what would happen on iOS or Android. */ schedule([&]() { mk::nettests::MultiNdtTest() // By default measurement-kit only prints warnings .set_verbosity(MK_LOG_INFO) // Do not write on disk the results of the test .set_options("no_file_report", "1") /* * Lambda called to notify about test progress. * * The lambda uses `[&]` because it only refers to objects in * main() scope. However, note how internally instead we * need to do the following: * * 1. make `message` persistent through `safe` (`message` is * a pointer inside of a temporary buffer) * * 2. copy `safe` and `percent` such that they are still alive * when the inner lambda is executed by the main thread * * 3. synchronize with the main() thread (this is done implicitly * by the `schedule()` primitive we defined) * * 4. care about exceptions (again `run()` does that) * * In general, these are the four points to keep in mind when * running in a lambda called back by measurement-kit. */ .on_progress([&](double percent, const char *message) { std::string safe = message; schedule([percent, safe]() { printf("[%.1f%%] - %s\n", percent * 100.0, safe.c_str()); }); }) // Lambda called when events occur. Here we process only download // speed updates emitted during the multi-ndt test. // // In case `nlohmann::json::parse()` throws an exception, no // worries because MK suppress exceptions in the on_event lambda. // // See the above four points to keep in mind. .on_event([&](const char *s) { nlohmann::json doc = nlohmann::json::parse(s); if (doc["type"] != "download-speed") { return; } schedule([doc]() { double elapsed = doc["elapsed"][0]; std::string elapsed_unit = doc["elapsed"][1]; double speed = doc["speed"][0]; std::string speed_unit = doc["speed"][1]; printf("%8.2f %s %10.2f %s\n", elapsed, elapsed_unit.c_str(), speed, speed_unit.c_str()); }); }) // Lambda called at the end of the test with final results. Here // we parse it to print a summary on stdout. // // See the above four points to keep in mind. .on_entry([&](std::string s) { schedule([s]() { nlohmann::json doc = nlohmann::json::parse(s); auto simple = doc["test_keys"]["simple"]; printf("\nTest summary\n"); printf("------------\n"); std::string fastest = simple["fastest_test"]; double download = simple["download"]; double ping = simple["ping"]; printf("Fastest test: %s\n", fastest.c_str()); printf("Download speed: %.2f kbit/s\n", download); printf("Ping: %.2f ms\n", ping); printf("\n"); }); }) // Lambda called to process log messages. The level is a bitmask // defined in the header. // // See the above four points to keep in mind. .on_log([&](int level, const char *message) { std::string safe = message; schedule([level, safe]() { fprintf(stderr, "<%d> %s\n", level, safe.c_str()); }); }) // Tell MK where to find files useful to identify the country code // and the ISP autonomous system number. You should probably have // them installed under /usr/local/ in a reall program. .set_options("geoip_country_path", "GeoIP.dat") .set_options("geoip_asn_path", "GeoIPASNum.dat") // Will become the default in MK v0.5.0. Better to use this flag // to avoid the need to discover the DNS server on mobile. .set_options("dns/engine", "system") /* * This instruction starts the test in a background thread * and calls the callback passed as argument when done. * * See the above four points to keep in mind. */ .start([&]() { again = false; /* Note: `again` is atomic */ }); }); /* * Finally, start the main thread. */ run(); return 0; } measurement-kit-0.7.1/example/nettests/simple.cpp000066400000000000000000000065051315356162600221500ustar00rootroot00000000000000// Public domain 2017, Simone Basso #include // Import nlohmann::json #include // Import mk::nettests #include /* * Run multi-ndt test in a single threaded app. * * Compile with: * * c++ -Wall -o simple simple.cpp -lmeasurement_kit */ int main(void) { mk::nettests::MultiNdtTest() // By default measurement-kit only prints warnings .set_verbosity(MK_LOG_INFO) // Lambda called to notify us about how the test is making progress .on_progress([](double percent, const char *message) { printf("[%.1f%%] - %s\n", percent * 100.0, message); }) // Lambda called when events occur. Here we process only download // speed updates emitted during the multi-ndt test. // // Note: in general `nlohmann::json` throws on error but MK // guarantees that on_event() is robust to exceptions. .on_event([](const char *s) { nlohmann::json doc = nlohmann::json::parse(s); if (doc["type"] != "download-speed") { return; } double elapsed = doc["elapsed"][0]; std::string elapsed_unit = doc["elapsed"][1]; double speed = doc["speed"][0]; std::string speed_unit = doc["speed"][1]; printf("%8.2f %s %10.2f %s\n", elapsed, elapsed_unit.c_str(), speed, speed_unit.c_str()); }) // Lambda called at the end of the test with final results. Here // we parse it to print a summary on stdout. // // Also in this case we don't care about exceptions because // MK suppresses exceptions occurring in this lambda. .on_entry([](std::string s) { nlohmann::json doc = nlohmann::json::parse(s); auto simple = doc["test_keys"]["simple"]; printf("\nTest summary\n"); printf("------------\n"); std::string fastest = simple["fastest_test"]; double download = simple["download"]; double ping = simple["ping"]; printf("Fastest test: %s\n", fastest.c_str()); printf("Download speed: %.2f kbit/s\n", download); printf("Ping: %.2f ms\n", ping); printf("\n"); }) // Lambda called to process log messages. The level is a bitmask // defined in the header. .on_log([](int level, const char *message) { fprintf(stderr, "<%d> %s\n", level, message); }) // Tell MK where to find files useful to identify the country code // and the ISP autonomous system number. You should probably have // them installed under /usr/local/ in a reall program. .set_options("geoip_country_path", "GeoIP.dat") .set_options("geoip_asn_path", "GeoIPASNum.dat") // Will become the default in MK v0.5.0. Better to use this flag // to avoid the need to discover the DNS server on mobile. .set_options("dns/engine", "system") // This instruction actually runs the test configured by all // the code lines above. This style of running a test is such // that the test runs in the current thread. .run(); return 0; } measurement-kit-0.7.1/example/ooni/000077500000000000000000000000001315356162600172405ustar00rootroot00000000000000measurement-kit-0.7.1/example/ooni/oonireport.cpp000066400000000000000000000026031315356162600221450ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include #include #define USAGE "oonireport [-v] [-c collector-base-url] filepath [...]" using namespace mk::ooni; using namespace mk; static void upload_report(std::string url, int index, char **argv) { if (argv[index] == nullptr) { break_loop(); return; } info("submitting report %s...", argv[index]); collector::submit_report(argv[index], url, [=](Error err) { info("submitting report %s... %d", argv[index], err.code); call_soon([=]() { debug("scheduling submit of next report..."); upload_report(url, index + 1, argv); }); }); } int main(int argc, char **argv) { std::string url = collector::production_collector_url(); int ch; while ((ch = getopt(argc, argv, "c:v")) != -1) { switch (ch) { case 'c': url = optarg; break; case 'v': increase_verbosity(); break; default: std::cout << USAGE << "\n"; exit(1); } } argc -= optind; argv += optind; loop_with_initial_event([&]() { upload_report(url, 0, argv); }); return 0; } measurement-kit-0.7.1/example/ooni/ooniresources.cpp000066400000000000000000000031321315356162600226420ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include #include #define USAGE "ooniresources [-v] [-d dir]" using namespace mk::ooni; using namespace mk; int main(int argc, char **argv) { Settings settings; for (int ch; (ch = getopt(argc, argv, "d:v")) != -1; ) { switch (ch) { case 'd': settings["ooni/resources_destdir"] = std::string{optarg}; break; case 'v': increase_verbosity(); break; default: fprintf(stderr, "%s\n", USAGE); exit(1); // NOTREACHED } } argc -= optind, argv += optind; loop_with_initial_event([=]() { mk::ooni::resources::get_latest_release( [=](Error error, std::string latest) { if (error) { fprintf(stderr, "error: %s\n", error.explain().c_str()); break_loop(); return; } mk::ooni::resources::get_resources( latest, "ALL", [=](Error error) { if (error) { fprintf(stderr, "error: %s\n", error.explain().c_str()); /* FALLTHROUGH */ } break_loop(); }, settings); }, settings); }); return 0; } measurement-kit-0.7.1/example/ooni/oorchestrate.cpp000066400000000000000000000064401315356162600224520ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/common/fcompose.hpp" #include #include #include using namespace mk::ooni::orchestrate; using namespace mk::ooni; using namespace mk; #define USAGE "oorchestrate [-v]" int main(int argc, char **argv) { Client client; for (int ch; (ch = getopt(argc, argv, "v")) != -1;) { switch (ch) { case 'v': client.logger->increase_verbosity(); break; default: std::cout << USAGE << "\n"; exit(1); } } argc -= optind, argv += optind; if (argc > 0) { std::cout << USAGE << "\n"; exit(1); } const std::string path = "orchestrator_secrets.json"; client.geoip_country_path = "GeoIP.dat"; client.geoip_asn_path = "GeoIPASNum.dat"; client.network_type = "wifi"; // client.device_token = "{TOKEN}"; /* Not needed on PC devices */ client.registry_url = testing_registry_url(); std::promise promise; std::future future = promise.get_future(); Auth auth; Error err = auth.load(path); auto func = mk::fcompose( mk::fcompose_policy_async(), [&err, &client, &path](Auth &&auth, Callback &&cb) { if (!err) { // If we have loaded the authentication, proceed cb(NoError(), std::move(auth)); return; } client.register_probe("", [&path, cb = std::move(cb) ]( Error && error, Auth && auth) { if (error) { cb(std::move(error), {}); return; } if ((error = auth.dump(path)) != NoError()) { cb(std::move(error), {}); return; } cb(NoError(), std::move(auth)); }); }, [&client](Error &&error, Auth &&auth, Callback &&cb) { if (error) { cb(std::move(error), {}); return; } client.network_type = "3g"; // Simulate network change client.update(std::move(auth), std::move(cb)); }, [&client, &path](Error &&error, Auth &&auth, Callback &&cb) { // Second update to check whether the auth token is working if (error) { cb(std::move(error), std::move(auth)); return; } // Dump after update() so we have also the token stored on disk if ((error = auth.dump(path)) != NoError()) { cb(std::move(error), {}); return; } client.network_type = "wifi"; // Simulate network change client.update(std::move(auth), std::move(cb)); }); func(std::move(auth), [&promise](Error &&error, Auth &&) { promise.set_value(error); }); return (future.get()) ? 1 : 0; } measurement-kit-0.7.1/include/000077500000000000000000000000001315356162600162645ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/000077500000000000000000000000001315356162600214605ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/common/000077500000000000000000000000001315356162600227505ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/common/aaa_base.hpp000066400000000000000000000016241315356162600252000ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_AAA_BASE_HPP #define MEASUREMENT_KIT_COMMON_AAA_BASE_HPP // Portability definition and headers #include #include #include #include #include #include #include #include // Note: standard headers with non-standard additions #include #include // Include ciso646 to make sure we have `and`, `or`, etc #include #endif measurement-kit-0.7.1/include/measurement_kit/common/callback.hpp000066400000000000000000000006151315356162600252170ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_CALLBACK_HPP #define MEASUREMENT_KIT_COMMON_CALLBACK_HPP #include namespace mk { template using Callback = std::function; } // namespace #endif measurement-kit-0.7.1/include/measurement_kit/common/continuation.hpp000066400000000000000000000006771315356162600262050ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_CONTINUATION_HPP #define MEASUREMENT_KIT_COMMON_CONTINUATION_HPP #include namespace mk { template using Continuation = std::function)>; } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/delegate.hpp000066400000000000000000000026211315356162600252340ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_DELEGATE_HPP #define MEASUREMENT_KIT_COMMON_DELEGATE_HPP #include #include namespace mk { // Implementation note: this class could also have been written as a subclass // of function but I, er, was not able to write it like so because I do not // know enough about templates syntax, plus it's not totally clear to me what // would be the proper way to wrap `swap` and `assign`. template class Delegate_ { public: Delegate_() {} template Delegate_(F f) : func(f) {} Delegate_(std::function f) : func(f) {} ~Delegate_() {} void operator=(std::function f) { func = f; } template void operator=(F f) { func = f; } void operator=(std::nullptr_t f) { func = f; } // not implementing swap and assign operator bool() { return static_cast(func); } template void operator()(Args &&... args) { // Make sure the original closure is not destroyed before end of scope auto orig = this->func; orig(std::forward(args)...); } private: std::function func; }; template using Delegate = Delegate_; } // namespace #endif measurement-kit-0.7.1/include/measurement_kit/common/error.hpp000066400000000000000000000073261315356162600246220ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_ERROR_HPP #define MEASUREMENT_KIT_COMMON_ERROR_HPP #include #include #include namespace mk { class Error : public std::exception { public: Error() : Error(0, "", nullptr) {} Error(int e) : Error(e, "", nullptr) {} Error(int e, std::string ooe) : Error(e, ooe, nullptr) {} Error(int e, std::string ooe, Var c) : code(e), reason(ooe) { if (code != 0 && reason == "") { reason = "unknown_failure " + std::to_string(code); } if (c) { child_errors.push_back(c); } } Error(int e, std::string ooe, Error c) : Error(e, ooe, Var(new Error(c))) {} operator bool() const { return code != 0; } bool operator==(int n) const { return code == n; } bool operator==(Error e) const { return code == e.code; } bool operator!=(int n) const { return code != n; } bool operator!=(Error e) const { return code != e.code; } std::string as_ooni_error() { return reason; } const char *what() const noexcept override { return reason.c_str(); } void add_child_error(const Error &err) { Var container(new Error(err)); child_errors.push_back(container); } std::string explain() const { std::string s; s += "{"; s += reason; s += "}"; if (child_errors.size() > 0) { s += " ["; for (auto &e : child_errors) { s += e->explain(); } s += "]"; } return s; } std::vector> child_errors; int code = 0; std::string reason; }; #define MK_DEFINE_ERR(_code_, _name_, _ooe_) \ class _name_ : public Error { \ public: \ _name_() : Error(_code_, _ooe_) {} \ _name_(std::string s) : Error(_code_, _ooe_) { \ reason += ": "; \ reason += s; \ } \ _name_(Error e) : Error(_code_, _ooe_, e) {} \ }; MK_DEFINE_ERR(0, NoError, "") MK_DEFINE_ERR(1, GenericError, "generic_error") MK_DEFINE_ERR(2, NotInitializedError, "not_initialized") MK_DEFINE_ERR(3, ValueError, "value_error") MK_DEFINE_ERR(4, MockedError, "mocked_error") MK_DEFINE_ERR(5, JsonParseError, "json_parse_error") MK_DEFINE_ERR(6, JsonKeyError, "json_key_error") MK_DEFINE_ERR(7, JsonDomainError, "json_domain_error") MK_DEFINE_ERR(8, FileEofError, "file_eof_error") MK_DEFINE_ERR(9, FileIoError, "file_io_error") MK_DEFINE_ERR(10, ParallelOperationError, "parallel_operation_error") MK_DEFINE_ERR(11, SequentialOperationError, "sequential_operation_error") MK_DEFINE_ERR(12, IllegalSequenceError, "illegal_sequence") MK_DEFINE_ERR(13, UnexpectedNullByteError, "unexpected_null_byte") MK_DEFINE_ERR(14, IncompleteUtf8SequenceError, "incomplete_utf8_sequence") MK_DEFINE_ERR(15, NotImplementedError, "not_implemented") #define MK_ERR_NET(x) (1000 + x) #define MK_ERR_DNS(x) (2000 + x) #define MK_ERR_HTTP(x) (3000 + x) #define MK_ERR_TRACEROUTE(x) (4000 + x) #define MK_ERR_MLABNS(x) (5000 + x) #define MK_ERR_OONI(x) (6000 + x) #define MK_ERR_REPORT(x) (7000 + x) #define MK_ERR_NDT(x) (8000 + x) } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/error_or.hpp000066400000000000000000000032401315356162600253110ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_ERROR_OR_HPP #define MEASUREMENT_KIT_COMMON_ERROR_OR_HPP #include namespace mk { template class ErrorOr { public: ErrorOr() : error_(NotInitializedError()) {} ErrorOr(T value) : value_(value) {} ErrorOr(Error error) : error_(error) {} ErrorOr(Error error, T value) : error_(error), value_(value) {} operator bool() const { return error_ == NoError(); } #define XX \ if (error_ != 0) { \ throw error_; \ } \ return value_; const T &as_value() const { XX } T &as_value() { XX } #undef XX Error as_error() const { return error_; } const T &operator*() const { return as_value(); } T &operator*() { return as_value(); } #define XX \ if (error_ != 0) { \ throw error_; \ } \ return &value_; const T *operator->() const { XX } T *operator->() { XX } #undef XX private: Error error_; T value_; }; } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/has_global_factory.hpp000066400000000000000000000014021315356162600273000ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_HAS_GLOBAL_FACTORY_HPP #define MEASUREMENT_KIT_COMMON_HAS_GLOBAL_FACTORY_HPP #include #include namespace mk { template class HasGlobalFactory { public: template static Var global(A &&... a) { return locked_global([&]() { static Var singleton; if (!singleton) { singleton = Var::make(std::forward(a)...); } return singleton; }); } }; } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/lexical_cast.hpp000066400000000000000000000015761315356162600261250ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_LEXICAL_CAST_HPP #define MEASUREMENT_KIT_COMMON_LEXICAL_CAST_HPP #include #include namespace mk { template To lexical_cast(From f) { std::stringstream ss; To value; ss << f; ss >> value; if (!ss.eof()) { throw ValueError(); // Not all input was converted } if (ss.fail()) { throw ValueError(); // Input format was wrong } return value; } template ErrorOr lexical_cast_noexcept(From f) { try { return lexical_cast(f); } catch (Error err) { return err; } } } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/locked.hpp000066400000000000000000000011221315356162600247160ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_LOCKED_HPP #define MEASUREMENT_KIT_COMMON_LOCKED_HPP #include namespace mk { template auto locked(std::mutex &mutex, Func &&func) { std::lock_guard guard{mutex}; return func(); } template auto locked_global(Func &&func) { static std::mutex mutex; return locked(mutex, std::move(func)); } } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/logger.hpp000066400000000000000000000064761315356162600247550ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_LOGGER_HPP #define MEASUREMENT_KIT_COMMON_LOGGER_HPP #include #include #include #include #include #include #include #include #include #include // The numbers [0-31] are reserved for verbosity levels. #define MK_LOG_WARNING 0 #define MK_LOG_INFO 1 #define MK_LOG_DEBUG 2 #define MK_LOG_DEBUG2 3 #define MK_LOG_VERBOSITY_MASK 31 // The number above 31 have different semantics: #define MK_LOG_EVENT 32 // Information encoded as JSON namespace mk { class Logger : public NonCopyable, public NonMovable { public: // TODO: refactor class to move all implementation in .cpp files static Var make(); void logv(uint32_t, const char *, va_list) __attribute__((format(printf, 3, 0))); void log(uint32_t, const char *, ...) __attribute__((format(printf, 3, 4))); void warn(const char *fmt, ...) __attribute__((format(printf, 2, 3))); void info(const char *fmt, ...) __attribute__((format(printf, 2, 3))); void debug(const char *fmt, ...) __attribute__((format(printf, 2, 3))); void set_verbosity(uint32_t v) { verbosity_ = (v & MK_LOG_VERBOSITY_MASK); } void increase_verbosity(); uint32_t get_verbosity() { return verbosity_; } void on_log(Delegate fn) { consumer_ = fn; } void on_eof(Delegate<> fn); void on_event(Delegate fn); void on_progress(Delegate fn); void set_logfile(std::string fpath); void progress(double, const char *); void progress_relative(double, const char *); void set_progress_offset(double offset); void set_progress_scale(double scale); static Var global() { static Var singleton(new Logger); return singleton; } ~Logger(); private: Delegate consumer_; uint32_t verbosity_ = MK_LOG_WARNING; char buffer_[32768]; std::mutex mutex_; Var ofile_; std::list> eof_handlers_; Delegate event_handler_; Delegate progress_handler_; double progress_offset_ = 0.0; double progress_scale_ = 1.0; double progress_relative_ = 0.0; Logger(); }; void log(uint32_t, const char *, ...) __attribute__((format(printf, 2, 3))); void warn(const char *, ...) __attribute__((format(printf, 1, 2))); void debug(const char *, ...) __attribute__((format(printf, 1, 2))); void info(const char *, ...) __attribute__((format(printf, 1, 2))); inline void set_verbosity(uint32_t v) { Logger::global()->set_verbosity(v); } inline void increase_verbosity() { Logger::global()->increase_verbosity(); } inline uint32_t get_verbosity() { return Logger::global()->get_verbosity(); } inline void on_log(Delegate fn) { Logger::global()->on_log(fn); } inline void set_logfile(std::string path) { Logger::global()->set_logfile(path); } } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/maybe.hpp000066400000000000000000000017461315356162600245660ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_MAYBE_HPP #define MEASUREMENT_KIT_COMMON_MAYBE_HPP #include #include namespace mk { template class Maybe { public: Maybe() {} Maybe(T &&t) : value_{std::move(t)}, valid_{true} {} #define IMPL \ if (!valid_) { \ throw std::runtime_error("Maybe is empty"); \ } \ return value_ T &operator*() { IMPL; } const T &operator*() const { IMPL; } #undef IMPL operator bool() const { return valid_; } private: T value_ = {}; bool valid_ = false; }; } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/non_copyable.hpp000066400000000000000000000010701315356162600261270ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_NON_COPYABLE_HPP #define MEASUREMENT_KIT_COMMON_NON_COPYABLE_HPP namespace mk { class NonCopyable { public: NonCopyable(const NonCopyable &) = delete; NonCopyable &operator=(const NonCopyable &) = delete; NonCopyable(NonCopyable &) = delete; NonCopyable &operator=(NonCopyable &) = delete; NonCopyable() {} }; } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/non_movable.hpp000066400000000000000000000007111315356162600257570ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_NON_MOVABLE_HPP #define MEASUREMENT_KIT_COMMON_NON_MOVABLE_HPP namespace mk { class NonMovable { public: NonMovable(NonMovable &&) = delete; NonMovable &operator=(NonMovable &&) = delete; NonMovable() {} }; } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/platform.h000066400000000000000000000006051315356162600247460ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_PLATFORM_HPP #define MEASUREMENT_KIT_COMMON_PLATFORM_HPP #ifdef __cplusplus extern "C" { #endif const char *mk_platform(void); #ifdef __cplusplus } // namespace mk #endif #endif measurement-kit-0.7.1/include/measurement_kit/common/reactor.hpp000066400000000000000000000047101315356162600251220ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_REACTOR_HPP #define MEASUREMENT_KIT_COMMON_REACTOR_HPP #include #include #include #include // Deprecated since v0.4.x struct event_base; #define MK_POLLIN 1 << 0 #define MK_POLLOUT 1 << 1 namespace mk { class Reactor { public: static Var make(); static Var global(); virtual ~Reactor(); virtual void call_soon(Callback<> &&cb) = 0; virtual void call_later(double, Callback<> &&cb) = 0; // Backward compatibility names void loop_with_initial_event(Callback<> &&cb) { run_with_initial_event(std::move(cb)); } void loop() { run(); } void break_loop() { stop(); } /* POSIX API for dealing with sockets. Slower than APIs in net, especially under Windows, but suitable to integrate with other async libraries such as c-ares and perhaps others. */ virtual void pollfd( socket_t sockfd, short events, double timeout, Callback &&callback ) = 0; // Backward compatibility API void pollfd(socket_t sockfd, short events, Callback &&cb, double timeout = -1.0) { pollfd(sockfd, events, timeout, std::move(cb)); } // Deprecated since v0.4.x virtual event_base *get_event_base() = 0; void run_with_initial_event(Callback<> &&cb); virtual void run() = 0; virtual void stop() = 0; }; void call_soon(Callback<> &&, Var = Reactor::global()); void call_later(double, Callback<> &&, Var = Reactor::global()); void loop_with_initial_event(Callback<> &&, Var = Reactor::global()); void loop(Var = Reactor::global()); void break_loop(Var = Reactor::global()); // Introduced as aliases in v0.4.x inline void run_with_initial_event(Callback<> &&callback, Var reactor = Reactor::global()) { loop_with_initial_event(std::move(callback), reactor); } inline void run(Var reactor = Reactor::global()) { loop(reactor); } inline void stop(Var reactor = Reactor::global()) { break_loop(reactor); } } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/settings.hpp000066400000000000000000000024431315356162600253240ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_SETTINGS_HPP #define MEASUREMENT_KIT_COMMON_SETTINGS_HPP #include #include namespace mk { class Settings : public std::map { public: using std::map::map; #define XX(_rv_, _methname_, _accessor_) \ template \ _rv_ _methname_(std::string key, Type def_value) const { \ if (find(key) == end()) { \ return def_value; \ } \ return at(key)._accessor_(); \ } XX(Type, get, as) XX(ErrorOr, get_noexcept, as_noexcept) #undef XX protected: private: // NO ATTRIBUTES HERE BY DESIGN. DO NOT ADD ATTRIBUTES HERE BECAUSE // DOING THAT CREATES THE RISK OF OBJECT SLICING. }; } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/settings_entry.hpp000066400000000000000000000033441315356162600265460ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_SETTINGS_ENTRY_HPP #define MEASUREMENT_KIT_COMMON_SETTINGS_ENTRY_HPP #include #include namespace mk { /// This class is a specialization of the ordinary string that can also /// store integral and boolean types. Once you have stored a value inside /// of this class, you can access its string representation easily since /// this class can be assigned to a string. If that fails, use the `str()` /// method that explicitly converts to a string. To convert to integral /// types, instead, use the `as()` template method. class SettingsEntry : public std::string { public: SettingsEntry() {} template SettingsEntry(Type value) { std::stringstream ss; ss << value; assign(ss.str()); } template Type as() const { std::stringstream ss(c_str()); Type value; ss >> value; if (!ss.eof()) { throw ValueError(); // Not all input was converted } if (ss.fail()) { throw ValueError(); // Input format was wrong } return value; } template ErrorOr as_noexcept() const { try { return as(); } catch (Error &e) { return e; } } std::string str() const { return as(); } protected: private: // NO ATTRIBUTES HERE BY DESIGN. DO NOT ADD ATTRIBUTES HERE BECAUSE // DOING THAT CREATES THE RISK OF OBJECT SLICING. }; } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/socket.hpp000066400000000000000000000006551315356162600247570ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_SOCKET_HPP #define MEASUREMENT_KIT_COMMON_SOCKET_HPP #include namespace mk { #ifdef _WIN32 using socket_t = uintptr_t; #else using socket_t = int; #endif } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/utils.hpp000066400000000000000000000024421315356162600246230ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_UTILS_HPP #define MEASUREMENT_KIT_COMMON_UTILS_HPP #include #include #include #include namespace mk { void timeval_now(timeval *); double time_now(); void utc_time_now(tm *); ErrorOr timestamp(const tm *); timeval *timeval_init(timeval *, double); Error parse_iso8601_utc(std::string ts, std::tm *tmb); template > T split(std::string s, std::string pattern = "\\s+") { // See // passing -1 as the submatch index parameter performs splitting std::regex re{pattern}; std::sregex_token_iterator first{s.begin(), s.end(), re, -1}, last; return {first, last}; } std::string sha256_of(std::string input); ErrorOr> slurpv(std::string path); ErrorOr slurp(std::string path); Error overwrite_file(std::string path, std::string content); bool startswith(std::string s, std::string p); bool endswith(std::string s, std::string p); } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/var.hpp000066400000000000000000000035451315356162600242600ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_VAR_HPP #define MEASUREMENT_KIT_COMMON_VAR_HPP #include #include namespace mk { template class Var { public: template Var(typename std::add_pointer::type p, Deleter &&deleter) : ptr_{std::shared_ptr{p, deleter}} {} Var(typename std::add_pointer::type p) : ptr_{std::shared_ptr{p}} {} Var(std::shared_ptr &&ptr) : ptr_{ptr} {} Var() {} long use_count() const noexcept { return ptr_.use_count(); } operator bool() const { return static_cast(ptr_); } void reset(typename std::add_pointer::type p = nullptr) { ptr_.reset(p); } bool operator==(std::nullptr_t x) const noexcept { return ptr_ == x; } template void reset(typename std::add_pointer::type p, Deleter &&deleter) { ptr_.reset(p, deleter); } typename std::add_pointer::type get() const { return operator->(); } typename std::add_pointer::type operator->() const { if (ptr_.get() == nullptr) { throw std::runtime_error("null pointer"); } return ptr_.operator->(); } typename std::add_lvalue_reference::type operator*() const { if (ptr_.get() == nullptr) { throw std::runtime_error("null pointer"); } return ptr_.operator*(); } template Var as() const { return std::dynamic_pointer_cast(ptr_); } template static Var make(A &&... a) { return std::make_shared(std::forward(a)...); } private: std::shared_ptr ptr_; }; } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/common/version.h000066400000000000000000000014101315356162600246020ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_COMMON_VERSION_HPP #define MEASUREMENT_KIT_COMMON_VERSION_HPP // File generated by `./autogen.sh` containing the exact version #include // Note: we use semantic versioning (see: http://semver.org/) #define MK_VERSION "0.7.1" #define MEASUREMENT_KIT_VERSION MK_VERSION /* Backward compatibility */ #ifdef __cplusplus extern "C" { #endif const char *mk_version(void); const char *mk_version_full(void); const char *mk_openssl_version(void); const char *mk_libevent_version(void); #ifdef __cplusplus } // namespace mk #endif #endif measurement-kit-0.7.1/include/measurement_kit/dns/000077500000000000000000000000001315356162600222445ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/dns/error.hpp000066400000000000000000000052241315356162600241110ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_DNS_ERROR_HPP #define MEASUREMENT_KIT_DNS_ERROR_HPP #include namespace mk { namespace dns { MK_DEFINE_ERR(MK_ERR_DNS(0), FormatError, "dns_lookup_error") MK_DEFINE_ERR(MK_ERR_DNS(1), ServerFailedError, "dns_lookup_error") MK_DEFINE_ERR(MK_ERR_DNS(2), NotExistError, "dns_lookup_error") MK_DEFINE_ERR(MK_ERR_DNS(3), NotImplementedError, "dns_lookup_error") MK_DEFINE_ERR(MK_ERR_DNS(4), RefusedError, "dns_lookup_error") MK_DEFINE_ERR(MK_ERR_DNS(5), TruncatedError, "dns_lookup_error") MK_DEFINE_ERR(MK_ERR_DNS(6), UnknownError, "dns_unknown_error") MK_DEFINE_ERR(MK_ERR_DNS(7), TimeoutError, "generic_timeout_error") MK_DEFINE_ERR(MK_ERR_DNS(8), ShutdownError, "dns_shutdown") MK_DEFINE_ERR(MK_ERR_DNS(9), CancelError, "dns_cancel") MK_DEFINE_ERR(MK_ERR_DNS(10), NoDataError, "dns_lookup_error") MK_DEFINE_ERR(MK_ERR_DNS(11), InvalidIPv4AddressError, "dns_invalid_ipv4") MK_DEFINE_ERR(MK_ERR_DNS(12), InvalidIPv6AddressError, "dns_invalid_ipv6") MK_DEFINE_ERR(MK_ERR_DNS(13), UnsupportedClassError, "dns_unsupported_class") MK_DEFINE_ERR(MK_ERR_DNS(14), InvalidNameForPTRError, "dns_invalid_ptr") MK_DEFINE_ERR(MK_ERR_DNS(15), ResolverError, "dns_resolver_error") MK_DEFINE_ERR(MK_ERR_DNS(16), UnsupportedTypeError, "dns_unsupported_type") MK_DEFINE_ERR(MK_ERR_DNS(17), InvalidDnsEngine, "dns_invalid_engine") // getaddrinfo errors MK_DEFINE_ERR(MK_ERR_DNS(18), TemporaryFailureError, "dns_temporary_failure") MK_DEFINE_ERR(MK_ERR_DNS(19), InvalidFlagsValueError, "dns_invalid_flags") MK_DEFINE_ERR(MK_ERR_DNS(20), InvalidHintsValueError, "dns_invalid_hints") MK_DEFINE_ERR(MK_ERR_DNS(21), NonRecoverableFailureError, "dns_non_recoverable_failure") MK_DEFINE_ERR(MK_ERR_DNS(22), NotSupportedAIFamilyError, "dns_unsupported_family") MK_DEFINE_ERR(MK_ERR_DNS(23), MemoryAllocationFailureError, "dns_memory_error") MK_DEFINE_ERR(MK_ERR_DNS(24), HostOrServiceNotProvidedOrNotKnownError, "dns_host_or_service_not_provided_or_not_known") MK_DEFINE_ERR(MK_ERR_DNS(25), ArgumentBufferOverflowError, "dns_overflow_error") MK_DEFINE_ERR(MK_ERR_DNS(26), UnknownResolvedProtocolError, "dns_unknown_protocol") MK_DEFINE_ERR(MK_ERR_DNS(27), NotSupportedServnameError, "dns_unsupported_servname") MK_DEFINE_ERR(MK_ERR_DNS(28), NotSupportedAISocktypeError, "dns_unsupported_socktype") MK_DEFINE_ERR(MK_ERR_DNS(29), InetNtopFailureError, "dns_inet_ntop_failure") } // namespace dns } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/dns/qctht_.hpp000066400000000000000000000020661315356162600242430ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_DNS_QCTHT__HPP #define MEASUREMENT_KIT_DNS_QCTHT__HPP // QCTHT = query class and type helper template #include #include namespace mk { namespace dns { template class qctht_ { public: qctht_() noexcept {} qctht_(Type v) noexcept : id_{v} {} template qctht_(Stringish v) { *this = v; } qctht_ &operator=(Type v) noexcept { id_ = v; return *this; } template qctht_ &operator=(Stringish v) { id_ = (*Mapping)(v); return *this; } bool operator==(Type id) const noexcept { return id_ == id; } bool operator!=(Type id) const noexcept { return id_ != id; } operator Type() const noexcept { return id_; } private: Type id_ = (*Mapping)(""); }; } // namespace dns } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/dns/query.hpp000066400000000000000000000032661315356162600241310ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_DNS_QUERY_HPP #define MEASUREMENT_KIT_DNS_QUERY_HPP #include #include #include namespace mk { namespace dns { class Answer { public: QueryType type; QueryClass qclass; int code = 0; uint32_t ttl = 0; std::string name; std::string ipv4; ///< For A records std::string ipv6; ///< For AAAA records std::string hostname; ///< For PTR, SOA and CNAME records std::string responsible_name; ///< For SOA records uint32_t serial_number; ///< For SOA records uint32_t refresh_interval; ///< For SOA records uint32_t retry_interval; ///< For SOA records uint32_t minimum_ttl; ///< For SOA records uint32_t expiration_limit; ///< For SOA records }; class Query { public: QueryType type; QueryClass qclass; uint32_t ttl = 0; std::string name; }; class Message { public: Message(){}; Message(std::nullptr_t){}; double rtt = 0.0; int error_code = 66 /* This is evdns's generic error */; std::vector answers; std::vector queries; }; void query( QueryClass dns_class, QueryType dns_type, std::string name, Callback> func, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global() ); } // namespace dns } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/dns/query_class.hpp000066400000000000000000000017501315356162600253120ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_DNS_QUERY_CLASS_HPP #define MEASUREMENT_KIT_DNS_QUERY_CLASS_HPP #include namespace mk { namespace dns { #define MK_DNS_CLASS_IDS \ XX(INVALID) /* Must be first */ \ XX(IN) \ XX(CS) \ XX(CH) \ XX(HS) #define XX(_name) MK_DNS_CLASS_##_name, enum QueryClassId { MK_DNS_CLASS_IDS }; #undef XX QueryClassId query_class_ids_(std::string s); using QueryClass = qctht_; } // namespace dns } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/dns/query_type.hpp000066400000000000000000000042711315356162600251670ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_DNS_QUERY_TYPE_HPP #define MEASUREMENT_KIT_DNS_QUERY_TYPE_HPP #include namespace mk { namespace dns { #define MK_DNS_TYPE_IDS \ XX(INVALID) /* Must be first */ \ XX(A) \ XX(NS) \ XX(MD) \ XX(MF) \ XX(CNAME) \ XX(SOA) \ XX(MB) \ XX(MG) \ XX(MR) \ XX(NUL) \ XX(WKS) \ XX(PTR) \ XX(HINFO) \ XX(MINFO) \ XX(MX) \ XX(TXT) \ XX(AAAA) \ XX(REVERSE_A /* nonstandard */) \ XX(REVERSE_AAAA /* nonstandard */) #define XX(_name) MK_DNS_TYPE_##_name, enum QueryTypeId { MK_DNS_TYPE_IDS }; #undef XX QueryTypeId query_type_ids_(std::string s); using QueryType = qctht_; } // namespace dns } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/dns/resolve_hostname.hpp000066400000000000000000000015341315356162600263350ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_DNS_RESOLVE_HOSTNAME_HPP #define MEASUREMENT_KIT_DNS_RESOLVE_HOSTNAME_HPP #include namespace mk { namespace dns { class ResolveHostnameResult { public: bool inet_pton_ipv4 = false; bool inet_pton_ipv6 = false; Error ipv4_err; dns::Message ipv4_reply; Error ipv6_err; dns::Message ipv6_reply; std::vector addresses; }; void resolve_hostname(std::string hostname, Callback cb, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); } // namespace dns } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/ext/000077500000000000000000000000001315356162600222605ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/ext/json.hpp000066400000000000000000015526661315356162600237670ustar00rootroot00000000000000/* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ | | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . Copyright (c) 2013-2017 Niels Lohmann . 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. */ #ifndef NLOHMANN_JSON_HPP #define NLOHMANN_JSON_HPP #include // all_of, copy, fill, find, for_each, none_of, remove, reverse, transform #include // array #include // assert #include // isdigit #include // and, not, or #include // isfinite, labs, ldexp, signbit #include // nullptr_t, ptrdiff_t, size_t #include // int64_t, uint64_t #include // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull #include // strlen #include // forward_list #include // function, hash, less #include // initializer_list #include // setw #include // istream, ostream #include // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator #include // numeric_limits #include // locale #include // map #include // addressof, allocator, allocator_traits, unique_ptr #include // accumulate #include // stringstream #include // domain_error, invalid_argument, out_of_range #include // getline, stoi, string, to_string #include // add_pointer, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type #include // declval, forward, make_pair, move, pair, swap #include // vector // exclude unsupported compilers #if defined(__clang__) #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" #endif #elif defined(__GNUC__) #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" #endif #endif // disable float-equal warnings on GCC/clang #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" #endif // disable documentation warnings on clang #if defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdocumentation" #endif // allow for portable deprecation warnings #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) #define JSON_DEPRECATED __attribute__((deprecated)) #elif defined(_MSC_VER) #define JSON_DEPRECATED __declspec(deprecated) #else #define JSON_DEPRECATED #endif // allow to disable exceptions #if not defined(JSON_NOEXCEPTION) || defined(__EXCEPTIONS) #define JSON_THROW(exception) throw exception #define JSON_TRY try #define JSON_CATCH(exception) catch(exception) #else #define JSON_THROW(exception) std::abort() #define JSON_TRY if(true) #define JSON_CATCH(exception) if(false) #endif /*! @brief namespace for Niels Lohmann @see https://github.com/nlohmann @since version 1.0.0 */ namespace nlohmann { /*! @brief unnamed namespace with internal helper functions This namespace collects some functions that could not be defined inside the @ref basic_json class. @since version 2.1.0 */ namespace detail { /////////////////////////// // JSON type enumeration // /////////////////////////// /*! @brief the JSON type enumeration This enumeration collects the different JSON types. It is internally used to distinguish the stored values, and the functions @ref basic_json::is_null(), @ref basic_json::is_object(), @ref basic_json::is_array(), @ref basic_json::is_string(), @ref basic_json::is_boolean(), @ref basic_json::is_number() (with @ref basic_json::is_number_integer(), @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and @ref basic_json::is_structured() rely on it. @note There are three enumeration entries (number_integer, number_unsigned, and number_float), because the library distinguishes these three types for numbers: @ref basic_json::number_unsigned_t is used for unsigned integers, @ref basic_json::number_integer_t is used for signed integers, and @ref basic_json::number_float_t is used for floating-point numbers or to approximate integers which do not fit in the limits of their respective type. @sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON value with the default value for a given type @since version 1.0.0 */ enum class value_t : uint8_t { null, ///< null value object, ///< object (unordered set of name/value pairs) array, ///< array (ordered collection of values) string, ///< string value boolean, ///< boolean value number_integer, ///< number value (signed integer) number_unsigned, ///< number value (unsigned integer) number_float, ///< number value (floating-point) discarded ///< discarded by the the parser callback function }; /*! @brief comparison operator for JSON types Returns an ordering that is similar to Python: - order: null < boolean < number < object < array < string - furthermore, each type is not smaller than itself @since version 1.0.0 */ inline bool operator<(const value_t lhs, const value_t rhs) noexcept { static constexpr std::array order = {{ 0, // null 3, // object 4, // array 5, // string 1, // boolean 2, // integer 2, // unsigned 2, // float } }; // discarded values are not comparable if (lhs == value_t::discarded or rhs == value_t::discarded) { return false; } return order[static_cast(lhs)] < order[static_cast(rhs)]; } ///////////// // helpers // ///////////// // alias templates to reduce boilerplate template using enable_if_t = typename std::enable_if::type; template using uncvref_t = typename std::remove_cv::type>::type; // taken from http://stackoverflow.com/a/26936864/266378 template using is_unscoped_enum = std::integral_constant::value and std::is_enum::value>; /* Implementation of two C++17 constructs: conjunction, negation. This is needed to avoid evaluating all the traits in a condition For example: not std::is_same::value and has_value_type::value will not compile when T = void (on MSVC at least). Whereas conjunction>, has_value_type>::value will stop evaluating if negation<...>::value == false Please note that those constructs must be used with caution, since symbols can become very long quickly (which can slow down compilation and cause MSVC internal compiler errors). Only use it when you have to (see example ahead). */ template struct conjunction : std::true_type {}; template struct conjunction : B1 {}; template struct conjunction : std::conditional, B1>::type {}; template struct negation : std::integral_constant < bool, !B::value > {}; // dispatch utility (taken from ranges-v3) template struct priority_tag : priority_tag < N - 1 > {}; template<> struct priority_tag<0> {}; ////////////////// // constructors // ////////////////// template struct external_constructor; template<> struct external_constructor { template static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept { j.m_type = value_t::boolean; j.m_value = b; j.assert_invariant(); } }; template<> struct external_constructor { template static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) { j.m_type = value_t::string; j.m_value = s; j.assert_invariant(); } }; template<> struct external_constructor { template static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept { // replace infinity and NAN by null if (not std::isfinite(val)) { j = BasicJsonType{}; } else { j.m_type = value_t::number_float; j.m_value = val; } j.assert_invariant(); } }; template<> struct external_constructor { template static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept { j.m_type = value_t::number_unsigned; j.m_value = val; j.assert_invariant(); } }; template<> struct external_constructor { template static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept { j.m_type = value_t::number_integer; j.m_value = val; j.assert_invariant(); } }; template<> struct external_constructor { template static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) { j.m_type = value_t::array; j.m_value = arr; j.assert_invariant(); } template::value, int> = 0> static void construct(BasicJsonType& j, const CompatibleArrayType& arr) { using std::begin; using std::end; j.m_type = value_t::array; j.m_value.array = j.template create(begin(arr), end(arr)); j.assert_invariant(); } }; template<> struct external_constructor { template static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) { j.m_type = value_t::object; j.m_value = obj; j.assert_invariant(); } template::value, int> = 0> static void construct(BasicJsonType& j, const CompatibleObjectType& obj) { using std::begin; using std::end; j.m_type = value_t::object; j.m_value.object = j.template create(begin(obj), end(obj)); j.assert_invariant(); } }; //////////////////////// // has_/is_ functions // //////////////////////// /*! @brief Helper to determine whether there's a key_type for T. This helper is used to tell associative containers apart from other containers such as sequence containers. For instance, `std::map` passes the test as it contains a `mapped_type`, whereas `std::vector` fails the test. @sa http://stackoverflow.com/a/7728728/266378 @since version 1.0.0, overworked in version 2.0.6 */ #define NLOHMANN_JSON_HAS_HELPER(type) \ template struct has_##type { \ private: \ template \ static int detect(U &&); \ static void detect(...); \ public: \ static constexpr bool value = \ std::is_integral()))>::value; \ } NLOHMANN_JSON_HAS_HELPER(mapped_type); NLOHMANN_JSON_HAS_HELPER(key_type); NLOHMANN_JSON_HAS_HELPER(value_type); NLOHMANN_JSON_HAS_HELPER(iterator); #undef NLOHMANN_JSON_HAS_HELPER template struct is_compatible_object_type_impl : std::false_type {}; template struct is_compatible_object_type_impl { static constexpr auto value = std::is_constructible::value and std::is_constructible::value; }; template struct is_compatible_object_type { static auto constexpr value = is_compatible_object_type_impl < conjunction>, has_mapped_type, has_key_type>::value, typename BasicJsonType::object_t, CompatibleObjectType >::value; }; template struct is_basic_json_nested_type { static auto constexpr value = std::is_same::value or std::is_same::value or std::is_same::value or std::is_same::value or std::is_same::value; }; template struct is_compatible_array_type { static auto constexpr value = conjunction>, negation>, negation>, negation>, has_value_type, has_iterator>::value; }; template struct is_compatible_integer_type_impl : std::false_type {}; template struct is_compatible_integer_type_impl { // is there an assert somewhere on overflows? using RealLimits = std::numeric_limits; using CompatibleLimits = std::numeric_limits; static constexpr auto value = std::is_constructible::value and CompatibleLimits::is_integer and RealLimits::is_signed == CompatibleLimits::is_signed; }; template struct is_compatible_integer_type { static constexpr auto value = is_compatible_integer_type_impl < std::is_integral::value and not std::is_same::value, RealIntegerType, CompatibleNumberIntegerType > ::value; }; // trait checking if JSONSerializer::from_json(json const&, udt&) exists template struct has_from_json { private: // also check the return type of from_json template::from_json( std::declval(), std::declval()))>::value>> static int detect(U&&); static void detect(...); public: static constexpr bool value = std::is_integral>()))>::value; }; // This trait checks if JSONSerializer::from_json(json const&) exists // this overload is used for non-default-constructible user-defined-types template struct has_non_default_from_json { private: template < typename U, typename = enable_if_t::from_json(std::declval()))>::value >> static int detect(U&&); static void detect(...); public: static constexpr bool value = std::is_integral>()))>::value; }; // This trait checks if BasicJsonType::json_serializer::to_json exists template struct has_to_json { private: template::to_json( std::declval(), std::declval()))> static int detect(U&&); static void detect(...); public: static constexpr bool value = std::is_integral>()))>::value; }; ///////////// // to_json // ///////////// template::value, int> = 0> void to_json(BasicJsonType& j, T b) noexcept { external_constructor::construct(j, b); } template::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleString& s) { external_constructor::construct(j, s); } template::value, int> = 0> void to_json(BasicJsonType& j, FloatType val) noexcept { external_constructor::construct(j, static_cast(val)); } template < typename BasicJsonType, typename CompatibleNumberUnsignedType, enable_if_t::value, int> = 0 > void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept { external_constructor::construct(j, static_cast(val)); } template < typename BasicJsonType, typename CompatibleNumberIntegerType, enable_if_t::value, int> = 0 > void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept { external_constructor::construct(j, static_cast(val)); } template::value, int> = 0> void to_json(BasicJsonType& j, UnscopedEnumType e) noexcept { external_constructor::construct(j, e); } template < typename BasicJsonType, typename CompatibleArrayType, enable_if_t < is_compatible_array_type::value or std::is_same::value, int > = 0 > void to_json(BasicJsonType& j, const CompatibleArrayType& arr) { external_constructor::construct(j, arr); } template < typename BasicJsonType, typename CompatibleObjectType, enable_if_t::value, int> = 0 > void to_json(BasicJsonType& j, const CompatibleObjectType& arr) { external_constructor::construct(j, arr); } /////////////// // from_json // /////////////// // overloads for basic_json template parameters template::value and not std::is_same::value, int> = 0> void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) { switch (static_cast(j)) { case value_t::number_unsigned: { val = static_cast( *j.template get_ptr()); break; } case value_t::number_integer: { val = static_cast( *j.template get_ptr()); break; } case value_t::number_float: { val = static_cast( *j.template get_ptr()); break; } default: { JSON_THROW( std::domain_error("type must be number, but is " + j.type_name())); } } } template void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) { if (not j.is_boolean()) { JSON_THROW(std::domain_error("type must be boolean, but is " + j.type_name())); } b = *j.template get_ptr(); } template void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) { if (not j.is_string()) { JSON_THROW(std::domain_error("type must be string, but is " + j.type_name())); } s = *j.template get_ptr(); } template void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) { get_arithmetic_value(j, val); } template void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) { get_arithmetic_value(j, val); } template void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) { get_arithmetic_value(j, val); } template::value, int> = 0> void from_json(const BasicJsonType& j, UnscopedEnumType& e) { typename std::underlying_type::type val; get_arithmetic_value(j, val); e = static_cast(val); } template void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) { if (not j.is_array()) { JSON_THROW(std::domain_error("type must be array, but is " + j.type_name())); } arr = *j.template get_ptr(); } // forward_list doesn't have an insert method template void from_json(const BasicJsonType& j, std::forward_list& l) { // do not perform the check when user wants to retrieve jsons // (except when it's null.. ?) if (j.is_null()) { JSON_THROW(std::domain_error("type must be array, but is " + j.type_name())); } if (not std::is_same::value) { if (not j.is_array()) { JSON_THROW(std::domain_error("type must be array, but is " + j.type_name())); } } for (auto it = j.rbegin(), end = j.rend(); it != end; ++it) { l.push_front(it->template get()); } } template void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>) { using std::begin; using std::end; std::transform(j.begin(), j.end(), std::inserter(arr, end(arr)), [](const BasicJsonType & i) { // get() returns *this, this won't call a from_json // method when value_type is BasicJsonType return i.template get(); }); } template auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>) -> decltype( arr.reserve(std::declval()), void()) { using std::begin; using std::end; arr.reserve(j.size()); std::transform( j.begin(), j.end(), std::inserter(arr, end(arr)), [](const BasicJsonType & i) { // get() returns *this, this won't call a from_json // method when value_type is BasicJsonType return i.template get(); }); } template::value and not std::is_same::value, int> = 0> void from_json(const BasicJsonType& j, CompatibleArrayType& arr) { if (j.is_null()) { JSON_THROW(std::domain_error("type must be array, but is " + j.type_name())); } // when T == BasicJsonType, do not check if value_t is correct if (not std::is_same::value) { if (not j.is_array()) { JSON_THROW(std::domain_error("type must be array, but is " + j.type_name())); } } from_json_array_impl(j, arr, priority_tag<1> {}); } template::value, int> = 0> void from_json(const BasicJsonType& j, CompatibleObjectType& obj) { if (not j.is_object()) { JSON_THROW(std::domain_error("type must be object, but is " + j.type_name())); } auto inner_object = j.template get_ptr(); using std::begin; using std::end; // we could avoid the assignment, but this might require a for loop, which // might be less efficient than the container constructor for some // containers (would it?) obj = CompatibleObjectType(begin(*inner_object), end(*inner_object)); } // overload for arithmetic types, not chosen for basic_json template arguments // (BooleanType, etc..); note: Is it really necessary to provide explicit // overloads for boolean_t etc. in case of a custom BooleanType which is not // an arithmetic type? template::value and not std::is_same::value and not std::is_same::value and not std::is_same::value and not std::is_same::value, int> = 0> void from_json(const BasicJsonType& j, ArithmeticType& val) { switch (static_cast(j)) { case value_t::number_unsigned: { val = static_cast(*j.template get_ptr()); break; } case value_t::number_integer: { val = static_cast(*j.template get_ptr()); break; } case value_t::number_float: { val = static_cast(*j.template get_ptr()); break; } case value_t::boolean: { val = static_cast(*j.template get_ptr()); break; } default: { JSON_THROW(std::domain_error("type must be number, but is " + j.type_name())); } } } struct to_json_fn { private: template auto call(BasicJsonType& j, T&& val, priority_tag<1>) const noexcept(noexcept(to_json(j, std::forward(val)))) -> decltype(to_json(j, std::forward(val)), void()) { return to_json(j, std::forward(val)); } template void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept { static_assert(sizeof(BasicJsonType) == 0, "could not find to_json() method in T's namespace"); } public: template void operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(std::declval().call(j, std::forward(val), priority_tag<1> {}))) { return call(j, std::forward(val), priority_tag<1> {}); } }; struct from_json_fn { private: template auto call(const BasicJsonType& j, T& val, priority_tag<1>) const noexcept(noexcept(from_json(j, val))) -> decltype(from_json(j, val), void()) { return from_json(j, val); } template void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept { static_assert(sizeof(BasicJsonType) == 0, "could not find from_json() method in T's namespace"); } public: template void operator()(const BasicJsonType& j, T& val) const noexcept(noexcept(std::declval().call(j, val, priority_tag<1> {}))) { return call(j, val, priority_tag<1> {}); } }; // taken from ranges-v3 template struct static_const { static constexpr T value{}; }; template constexpr T static_const::value; } // namespace detail /// namespace to hold default `to_json` / `from_json` functions namespace { constexpr const auto& to_json = detail::static_const::value; constexpr const auto& from_json = detail::static_const::value; } /*! @brief default JSONSerializer template argument This serializer ignores the template arguments and uses ADL ([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl)) for serialization. */ template struct adl_serializer { /*! @brief convert a JSON value to any value type This function is usually called by the `get()` function of the @ref basic_json class (either explicit or via conversion operators). @param[in] j JSON value to read from @param[in,out] val value to write to */ template static void from_json(BasicJsonType&& j, ValueType& val) noexcept( noexcept(::nlohmann::from_json(std::forward(j), val))) { ::nlohmann::from_json(std::forward(j), val); } /*! @brief convert any value type to a JSON value This function is usually called by the constructors of the @ref basic_json class. @param[in,out] j JSON value to write to @param[in] val value to read from */ template static void to_json(BasicJsonType& j, ValueType&& val) noexcept( noexcept(::nlohmann::to_json(j, std::forward(val)))) { ::nlohmann::to_json(j, std::forward(val)); } }; /*! @brief a class to store JSON values @tparam ObjectType type for JSON objects (`std::map` by default; will be used in @ref object_t) @tparam ArrayType type for JSON arrays (`std::vector` by default; will be used in @ref array_t) @tparam StringType type for JSON strings and object keys (`std::string` by default; will be used in @ref string_t) @tparam BooleanType type for JSON booleans (`bool` by default; will be used in @ref boolean_t) @tparam NumberIntegerType type for JSON integer numbers (`int64_t` by default; will be used in @ref number_integer_t) @tparam NumberUnsignedType type for JSON unsigned integer numbers (@c `uint64_t` by default; will be used in @ref number_unsigned_t) @tparam NumberFloatType type for JSON floating-point numbers (`double` by default; will be used in @ref number_float_t) @tparam AllocatorType type of the allocator to use (`std::allocator` by default) @tparam JSONSerializer the serializer to resolve internal calls to `to_json()` and `from_json()` (@ref adl_serializer by default) @requirement The class satisfies the following concept requirements: - Basic - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible): JSON values can be default constructed. The result will be a JSON null value. - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible): A JSON value can be constructed from an rvalue argument. - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible): A JSON value can be copy-constructed from an lvalue expression. - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable): A JSON value van be assigned from an rvalue argument. - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable): A JSON value can be copy-assigned from an lvalue expression. - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible): JSON values can be destructed. - Layout - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType): JSON values have [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout): All non-static data members are private and standard layout types, the class has no virtual functions or (virtual) base classes. - Library-wide - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable): JSON values can be compared with `==`, see @ref operator==(const_reference,const_reference). - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable): JSON values can be compared with `<`, see @ref operator<(const_reference,const_reference). - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable): Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of other compatible types, using unqualified function call @ref swap(). - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer): JSON values can be compared against `std::nullptr_t` objects which are used to model the `null` value. - Container - [Container](http://en.cppreference.com/w/cpp/concept/Container): JSON values can be used like STL containers and provide iterator access. - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer); JSON values can be used like STL containers and provide reverse iterator access. @invariant The member variables @a m_value and @a m_type have the following relationship: - If `m_type == value_t::object`, then `m_value.object != nullptr`. - If `m_type == value_t::array`, then `m_value.array != nullptr`. - If `m_type == value_t::string`, then `m_value.string != nullptr`. The invariants are checked by member function assert_invariant(). @internal @note ObjectType trick from http://stackoverflow.com/a/9860911 @endinternal @see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange Format](http://rfc7159.net/rfc7159) @since version 1.0.0 @nosubgrouping */ template < template class ObjectType = std::map, template class ArrayType = std::vector, class StringType = std::string, class BooleanType = bool, class NumberIntegerType = std::int64_t, class NumberUnsignedType = std::uint64_t, class NumberFloatType = double, template class AllocatorType = std::allocator, template class JSONSerializer = adl_serializer > class basic_json { private: template friend struct detail::external_constructor; /// workaround type for MSVC using basic_json_t = basic_json; public: using value_t = detail::value_t; // forward declarations template class iter_impl; template class json_reverse_iterator; class json_pointer; template using json_serializer = JSONSerializer; ///////////////////// // container types // ///////////////////// /// @name container types /// The canonic container types to use @ref basic_json like any other STL /// container. /// @{ /// the type of elements in a basic_json container using value_type = basic_json; /// the type of an element reference using reference = value_type&; /// the type of an element const reference using const_reference = const value_type&; /// a type to represent differences between iterators using difference_type = std::ptrdiff_t; /// a type to represent container sizes using size_type = std::size_t; /// the allocator type using allocator_type = AllocatorType; /// the type of an element pointer using pointer = typename std::allocator_traits::pointer; /// the type of an element const pointer using const_pointer = typename std::allocator_traits::const_pointer; /// an iterator for a basic_json container using iterator = iter_impl; /// a const iterator for a basic_json container using const_iterator = iter_impl; /// a reverse iterator for a basic_json container using reverse_iterator = json_reverse_iterator; /// a const reverse iterator for a basic_json container using const_reverse_iterator = json_reverse_iterator; /// @} /*! @brief returns the allocator associated with the container */ static allocator_type get_allocator() { return allocator_type(); } /*! @brief returns version information on the library This function returns a JSON object with information about the library, including the version number and information on the platform and compiler. @return JSON object holding version information key | description ----------- | --------------- `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). `copyright` | The copyright line for the library as string. `name` | The name of the library as string. `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. `url` | The URL of the project as string. `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). @liveexample{The following code shows an example output of the `meta()` function.,meta} @complexity Constant. @since 2.1.0 */ static basic_json meta() { basic_json result; result["copyright"] = "(C) 2013-2017 Niels Lohmann"; result["name"] = "JSON for Modern C++"; result["url"] = "https://github.com/nlohmann/json"; result["version"] = { {"string", "2.1.1"}, {"major", 2}, {"minor", 1}, {"patch", 1} }; #ifdef _WIN32 result["platform"] = "win32"; #elif defined __linux__ result["platform"] = "linux"; #elif defined __APPLE__ result["platform"] = "apple"; #elif defined __unix__ result["platform"] = "unix"; #else result["platform"] = "unknown"; #endif #if defined(__clang__) result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; #elif defined(__ICC) || defined(__INTEL_COMPILER) result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; #elif defined(__GNUC__) || defined(__GNUG__) result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; #elif defined(__HP_cc) || defined(__HP_aCC) result["compiler"] = "hp" #elif defined(__IBMCPP__) result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; #elif defined(_MSC_VER) result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; #elif defined(__PGI) result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; #elif defined(__SUNPRO_CC) result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; #else result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; #endif #ifdef __cplusplus result["compiler"]["c++"] = std::to_string(__cplusplus); #else result["compiler"]["c++"] = "unknown"; #endif return result; } /////////////////////////// // JSON value data types // /////////////////////////// /// @name JSON value data types /// The data types to store a JSON value. These types are derived from /// the template arguments passed to class @ref basic_json. /// @{ /*! @brief a type for an object [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: > An object is an unordered collection of zero or more name/value pairs, > where a name is a string and a value is a string, number, boolean, null, > object, or array. To store objects in C++, a type is defined by the template parameters described below. @tparam ObjectType the container to store objects (e.g., `std::map` or `std::unordered_map`) @tparam StringType the type of the keys or names (e.g., `std::string`). The comparison function `std::less` is used to order elements inside the container. @tparam AllocatorType the allocator to use for objects (e.g., `std::allocator`) #### Default type With the default values for @a ObjectType (`std::map`), @a StringType (`std::string`), and @a AllocatorType (`std::allocator`), the default value for @a object_t is: @code {.cpp} std::map< std::string, // key_type basic_json, // value_type std::less, // key_compare std::allocator> // allocator_type > @endcode #### Behavior The choice of @a object_t influences the behavior of the JSON class. With the default type, objects have the following behavior: - When all names are unique, objects will be interoperable in the sense that all software implementations receiving that object will agree on the name-value mappings. - When the names within an object are not unique, later stored name/value pairs overwrite previously stored name/value pairs, leaving the used names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will be treated as equal and both stored as `{"key": 1}`. - Internally, name/value pairs are stored in lexicographical order of the names. Objects will also be serialized (see @ref dump) in this order. For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored and serialized as `{"a": 2, "b": 1}`. - When comparing objects, the order of the name/value pairs is irrelevant. This makes objects interoperable in the sense that they will not be affected by these differences. For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be treated as equal. #### Limits [RFC 7159](http://rfc7159.net/rfc7159) specifies: > An implementation may set limits on the maximum depth of nesting. In this class, the object's limit of nesting is not constraint explicitly. However, a maximum depth of nesting may be introduced by the compiler or runtime environment. A theoretical limit can be queried by calling the @ref max_size function of a JSON object. #### Storage Objects are stored as pointers in a @ref basic_json type. That is, for any access to object values, a pointer of type `object_t*` must be dereferenced. @sa @ref array_t -- type for an array value @since version 1.0.0 @note The order name/value pairs are added to the object is *not* preserved by the library. Therefore, iterating an object may return name/value pairs in a different order than they were originally stored. In fact, keys will be traversed in alphabetical order as `std::map` with `std::less` is used by default. Please note this behavior conforms to [RFC 7159](http://rfc7159.net/rfc7159), because any order implements the specified "unordered" nature of JSON objects. */ using object_t = ObjectType, AllocatorType>>; /*! @brief a type for an array [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: > An array is an ordered sequence of zero or more values. To store objects in C++, a type is defined by the template parameters explained below. @tparam ArrayType container type to store arrays (e.g., `std::vector` or `std::list`) @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) #### Default type With the default values for @a ArrayType (`std::vector`) and @a AllocatorType (`std::allocator`), the default value for @a array_t is: @code {.cpp} std::vector< basic_json, // value_type std::allocator // allocator_type > @endcode #### Limits [RFC 7159](http://rfc7159.net/rfc7159) specifies: > An implementation may set limits on the maximum depth of nesting. In this class, the array's limit of nesting is not constraint explicitly. However, a maximum depth of nesting may be introduced by the compiler or runtime environment. A theoretical limit can be queried by calling the @ref max_size function of a JSON array. #### Storage Arrays are stored as pointers in a @ref basic_json type. That is, for any access to array values, a pointer of type `array_t*` must be dereferenced. @sa @ref object_t -- type for an object value @since version 1.0.0 */ using array_t = ArrayType>; /*! @brief a type for a string [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: > A string is a sequence of zero or more Unicode characters. To store objects in C++, a type is defined by the template parameter described below. Unicode values are split by the JSON class into byte-sized characters during deserialization. @tparam StringType the container to store strings (e.g., `std::string`). Note this container is used for keys/names in objects, see @ref object_t. #### Default type With the default values for @a StringType (`std::string`), the default value for @a string_t is: @code {.cpp} std::string @endcode #### Encoding Strings are stored in UTF-8 encoding. Therefore, functions like `std::string::size()` or `std::string::length()` return the number of bytes in the string rather than the number of characters or glyphs. #### String comparison [RFC 7159](http://rfc7159.net/rfc7159) states: > Software implementations are typically required to test names of object > members for equality. Implementations that transform the textual > representation into sequences of Unicode code units and then perform the > comparison numerically, code unit by code unit, are interoperable in the > sense that implementations will agree in all cases on equality or > inequality of two strings. For example, implementations that compare > strings with escaped characters unconverted may incorrectly find that > `"a\\b"` and `"a\u005Cb"` are not equal. This implementation is interoperable as it does compare strings code unit by code unit. #### Storage String values are stored as pointers in a @ref basic_json type. That is, for any access to string values, a pointer of type `string_t*` must be dereferenced. @since version 1.0.0 */ using string_t = StringType; /*! @brief a type for a boolean [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a type which differentiates the two literals `true` and `false`. To store objects in C++, a type is defined by the template parameter @a BooleanType which chooses the type to use. #### Default type With the default values for @a BooleanType (`bool`), the default value for @a boolean_t is: @code {.cpp} bool @endcode #### Storage Boolean values are stored directly inside a @ref basic_json type. @since version 1.0.0 */ using boolean_t = BooleanType; /*! @brief a type for a number (integer) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: > The representation of numbers is similar to that used in most > programming languages. A number is represented in base 10 using decimal > digits. It contains an integer component that may be prefixed with an > optional minus sign, which may be followed by a fraction part and/or an > exponent part. Leading zeros are not allowed. (...) Numeric values that > cannot be represented in the grammar below (such as Infinity and NaN) > are not permitted. This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is known whether the number is a signed integer, an unsigned integer or a floating-point number. Therefore, three different types, @ref number_integer_t, @ref number_unsigned_t and @ref number_float_t are used. To store integer numbers in C++, a type is defined by the template parameter @a NumberIntegerType which chooses the type to use. #### Default type With the default values for @a NumberIntegerType (`int64_t`), the default value for @a number_integer_t is: @code {.cpp} int64_t @endcode #### Default behavior - The restrictions about leading zeros is not enforced in C++. Instead, leading zeros in integer literals lead to an interpretation as octal number. Internally, the value will be stored as decimal number. For instance, the C++ integer literal `010` will be serialized to `8`. During deserialization, leading zeros yield an error. - Not-a-number (NaN) values will be serialized to `null`. #### Limits [RFC 7159](http://rfc7159.net/rfc7159) specifies: > An implementation may set limits on the range and precision of numbers. When the default type is used, the maximal integer number that can be stored is `9223372036854775807` (INT64_MAX) and the minimal integer number that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers that are out of range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers will be automatically be stored as @ref number_unsigned_t or @ref number_float_t. [RFC 7159](http://rfc7159.net/rfc7159) further states: > Note that when such software is used, numbers that are integers and are > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense > that implementations will agree exactly on their numeric values. As this range is a subrange of the exactly supported range [INT64_MIN, INT64_MAX], this class's integer type is interoperable. #### Storage Integer number values are stored directly inside a @ref basic_json type. @sa @ref number_float_t -- type for number values (floating-point) @sa @ref number_unsigned_t -- type for number values (unsigned integer) @since version 1.0.0 */ using number_integer_t = NumberIntegerType; /*! @brief a type for a number (unsigned) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: > The representation of numbers is similar to that used in most > programming languages. A number is represented in base 10 using decimal > digits. It contains an integer component that may be prefixed with an > optional minus sign, which may be followed by a fraction part and/or an > exponent part. Leading zeros are not allowed. (...) Numeric values that > cannot be represented in the grammar below (such as Infinity and NaN) > are not permitted. This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is known whether the number is a signed integer, an unsigned integer or a floating-point number. Therefore, three different types, @ref number_integer_t, @ref number_unsigned_t and @ref number_float_t are used. To store unsigned integer numbers in C++, a type is defined by the template parameter @a NumberUnsignedType which chooses the type to use. #### Default type With the default values for @a NumberUnsignedType (`uint64_t`), the default value for @a number_unsigned_t is: @code {.cpp} uint64_t @endcode #### Default behavior - The restrictions about leading zeros is not enforced in C++. Instead, leading zeros in integer literals lead to an interpretation as octal number. Internally, the value will be stored as decimal number. For instance, the C++ integer literal `010` will be serialized to `8`. During deserialization, leading zeros yield an error. - Not-a-number (NaN) values will be serialized to `null`. #### Limits [RFC 7159](http://rfc7159.net/rfc7159) specifies: > An implementation may set limits on the range and precision of numbers. When the default type is used, the maximal integer number that can be stored is `18446744073709551615` (UINT64_MAX) and the minimal integer number that can be stored is `0`. Integer numbers that are out of range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers will be automatically be stored as @ref number_integer_t or @ref number_float_t. [RFC 7159](http://rfc7159.net/rfc7159) further states: > Note that when such software is used, numbers that are integers and are > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense > that implementations will agree exactly on their numeric values. As this range is a subrange (when considered in conjunction with the number_integer_t type) of the exactly supported range [0, UINT64_MAX], this class's integer type is interoperable. #### Storage Integer number values are stored directly inside a @ref basic_json type. @sa @ref number_float_t -- type for number values (floating-point) @sa @ref number_integer_t -- type for number values (integer) @since version 2.0.0 */ using number_unsigned_t = NumberUnsignedType; /*! @brief a type for a number (floating-point) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: > The representation of numbers is similar to that used in most > programming languages. A number is represented in base 10 using decimal > digits. It contains an integer component that may be prefixed with an > optional minus sign, which may be followed by a fraction part and/or an > exponent part. Leading zeros are not allowed. (...) Numeric values that > cannot be represented in the grammar below (such as Infinity and NaN) > are not permitted. This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is known whether the number is a signed integer, an unsigned integer or a floating-point number. Therefore, three different types, @ref number_integer_t, @ref number_unsigned_t and @ref number_float_t are used. To store floating-point numbers in C++, a type is defined by the template parameter @a NumberFloatType which chooses the type to use. #### Default type With the default values for @a NumberFloatType (`double`), the default value for @a number_float_t is: @code {.cpp} double @endcode #### Default behavior - The restrictions about leading zeros is not enforced in C++. Instead, leading zeros in floating-point literals will be ignored. Internally, the value will be stored as decimal number. For instance, the C++ floating-point literal `01.2` will be serialized to `1.2`. During deserialization, leading zeros yield an error. - Not-a-number (NaN) values will be serialized to `null`. #### Limits [RFC 7159](http://rfc7159.net/rfc7159) states: > This specification allows implementations to set limits on the range and > precision of numbers accepted. Since software that implements IEEE > 754-2008 binary64 (double precision) numbers is generally available and > widely used, good interoperability can be achieved by implementations > that expect no more precision or range than these provide, in the sense > that implementations will approximate JSON numbers within the expected > precision. This implementation does exactly follow this approach, as it uses double precision floating-point numbers. Note values smaller than `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` will be stored as NaN internally and be serialized to `null`. #### Storage Floating-point number values are stored directly inside a @ref basic_json type. @sa @ref number_integer_t -- type for number values (integer) @sa @ref number_unsigned_t -- type for number values (unsigned integer) @since version 1.0.0 */ using number_float_t = NumberFloatType; /// @} private: /// helper for exception-safe object creation template static T* create(Args&& ... args) { AllocatorType alloc; auto deleter = [&](T * object) { alloc.deallocate(object, 1); }; std::unique_ptr object(alloc.allocate(1), deleter); alloc.construct(object.get(), std::forward(args)...); assert(object != nullptr); return object.release(); } //////////////////////// // JSON value storage // //////////////////////// /*! @brief a JSON value The actual storage for a JSON value of the @ref basic_json class. This union combines the different storage types for the JSON value types defined in @ref value_t. JSON type | value_t type | used type --------- | --------------- | ------------------------ object | object | pointer to @ref object_t array | array | pointer to @ref array_t string | string | pointer to @ref string_t boolean | boolean | @ref boolean_t number | number_integer | @ref number_integer_t number | number_unsigned | @ref number_unsigned_t number | number_float | @ref number_float_t null | null | *no value is stored* @note Variable-length types (objects, arrays, and strings) are stored as pointers. The size of the union should not exceed 64 bits if the default value types are used. @since version 1.0.0 */ union json_value { /// object (stored with pointer to save storage) object_t* object; /// array (stored with pointer to save storage) array_t* array; /// string (stored with pointer to save storage) string_t* string; /// boolean boolean_t boolean; /// number (integer) number_integer_t number_integer; /// number (unsigned integer) number_unsigned_t number_unsigned; /// number (floating-point) number_float_t number_float; /// default constructor (for null values) json_value() = default; /// constructor for booleans json_value(boolean_t v) noexcept : boolean(v) {} /// constructor for numbers (integer) json_value(number_integer_t v) noexcept : number_integer(v) {} /// constructor for numbers (unsigned) json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} /// constructor for numbers (floating-point) json_value(number_float_t v) noexcept : number_float(v) {} /// constructor for empty values of a given type json_value(value_t t) { switch (t) { case value_t::object: { object = create(); break; } case value_t::array: { array = create(); break; } case value_t::string: { string = create(""); break; } case value_t::boolean: { boolean = boolean_t(false); break; } case value_t::number_integer: { number_integer = number_integer_t(0); break; } case value_t::number_unsigned: { number_unsigned = number_unsigned_t(0); break; } case value_t::number_float: { number_float = number_float_t(0.0); break; } case value_t::null: { break; } default: { if (t == value_t::null) { JSON_THROW(std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE } break; } } } /// constructor for strings json_value(const string_t& value) { string = create(value); } /// constructor for objects json_value(const object_t& value) { object = create(value); } /// constructor for arrays json_value(const array_t& value) { array = create(value); } }; /*! @brief checks the class invariants This function asserts the class invariants. It needs to be called at the end of every constructor to make sure that created objects respect the invariant. Furthermore, it has to be called each time the type of a JSON value is changed, because the invariant expresses a relationship between @a m_type and @a m_value. */ void assert_invariant() const { assert(m_type != value_t::object or m_value.object != nullptr); assert(m_type != value_t::array or m_value.array != nullptr); assert(m_type != value_t::string or m_value.string != nullptr); } public: ////////////////////////// // JSON parser callback // ////////////////////////// /*! @brief JSON callback events This enumeration lists the parser events that can trigger calling a callback function of type @ref parser_callback_t during parsing. @image html callback_events.png "Example when certain parse events are triggered" @since version 1.0.0 */ enum class parse_event_t : uint8_t { /// the parser read `{` and started to process a JSON object object_start, /// the parser read `}` and finished processing a JSON object object_end, /// the parser read `[` and started to process a JSON array array_start, /// the parser read `]` and finished processing a JSON array array_end, /// the parser read a key of a value in an object key, /// the parser finished reading a JSON value value }; /*! @brief per-element parser callback type With a parser callback function, the result of parsing a JSON text can be influenced. When passed to @ref parse(std::istream&, const parser_callback_t) or @ref parse(const CharT, const parser_callback_t), it is called on certain events (passed as @ref parse_event_t via parameter @a event) with a set recursion depth @a depth and context JSON value @a parsed. The return value of the callback function is a boolean indicating whether the element that emitted the callback shall be kept or not. We distinguish six scenarios (determined by the event type) in which the callback function can be called. The following table describes the values of the parameters @a depth, @a event, and @a parsed. parameter @a event | description | parameter @a depth | parameter @a parsed ------------------ | ----------- | ------------------ | ------------------- parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value @image html callback_events.png "Example when certain parse events are triggered" Discarding a value (i.e., returning `false`) has different effects depending on the context in which function was called: - Discarded values in structured types are skipped. That is, the parser will behave as if the discarded value was never read. - In case a value outside a structured type is skipped, it is replaced with `null`. This case happens if the top-level element is skipped. @param[in] depth the depth of the recursion during parsing @param[in] event an event of type parse_event_t indicating the context in the callback function has been called @param[in,out] parsed the current intermediate parse result; note that writing to this value has no effect for parse_event_t::key events @return Whether the JSON value which called the function during parsing should be kept (`true`) or not (`false`). In the latter case, it is either skipped completely or replaced by an empty discarded object. @sa @ref parse(std::istream&, parser_callback_t) or @ref parse(const CharT, const parser_callback_t) for examples @since version 1.0.0 */ using parser_callback_t = std::function; ////////////////// // constructors // ////////////////// /// @name constructors and destructors /// Constructors of class @ref basic_json, copy/move constructor, copy /// assignment, static functions creating objects, and the destructor. /// @{ /*! @brief create an empty value with a given type Create an empty JSON value with a given type. The value will be default initialized with an empty value which depends on the type: Value type | initial value ----------- | ------------- null | `null` boolean | `false` string | `""` number | `0` object | `{}` array | `[]` @param[in] value_type the type of the value to create @complexity Constant. @throw std::bad_alloc if allocation for object, array, or string value fails @liveexample{The following code shows the constructor for different @ref value_t values,basic_json__value_t} @since version 1.0.0 */ basic_json(const value_t value_type) : m_type(value_type), m_value(value_type) { assert_invariant(); } /*! @brief create a null object Create a `null` JSON value. It either takes a null pointer as parameter (explicitly creating `null`) or no parameter (implicitly creating `null`). The passed null pointer itself is not read -- it is only used to choose the right constructor. @complexity Constant. @exceptionsafety No-throw guarantee: this constructor never throws exceptions. @liveexample{The following code shows the constructor with and without a null pointer parameter.,basic_json__nullptr_t} @since version 1.0.0 */ basic_json(std::nullptr_t = nullptr) noexcept : basic_json(value_t::null) { assert_invariant(); } /*! @brief create a JSON value This is a "catch all" constructor for all compatible JSON types; that is, types for which a `to_json()` method exsits. The constructor forwards the parameter @a val to that method (to `json_serializer::to_json` method with `U = uncvref_t`, to be exact). Template type @a CompatibleType includes, but is not limited to, the following types: - **arrays**: @ref array_t and all kinds of compatible containers such as `std::vector`, `std::deque`, `std::list`, `std::forward_list`, `std::array`, `std::set`, `std::unordered_set`, `std::multiset`, and `unordered_multiset` with a `value_type` from which a @ref basic_json value can be constructed. - **objects**: @ref object_t and all kinds of compatible associative containers such as `std::map`, `std::unordered_map`, `std::multimap`, and `std::unordered_multimap` with a `key_type` compatible to @ref string_t and a `value_type` from which a @ref basic_json value can be constructed. - **strings**: @ref string_t, string literals, and all compatible string containers can be used. - **numbers**: @ref number_integer_t, @ref number_unsigned_t, @ref number_float_t, and all convertible number types such as `int`, `size_t`, `int64_t`, `float` or `double` can be used. - **boolean**: @ref boolean_t / `bool` can be used. See the examples below. @tparam CompatibleType a type such that: - @a CompatibleType is not derived from `std::istream`, - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move constructors), - @a CompatibleType is not a @ref basic_json nested type (e.g., @ref json_pointer, @ref iterator, etc ...) - @ref @ref json_serializer has a `to_json(basic_json_t&, CompatibleType&&)` method @tparam U = `uncvref_t` @param[in] val the value to be forwarded @complexity Usually linear in the size of the passed @a val, also depending on the implementation of the called `to_json()` method. @throw what `json_serializer::to_json()` throws @liveexample{The following code shows the constructor with several compatible types.,basic_json__CompatibleType} @since version 2.1.0 */ template, detail::enable_if_t::value and not std::is_same::value and not detail::is_basic_json_nested_type< basic_json_t, U>::value and detail::has_to_json::value, int> = 0> basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer::to_json( std::declval(), std::forward(val)))) { JSONSerializer::to_json(*this, std::forward(val)); assert_invariant(); } /*! @brief create a container (array or object) from an initializer list Creates a JSON value of type array or object from the passed initializer list @a init. In case @a type_deduction is `true` (default), the type of the JSON value to be created is deducted from the initializer list @a init according to the following rules: 1. If the list is empty, an empty JSON object value `{}` is created. 2. If the list consists of pairs whose first element is a string, a JSON object value is created where the first elements of the pairs are treated as keys and the second elements are as values. 3. In all other cases, an array is created. The rules aim to create the best fit between a C++ initializer list and JSON values. The rationale is as follows: 1. The empty initializer list is written as `{}` which is exactly an empty JSON object. 2. C++ has now way of describing mapped types other than to list a list of pairs. As JSON requires that keys must be of type string, rule 2 is the weakest constraint one can pose on initializer lists to interpret them as an object. 3. In all other cases, the initializer list could not be interpreted as JSON object type, so interpreting it as JSON array type is safe. With the rules described above, the following JSON values cannot be expressed by an initializer list: - the empty array (`[]`): use @ref array(std::initializer_list) with an empty initializer list in this case - arrays whose elements satisfy rule 2: use @ref array(std::initializer_list) with the same initializer list in this case @note When used without parentheses around an empty initializer list, @ref basic_json() is called instead of this function, yielding the JSON null value. @param[in] init initializer list with JSON values @param[in] type_deduction internal parameter; when set to `true`, the type of the JSON value is deducted from the initializer list @a init; when set to `false`, the type provided via @a manual_type is forced. This mode is used by the functions @ref array(std::initializer_list) and @ref object(std::initializer_list). @param[in] manual_type internal parameter; when @a type_deduction is set to `false`, the created JSON value will use the provided type (only @ref value_t::array and @ref value_t::object are valid); when @a type_deduction is set to `true`, this parameter has no effect @throw std::domain_error if @a type_deduction is `false`, @a manual_type is `value_t::object`, but @a init contains an element which is not a pair whose first element is a string; example: `"cannot create object from initializer list"` @complexity Linear in the size of the initializer list @a init. @liveexample{The example below shows how JSON values are created from initializer lists.,basic_json__list_init_t} @sa @ref array(std::initializer_list) -- create a JSON array value from an initializer list @sa @ref object(std::initializer_list) -- create a JSON object value from an initializer list @since version 1.0.0 */ basic_json(std::initializer_list init, bool type_deduction = true, value_t manual_type = value_t::array) { // check if each element is an array with two elements whose first // element is a string bool is_an_object = std::all_of(init.begin(), init.end(), [](const basic_json & element) { return element.is_array() and element.size() == 2 and element[0].is_string(); }); // adjust type if type deduction is not wanted if (not type_deduction) { // if array is wanted, do not create an object though possible if (manual_type == value_t::array) { is_an_object = false; } // if object is wanted but impossible, throw an exception if (manual_type == value_t::object and not is_an_object) { JSON_THROW(std::domain_error("cannot create object from initializer list")); } } if (is_an_object) { // the initializer list is a list of pairs -> create object m_type = value_t::object; m_value = value_t::object; std::for_each(init.begin(), init.end(), [this](const basic_json & element) { m_value.object->emplace(*(element[0].m_value.string), element[1]); }); } else { // the initializer list describes an array -> create array m_type = value_t::array; m_value.array = create(init); } assert_invariant(); } /*! @brief explicitly create an array from an initializer list Creates a JSON array value from a given initializer list. That is, given a list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the initializer list is empty, the empty array `[]` is created. @note This function is only needed to express two edge cases that cannot be realized with the initializer list constructor (@ref basic_json(std::initializer_list, bool, value_t)). These cases are: 1. creating an array whose elements are all pairs whose first element is a string -- in this case, the initializer list constructor would create an object, taking the first elements as keys 2. creating an empty array -- passing the empty initializer list to the initializer list constructor yields an empty object @param[in] init initializer list with JSON values to create an array from (optional) @return JSON array value @complexity Linear in the size of @a init. @liveexample{The following code shows an example for the `array` function.,array} @sa @ref basic_json(std::initializer_list, bool, value_t) -- create a JSON value from an initializer list @sa @ref object(std::initializer_list) -- create a JSON object value from an initializer list @since version 1.0.0 */ static basic_json array(std::initializer_list init = std::initializer_list()) { return basic_json(init, false, value_t::array); } /*! @brief explicitly create an object from an initializer list Creates a JSON object value from a given initializer list. The initializer lists elements must be pairs, and their first elements must be strings. If the initializer list is empty, the empty object `{}` is created. @note This function is only added for symmetry reasons. In contrast to the related function @ref array(std::initializer_list), there are no cases which can only be expressed by this function. That is, any initializer list @a init can also be passed to the initializer list constructor @ref basic_json(std::initializer_list, bool, value_t). @param[in] init initializer list to create an object from (optional) @return JSON object value @throw std::domain_error if @a init is not a pair whose first elements are strings; thrown by @ref basic_json(std::initializer_list, bool, value_t) @complexity Linear in the size of @a init. @liveexample{The following code shows an example for the `object` function.,object} @sa @ref basic_json(std::initializer_list, bool, value_t) -- create a JSON value from an initializer list @sa @ref array(std::initializer_list) -- create a JSON array value from an initializer list @since version 1.0.0 */ static basic_json object(std::initializer_list init = std::initializer_list()) { return basic_json(init, false, value_t::object); } /*! @brief construct an array with count copies of given value Constructs a JSON array value by creating @a cnt copies of a passed value. In case @a cnt is `0`, an empty array is created. As postcondition, `std::distance(begin(),end()) == cnt` holds. @param[in] cnt the number of JSON copies of @a val to create @param[in] val the JSON value to copy @complexity Linear in @a cnt. @liveexample{The following code shows examples for the @ref basic_json(size_type\, const basic_json&) constructor.,basic_json__size_type_basic_json} @since version 1.0.0 */ basic_json(size_type cnt, const basic_json& val) : m_type(value_t::array) { m_value.array = create(cnt, val); assert_invariant(); } /*! @brief construct a JSON container given an iterator range Constructs the JSON value with the contents of the range `[first, last)`. The semantics depends on the different types a JSON value can have: - In case of primitive types (number, boolean, or string), @a first must be `begin()` and @a last must be `end()`. In this case, the value is copied. Otherwise, std::out_of_range is thrown. - In case of structured types (array, object), the constructor behaves as similar versions for `std::vector`. - In case of a null type, std::domain_error is thrown. @tparam InputIT an input iterator type (@ref iterator or @ref const_iterator) @param[in] first begin of the range to copy from (included) @param[in] last end of the range to copy from (excluded) @pre Iterators @a first and @a last must be initialized. **This precondition is enforced with an assertion.** @throw std::domain_error if iterators are not compatible; that is, do not belong to the same JSON value; example: `"iterators are not compatible"` @throw std::out_of_range if iterators are for a primitive type (number, boolean, or string) where an out of range error can be detected easily; example: `"iterators out of range"` @throw std::bad_alloc if allocation for object, array, or string fails @throw std::domain_error if called with a null value; example: `"cannot use construct with iterators from null"` @complexity Linear in distance between @a first and @a last. @liveexample{The example below shows several ways to create JSON values by specifying a subrange with iterators.,basic_json__InputIt_InputIt} @since version 1.0.0 */ template::value or std::is_same::value, int>::type = 0> basic_json(InputIT first, InputIT last) { assert(first.m_object != nullptr); assert(last.m_object != nullptr); // make sure iterator fits the current value if (first.m_object != last.m_object) { JSON_THROW(std::domain_error("iterators are not compatible")); } // copy type from first iterator m_type = first.m_object->m_type; // check if iterator range is complete for primitive values switch (m_type) { case value_t::boolean: case value_t::number_float: case value_t::number_integer: case value_t::number_unsigned: case value_t::string: { if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) { JSON_THROW(std::out_of_range("iterators out of range")); } break; } default: { break; } } switch (m_type) { case value_t::number_integer: { m_value.number_integer = first.m_object->m_value.number_integer; break; } case value_t::number_unsigned: { m_value.number_unsigned = first.m_object->m_value.number_unsigned; break; } case value_t::number_float: { m_value.number_float = first.m_object->m_value.number_float; break; } case value_t::boolean: { m_value.boolean = first.m_object->m_value.boolean; break; } case value_t::string: { m_value = *first.m_object->m_value.string; break; } case value_t::object: { m_value.object = create(first.m_it.object_iterator, last.m_it.object_iterator); break; } case value_t::array: { m_value.array = create(first.m_it.array_iterator, last.m_it.array_iterator); break; } default: { JSON_THROW(std::domain_error("cannot use construct with iterators from " + first.m_object->type_name())); } } assert_invariant(); } /*! @brief construct a JSON value given an input stream @param[in,out] i stream to read a serialized JSON value from @param[in] cb a parser callback function of type @ref parser_callback_t which is used to control the deserialization by filtering unwanted values (optional) @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @note A UTF-8 byte order mark is silently ignored. @deprecated This constructor is deprecated and will be removed in version 3.0.0 to unify the interface of the library. Deserialization will be done by stream operators or by calling one of the `parse` functions, e.g. @ref parse(std::istream&, const parser_callback_t). That is, calls like `json j(i);` for an input stream @a i need to be replaced by `json j = json::parse(i);`. See the example below. @liveexample{The example below demonstrates constructing a JSON value from a `std::stringstream` with and without callback function.,basic_json__istream} @since version 2.0.0, deprecated in version 2.0.3, to be removed in version 3.0.0 */ JSON_DEPRECATED explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr) { *this = parser(i, cb).parse(); assert_invariant(); } /////////////////////////////////////// // other constructors and destructor // /////////////////////////////////////// /*! @brief copy constructor Creates a copy of a given JSON value. @param[in] other the JSON value to copy @complexity Linear in the size of @a other. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is linear. - As postcondition, it holds: `other == basic_json(other)`. @throw std::bad_alloc if allocation for object, array, or string fails. @liveexample{The following code shows an example for the copy constructor.,basic_json__basic_json} @since version 1.0.0 */ basic_json(const basic_json& other) : m_type(other.m_type) { // check of passed value is valid other.assert_invariant(); switch (m_type) { case value_t::object: { m_value = *other.m_value.object; break; } case value_t::array: { m_value = *other.m_value.array; break; } case value_t::string: { m_value = *other.m_value.string; break; } case value_t::boolean: { m_value = other.m_value.boolean; break; } case value_t::number_integer: { m_value = other.m_value.number_integer; break; } case value_t::number_unsigned: { m_value = other.m_value.number_unsigned; break; } case value_t::number_float: { m_value = other.m_value.number_float; break; } default: { break; } } assert_invariant(); } /*! @brief move constructor Move constructor. Constructs a JSON value with the contents of the given value @a other using move semantics. It "steals" the resources from @a other and leaves it as JSON null value. @param[in,out] other value to move to this object @post @a other is a JSON null value @complexity Constant. @liveexample{The code below shows the move constructor explicitly called via std::move.,basic_json__moveconstructor} @since version 1.0.0 */ basic_json(basic_json&& other) noexcept : m_type(std::move(other.m_type)), m_value(std::move(other.m_value)) { // check that passed value is valid other.assert_invariant(); // invalidate payload other.m_type = value_t::null; other.m_value = {}; assert_invariant(); } /*! @brief copy assignment Copy assignment operator. Copies a JSON value via the "copy and swap" strategy: It is expressed in terms of the copy constructor, destructor, and the swap() member function. @param[in] other value to copy from @complexity Linear. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is linear. @liveexample{The code below shows and example for the copy assignment. It creates a copy of value `a` which is then swapped with `b`. Finally\, the copy of `a` (which is the null value after the swap) is destroyed.,basic_json__copyassignment} @since version 1.0.0 */ reference& operator=(basic_json other) noexcept ( std::is_nothrow_move_constructible::value and std::is_nothrow_move_assignable::value and std::is_nothrow_move_constructible::value and std::is_nothrow_move_assignable::value ) { // check that passed value is valid other.assert_invariant(); using std::swap; swap(m_type, other.m_type); swap(m_value, other.m_value); assert_invariant(); return *this; } /*! @brief destructor Destroys the JSON value and frees all allocated memory. @complexity Linear. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is linear. - All stored elements are destroyed and all memory is freed. @since version 1.0.0 */ ~basic_json() { assert_invariant(); switch (m_type) { case value_t::object: { AllocatorType alloc; alloc.destroy(m_value.object); alloc.deallocate(m_value.object, 1); break; } case value_t::array: { AllocatorType alloc; alloc.destroy(m_value.array); alloc.deallocate(m_value.array, 1); break; } case value_t::string: { AllocatorType alloc; alloc.destroy(m_value.string); alloc.deallocate(m_value.string, 1); break; } default: { // all other types need no specific destructor break; } } } /// @} public: /////////////////////// // object inspection // /////////////////////// /// @name object inspection /// Functions to inspect the type of a JSON value. /// @{ /*! @brief serialization Serialization function for JSON values. The function tries to mimic Python's `json.dumps()` function, and currently supports its @a indent parameter. @param[in] indent If indent is nonnegative, then array elements and object members will be pretty-printed with that indent level. An indent level of `0` will only insert newlines. `-1` (the default) selects the most compact representation. @return string containing the serialization of the JSON value @complexity Linear. @liveexample{The following example shows the effect of different @a indent parameters to the result of the serialization.,dump} @see https://docs.python.org/2/library/json.html#json.dump @since version 1.0.0 */ string_t dump(const int indent = -1) const { std::stringstream ss; if (indent >= 0) { dump(ss, true, static_cast(indent)); } else { dump(ss, false, 0); } return ss.str(); } /*! @brief return the type of the JSON value (explicit) Return the type of the JSON value as a value from the @ref value_t enumeration. @return the type of the JSON value @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `type()` for all JSON types.,type} @since version 1.0.0 */ constexpr value_t type() const noexcept { return m_type; } /*! @brief return whether type is primitive This function returns true iff the JSON type is primitive (string, number, boolean, or null). @return `true` if type is primitive (string, number, boolean, or null), `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_primitive()` for all JSON types.,is_primitive} @sa @ref is_structured() -- returns whether JSON value is structured @sa @ref is_null() -- returns whether JSON value is `null` @sa @ref is_string() -- returns whether JSON value is a string @sa @ref is_boolean() -- returns whether JSON value is a boolean @sa @ref is_number() -- returns whether JSON value is a number @since version 1.0.0 */ constexpr bool is_primitive() const noexcept { return is_null() or is_string() or is_boolean() or is_number(); } /*! @brief return whether type is structured This function returns true iff the JSON type is structured (array or object). @return `true` if type is structured (array or object), `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_structured()` for all JSON types.,is_structured} @sa @ref is_primitive() -- returns whether value is primitive @sa @ref is_array() -- returns whether value is an array @sa @ref is_object() -- returns whether value is an object @since version 1.0.0 */ constexpr bool is_structured() const noexcept { return is_array() or is_object(); } /*! @brief return whether value is null This function returns true iff the JSON value is null. @return `true` if type is null, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_null()` for all JSON types.,is_null} @since version 1.0.0 */ constexpr bool is_null() const noexcept { return m_type == value_t::null; } /*! @brief return whether value is a boolean This function returns true iff the JSON value is a boolean. @return `true` if type is boolean, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_boolean()` for all JSON types.,is_boolean} @since version 1.0.0 */ constexpr bool is_boolean() const noexcept { return m_type == value_t::boolean; } /*! @brief return whether value is a number This function returns true iff the JSON value is a number. This includes both integer and floating-point values. @return `true` if type is number (regardless whether integer, unsigned integer or floating-type), `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_number()` for all JSON types.,is_number} @sa @ref is_number_integer() -- check if value is an integer or unsigned integer number @sa @ref is_number_unsigned() -- check if value is an unsigned integer number @sa @ref is_number_float() -- check if value is a floating-point number @since version 1.0.0 */ constexpr bool is_number() const noexcept { return is_number_integer() or is_number_float(); } /*! @brief return whether value is an integer number This function returns true iff the JSON value is an integer or unsigned integer number. This excludes floating-point values. @return `true` if type is an integer or unsigned integer number, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_number_integer()` for all JSON types.,is_number_integer} @sa @ref is_number() -- check if value is a number @sa @ref is_number_unsigned() -- check if value is an unsigned integer number @sa @ref is_number_float() -- check if value is a floating-point number @since version 1.0.0 */ constexpr bool is_number_integer() const noexcept { return m_type == value_t::number_integer or m_type == value_t::number_unsigned; } /*! @brief return whether value is an unsigned integer number This function returns true iff the JSON value is an unsigned integer number. This excludes floating-point and (signed) integer values. @return `true` if type is an unsigned integer number, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_number_unsigned()` for all JSON types.,is_number_unsigned} @sa @ref is_number() -- check if value is a number @sa @ref is_number_integer() -- check if value is an integer or unsigned integer number @sa @ref is_number_float() -- check if value is a floating-point number @since version 2.0.0 */ constexpr bool is_number_unsigned() const noexcept { return m_type == value_t::number_unsigned; } /*! @brief return whether value is a floating-point number This function returns true iff the JSON value is a floating-point number. This excludes integer and unsigned integer values. @return `true` if type is a floating-point number, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_number_float()` for all JSON types.,is_number_float} @sa @ref is_number() -- check if value is number @sa @ref is_number_integer() -- check if value is an integer number @sa @ref is_number_unsigned() -- check if value is an unsigned integer number @since version 1.0.0 */ constexpr bool is_number_float() const noexcept { return m_type == value_t::number_float; } /*! @brief return whether value is an object This function returns true iff the JSON value is an object. @return `true` if type is object, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_object()` for all JSON types.,is_object} @since version 1.0.0 */ constexpr bool is_object() const noexcept { return m_type == value_t::object; } /*! @brief return whether value is an array This function returns true iff the JSON value is an array. @return `true` if type is array, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_array()` for all JSON types.,is_array} @since version 1.0.0 */ constexpr bool is_array() const noexcept { return m_type == value_t::array; } /*! @brief return whether value is a string This function returns true iff the JSON value is a string. @return `true` if type is string, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_string()` for all JSON types.,is_string} @since version 1.0.0 */ constexpr bool is_string() const noexcept { return m_type == value_t::string; } /*! @brief return whether value is discarded This function returns true iff the JSON value was discarded during parsing with a callback function (see @ref parser_callback_t). @note This function will always be `false` for JSON values after parsing. That is, discarded values can only occur during parsing, but will be removed when inside a structured value or replaced by null in other cases. @return `true` if type is discarded, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_discarded()` for all JSON types.,is_discarded} @since version 1.0.0 */ constexpr bool is_discarded() const noexcept { return m_type == value_t::discarded; } /*! @brief return the type of the JSON value (implicit) Implicitly return the type of the JSON value as a value from the @ref value_t enumeration. @return the type of the JSON value @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies the @ref value_t operator for all JSON types.,operator__value_t} @since version 1.0.0 */ constexpr operator value_t() const noexcept { return m_type; } /// @} private: ////////////////// // value access // ////////////////// /// get a boolean (explicit) boolean_t get_impl(boolean_t* /*unused*/) const { if (is_boolean()) { return m_value.boolean; } JSON_THROW(std::domain_error("type must be boolean, but is " + type_name())); } /// get a pointer to the value (object) object_t* get_impl_ptr(object_t* /*unused*/) noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (object) constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (array) array_t* get_impl_ptr(array_t* /*unused*/) noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (array) constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (string) string_t* get_impl_ptr(string_t* /*unused*/) noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (string) constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (boolean) boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (boolean) constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (integer number) number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept { return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept { return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept { return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (unsigned number) constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept { return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (floating-point number) number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept { return is_number_float() ? &m_value.number_float : nullptr; } /// get a pointer to the value (floating-point number) constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept { return is_number_float() ? &m_value.number_float : nullptr; } /*! @brief helper function to implement get_ref() This funcion helps to implement get_ref() without code duplication for const and non-const overloads @tparam ThisType will be deduced as `basic_json` or `const basic_json` @throw std::domain_error if ReferenceType does not match underlying value type of the current JSON */ template static ReferenceType get_ref_impl(ThisType& obj) { // helper type using PointerType = typename std::add_pointer::type; // delegate the call to get_ptr<>() auto ptr = obj.template get_ptr(); if (ptr != nullptr) { return *ptr; } JSON_THROW(std::domain_error("incompatible ReferenceType for get_ref, actual type is " + obj.type_name())); } public: /// @name value access /// Direct access to the stored value of a JSON value. /// @{ /*! @brief get special-case overload This overloads avoids a lot of template boilerplate, it can be seen as the identity method @tparam BasicJsonType == @ref basic_json @return a copy of *this @complexity Constant. @since version 2.1.0 */ template < typename BasicJsonType, detail::enable_if_t::type, basic_json_t>::value, int> = 0 > basic_json get() const { return *this; } /*! @brief get a value (explicit) Explicit type conversion between the JSON value and a compatible value which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). The value is converted by calling the @ref json_serializer `from_json()` method. The function is equivalent to executing @code {.cpp} ValueType ret; JSONSerializer::from_json(*this, ret); return ret; @endcode This overloads is chosen if: - @a ValueType is not @ref basic_json, - @ref json_serializer has a `from_json()` method of the form `void from_json(const @ref basic_json&, ValueType&)`, and - @ref json_serializer does not have a `from_json()` method of the form `ValueType from_json(const @ref basic_json&)` @tparam ValueTypeCV the provided value type @tparam ValueType the returned value type @return copy of the JSON value, converted to @a ValueType @throw what @ref json_serializer `from_json()` method throws @liveexample{The example below shows several conversions from JSON values to other types. There a few things to note: (1) Floating-point numbers can be converted to integers\, (2) A JSON array can be converted to a standard `std::vector`\, (3) A JSON object can be converted to C++ associative containers such as `std::unordered_map`.,get__ValueType_const} @since version 2.1.0 */ template < typename ValueTypeCV, typename ValueType = detail::uncvref_t, detail::enable_if_t < not std::is_same::value and detail::has_from_json::value and not detail::has_non_default_from_json::value, int > = 0 > ValueType get() const noexcept(noexcept( JSONSerializer::from_json(std::declval(), std::declval()))) { // we cannot static_assert on ValueTypeCV being non-const, because // there is support for get(), which is why we // still need the uncvref static_assert(not std::is_reference::value, "get() cannot be used with reference types, you might want to use get_ref()"); static_assert(std::is_default_constructible::value, "types must be DefaultConstructible when used with get()"); ValueType ret; JSONSerializer::from_json(*this, ret); return ret; } /*! @brief get a value (explicit); special case Explicit type conversion between the JSON value and a compatible value which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). The value is converted by calling the @ref json_serializer `from_json()` method. The function is equivalent to executing @code {.cpp} return JSONSerializer::from_json(*this); @endcode This overloads is chosen if: - @a ValueType is not @ref basic_json and - @ref json_serializer has a `from_json()` method of the form `ValueType from_json(const @ref basic_json&)` @note If @ref json_serializer has both overloads of `from_json()`, this one is chosen. @tparam ValueTypeCV the provided value type @tparam ValueType the returned value type @return copy of the JSON value, converted to @a ValueType @throw what @ref json_serializer `from_json()` method throws @since version 2.1.0 */ template < typename ValueTypeCV, typename ValueType = detail::uncvref_t, detail::enable_if_t::value and detail::has_non_default_from_json::value, int> = 0 > ValueType get() const noexcept(noexcept( JSONSerializer::from_json(std::declval()))) { static_assert(not std::is_reference::value, "get() cannot be used with reference types, you might want to use get_ref()"); return JSONSerializer::from_json(*this); } /*! @brief get a pointer value (explicit) Explicit pointer access to the internally stored JSON value. No copies are made. @warning The pointer becomes invalid if the underlying JSON object changes. @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, @ref number_unsigned_t, or @ref number_float_t. @return pointer to the internally stored JSON value if the requested pointer type @a PointerType fits to the JSON value; `nullptr` otherwise @complexity Constant. @liveexample{The example below shows how pointers to internal values of a JSON value can be requested. Note that no type conversions are made and a `nullptr` is returned if the value and the requested pointer type does not match.,get__PointerType} @sa @ref get_ptr() for explicit pointer-member access @since version 1.0.0 */ template::value, int>::type = 0> PointerType get() noexcept { // delegate the call to get_ptr return get_ptr(); } /*! @brief get a pointer value (explicit) @copydoc get() */ template::value, int>::type = 0> constexpr const PointerType get() const noexcept { // delegate the call to get_ptr return get_ptr(); } /*! @brief get a pointer value (implicit) Implicit pointer access to the internally stored JSON value. No copies are made. @warning Writing data to the pointee of the result yields an undefined state. @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, @ref number_unsigned_t, or @ref number_float_t. Enforced by a static assertion. @return pointer to the internally stored JSON value if the requested pointer type @a PointerType fits to the JSON value; `nullptr` otherwise @complexity Constant. @liveexample{The example below shows how pointers to internal values of a JSON value can be requested. Note that no type conversions are made and a `nullptr` is returned if the value and the requested pointer type does not match.,get_ptr} @since version 1.0.0 */ template::value, int>::type = 0> PointerType get_ptr() noexcept { // get the type of the PointerType (remove pointer and const) using pointee_t = typename std::remove_const::type>::type>::type; // make sure the type matches the allowed types static_assert( std::is_same::value or std::is_same::value or std::is_same::value or std::is_same::value or std::is_same::value or std::is_same::value or std::is_same::value , "incompatible pointer type"); // delegate the call to get_impl_ptr<>() return get_impl_ptr(static_cast(nullptr)); } /*! @brief get a pointer value (implicit) @copydoc get_ptr() */ template::value and std::is_const::type>::value, int>::type = 0> constexpr const PointerType get_ptr() const noexcept { // get the type of the PointerType (remove pointer and const) using pointee_t = typename std::remove_const::type>::type>::type; // make sure the type matches the allowed types static_assert( std::is_same::value or std::is_same::value or std::is_same::value or std::is_same::value or std::is_same::value or std::is_same::value or std::is_same::value , "incompatible pointer type"); // delegate the call to get_impl_ptr<>() const return get_impl_ptr(static_cast(nullptr)); } /*! @brief get a reference value (implicit) Implicit reference access to the internally stored JSON value. No copies are made. @warning Writing data to the referee of the result yields an undefined state. @tparam ReferenceType reference type; must be a reference to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref number_float_t. Enforced by static assertion. @return reference to the internally stored JSON value if the requested reference type @a ReferenceType fits to the JSON value; throws std::domain_error otherwise @throw std::domain_error in case passed type @a ReferenceType is incompatible with the stored JSON value @complexity Constant. @liveexample{The example shows several calls to `get_ref()`.,get_ref} @since version 1.1.0 */ template::value, int>::type = 0> ReferenceType get_ref() { // delegate call to get_ref_impl return get_ref_impl(*this); } /*! @brief get a reference value (implicit) @copydoc get_ref() */ template::value and std::is_const::type>::value, int>::type = 0> ReferenceType get_ref() const { // delegate call to get_ref_impl return get_ref_impl(*this); } /*! @brief get a value (implicit) Implicit type conversion between the JSON value and a compatible value. The call is realized by calling @ref get() const. @tparam ValueType non-pointer type compatible to the JSON value, for instance `int` for JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for JSON arrays. The character type of @ref string_t as well as an initializer list of this type is excluded to avoid ambiguities as these types implicitly convert to `std::string`. @return copy of the JSON value, converted to type @a ValueType @throw std::domain_error in case passed type @a ValueType is incompatible to JSON, thrown by @ref get() const @complexity Linear in the size of the JSON value. @liveexample{The example below shows several conversions from JSON values to other types. There a few things to note: (1) Floating-point numbers can be converted to integers\, (2) A JSON array can be converted to a standard `std::vector`\, (3) A JSON object can be converted to C++ associative containers such as `std::unordered_map`.,operator__ValueType} @since version 1.0.0 */ template < typename ValueType, typename std::enable_if < not std::is_pointer::value and not std::is_same::value #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value #endif , int >::type = 0 > operator ValueType() const { // delegate the call to get<>() const return get(); } /// @} //////////////////// // element access // //////////////////// /// @name element access /// Access to the JSON value. /// @{ /*! @brief access specified array element with bounds checking Returns a reference to the element at specified location @a idx, with bounds checking. @param[in] idx index of the element to access @return reference to the element at index @a idx @throw std::domain_error if the JSON value is not an array; example: `"cannot use at() with string"` @throw std::out_of_range if the index @a idx is out of range of the array; that is, `idx >= size()`; example: `"array index 7 is out of range"` @complexity Constant. @liveexample{The example below shows how array elements can be read and written using `at()`.,at__size_type} @since version 1.0.0 */ reference at(size_type idx) { // at only works for arrays if (is_array()) { JSON_TRY { return m_value.array->at(idx); } JSON_CATCH (std::out_of_range&) { // create better exception explanation JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range")); } } else { JSON_THROW(std::domain_error("cannot use at() with " + type_name())); } } /*! @brief access specified array element with bounds checking Returns a const reference to the element at specified location @a idx, with bounds checking. @param[in] idx index of the element to access @return const reference to the element at index @a idx @throw std::domain_error if the JSON value is not an array; example: `"cannot use at() with string"` @throw std::out_of_range if the index @a idx is out of range of the array; that is, `idx >= size()`; example: `"array index 7 is out of range"` @complexity Constant. @liveexample{The example below shows how array elements can be read using `at()`.,at__size_type_const} @since version 1.0.0 */ const_reference at(size_type idx) const { // at only works for arrays if (is_array()) { JSON_TRY { return m_value.array->at(idx); } JSON_CATCH (std::out_of_range&) { // create better exception explanation JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range")); } } else { JSON_THROW(std::domain_error("cannot use at() with " + type_name())); } } /*! @brief access specified object element with bounds checking Returns a reference to the element at with specified key @a key, with bounds checking. @param[in] key key of the element to access @return reference to the element at key @a key @throw std::domain_error if the JSON value is not an object; example: `"cannot use at() with boolean"` @throw std::out_of_range if the key @a key is is not stored in the object; that is, `find(key) == end()`; example: `"key "the fast" not found"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read and written using `at()`.,at__object_t_key_type} @sa @ref operator[](const typename object_t::key_type&) for unchecked access by reference @sa @ref value() for access by value with a default value @since version 1.0.0 */ reference at(const typename object_t::key_type& key) { // at only works for objects if (is_object()) { JSON_TRY { return m_value.object->at(key); } JSON_CATCH (std::out_of_range&) { // create better exception explanation JSON_THROW(std::out_of_range("key '" + key + "' not found")); } } else { JSON_THROW(std::domain_error("cannot use at() with " + type_name())); } } /*! @brief access specified object element with bounds checking Returns a const reference to the element at with specified key @a key, with bounds checking. @param[in] key key of the element to access @return const reference to the element at key @a key @throw std::domain_error if the JSON value is not an object; example: `"cannot use at() with boolean"` @throw std::out_of_range if the key @a key is is not stored in the object; that is, `find(key) == end()`; example: `"key "the fast" not found"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read using `at()`.,at__object_t_key_type_const} @sa @ref operator[](const typename object_t::key_type&) for unchecked access by reference @sa @ref value() for access by value with a default value @since version 1.0.0 */ const_reference at(const typename object_t::key_type& key) const { // at only works for objects if (is_object()) { JSON_TRY { return m_value.object->at(key); } JSON_CATCH (std::out_of_range&) { // create better exception explanation JSON_THROW(std::out_of_range("key '" + key + "' not found")); } } else { JSON_THROW(std::domain_error("cannot use at() with " + type_name())); } } /*! @brief access specified array element Returns a reference to the element at specified location @a idx. @note If @a idx is beyond the range of the array (i.e., `idx >= size()`), then the array is silently filled up with `null` values to make `idx` a valid reference to the last stored element. @param[in] idx index of the element to access @return reference to the element at index @a idx @throw std::domain_error if JSON is not an array or null; example: `"cannot use operator[] with string"` @complexity Constant if @a idx is in the range of the array. Otherwise linear in `idx - size()`. @liveexample{The example below shows how array elements can be read and written using `[]` operator. Note the addition of `null` values.,operatorarray__size_type} @since version 1.0.0 */ reference operator[](size_type idx) { // implicitly convert null value to an empty array if (is_null()) { m_type = value_t::array; m_value.array = create(); assert_invariant(); } // operator[] only works for arrays if (is_array()) { // fill up array with null values if given idx is outside range if (idx >= m_value.array->size()) { m_value.array->insert(m_value.array->end(), idx - m_value.array->size() + 1, basic_json()); } return m_value.array->operator[](idx); } JSON_THROW(std::domain_error("cannot use operator[] with " + type_name())); } /*! @brief access specified array element Returns a const reference to the element at specified location @a idx. @param[in] idx index of the element to access @return const reference to the element at index @a idx @throw std::domain_error if JSON is not an array; example: `"cannot use operator[] with null"` @complexity Constant. @liveexample{The example below shows how array elements can be read using the `[]` operator.,operatorarray__size_type_const} @since version 1.0.0 */ const_reference operator[](size_type idx) const { // const operator[] only works for arrays if (is_array()) { return m_value.array->operator[](idx); } JSON_THROW(std::domain_error("cannot use operator[] with " + type_name())); } /*! @brief access specified object element Returns a reference to the element at with specified key @a key. @note If @a key is not found in the object, then it is silently added to the object and filled with a `null` value to make `key` a valid reference. In case the value was `null` before, it is converted to an object. @param[in] key key of the element to access @return reference to the element at key @a key @throw std::domain_error if JSON is not an object or null; example: `"cannot use operator[] with string"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read and written using the `[]` operator.,operatorarray__key_type} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @sa @ref value() for access by value with a default value @since version 1.0.0 */ reference operator[](const typename object_t::key_type& key) { // implicitly convert null value to an empty object if (is_null()) { m_type = value_t::object; m_value.object = create(); assert_invariant(); } // operator[] only works for objects if (is_object()) { return m_value.object->operator[](key); } JSON_THROW(std::domain_error("cannot use operator[] with " + type_name())); } /*! @brief read-only access specified object element Returns a const reference to the element at with specified key @a key. No bounds checking is performed. @warning If the element with key @a key does not exist, the behavior is undefined. @param[in] key key of the element to access @return const reference to the element at key @a key @pre The element with key @a key must exist. **This precondition is enforced with an assertion.** @throw std::domain_error if JSON is not an object; example: `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read using the `[]` operator.,operatorarray__key_type_const} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @sa @ref value() for access by value with a default value @since version 1.0.0 */ const_reference operator[](const typename object_t::key_type& key) const { // const operator[] only works for objects if (is_object()) { assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } JSON_THROW(std::domain_error("cannot use operator[] with " + type_name())); } /*! @brief access specified object element Returns a reference to the element at with specified key @a key. @note If @a key is not found in the object, then it is silently added to the object and filled with a `null` value to make `key` a valid reference. In case the value was `null` before, it is converted to an object. @param[in] key key of the element to access @return reference to the element at key @a key @throw std::domain_error if JSON is not an object or null; example: `"cannot use operator[] with string"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read and written using the `[]` operator.,operatorarray__key_type} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @sa @ref value() for access by value with a default value @since version 1.0.0 */ template reference operator[](T * (&key)[n]) { return operator[](static_cast(key)); } /*! @brief read-only access specified object element Returns a const reference to the element at with specified key @a key. No bounds checking is performed. @warning If the element with key @a key does not exist, the behavior is undefined. @note This function is required for compatibility reasons with Clang. @param[in] key key of the element to access @return const reference to the element at key @a key @throw std::domain_error if JSON is not an object; example: `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read using the `[]` operator.,operatorarray__key_type_const} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @sa @ref value() for access by value with a default value @since version 1.0.0 */ template const_reference operator[](T * (&key)[n]) const { return operator[](static_cast(key)); } /*! @brief access specified object element Returns a reference to the element at with specified key @a key. @note If @a key is not found in the object, then it is silently added to the object and filled with a `null` value to make `key` a valid reference. In case the value was `null` before, it is converted to an object. @param[in] key key of the element to access @return reference to the element at key @a key @throw std::domain_error if JSON is not an object or null; example: `"cannot use operator[] with string"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read and written using the `[]` operator.,operatorarray__key_type} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @sa @ref value() for access by value with a default value @since version 1.1.0 */ template reference operator[](T* key) { // implicitly convert null to object if (is_null()) { m_type = value_t::object; m_value = value_t::object; assert_invariant(); } // at only works for objects if (is_object()) { return m_value.object->operator[](key); } JSON_THROW(std::domain_error("cannot use operator[] with " + type_name())); } /*! @brief read-only access specified object element Returns a const reference to the element at with specified key @a key. No bounds checking is performed. @warning If the element with key @a key does not exist, the behavior is undefined. @param[in] key key of the element to access @return const reference to the element at key @a key @pre The element with key @a key must exist. **This precondition is enforced with an assertion.** @throw std::domain_error if JSON is not an object; example: `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be read using the `[]` operator.,operatorarray__key_type_const} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @sa @ref value() for access by value with a default value @since version 1.1.0 */ template const_reference operator[](T* key) const { // at only works for objects if (is_object()) { assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } JSON_THROW(std::domain_error("cannot use operator[] with " + type_name())); } /*! @brief access specified object element with default value Returns either a copy of an object's element at the specified key @a key or a given default value if no element with key @a key exists. The function is basically equivalent to executing @code {.cpp} try { return at(key); } catch(std::out_of_range) { return default_value; } @endcode @note Unlike @ref at(const typename object_t::key_type&), this function does not throw if the given key @a key was not found. @note Unlike @ref operator[](const typename object_t::key_type& key), this function does not implicitly add an element to the position defined by @a key. This function is furthermore also applicable to const objects. @param[in] key key of the element to access @param[in] default_value the value to return if @a key is not found @tparam ValueType type compatible to JSON values, for instance `int` for JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for JSON arrays. Note the type of the expected value at @a key and the default value @a default_value must be compatible. @return copy of the element at key @a key or @a default_value if @a key is not found @throw std::domain_error if JSON is not an object; example: `"cannot use value() with null"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be queried with a default value.,basic_json__value} @sa @ref at(const typename object_t::key_type&) for access by reference with range checking @sa @ref operator[](const typename object_t::key_type&) for unchecked access by reference @since version 1.0.0 */ template::value, int>::type = 0> ValueType value(const typename object_t::key_type& key, ValueType default_value) const { // at only works for objects if (is_object()) { // if key is found, return value and given default value otherwise const auto it = find(key); if (it != end()) { return *it; } return default_value; } else { JSON_THROW(std::domain_error("cannot use value() with " + type_name())); } } /*! @brief overload for a default value of type const char* @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const */ string_t value(const typename object_t::key_type& key, const char* default_value) const { return value(key, string_t(default_value)); } /*! @brief access specified object element via JSON Pointer with default value Returns either a copy of an object's element at the specified key @a key or a given default value if no element with key @a key exists. The function is basically equivalent to executing @code {.cpp} try { return at(ptr); } catch(std::out_of_range) { return default_value; } @endcode @note Unlike @ref at(const json_pointer&), this function does not throw if the given key @a key was not found. @param[in] ptr a JSON pointer to the element to access @param[in] default_value the value to return if @a ptr found no value @tparam ValueType type compatible to JSON values, for instance `int` for JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for JSON arrays. Note the type of the expected value at @a key and the default value @a default_value must be compatible. @return copy of the element at key @a key or @a default_value if @a key is not found @throw std::domain_error if JSON is not an object; example: `"cannot use value() with null"` @complexity Logarithmic in the size of the container. @liveexample{The example below shows how object elements can be queried with a default value.,basic_json__value_ptr} @sa @ref operator[](const json_pointer&) for unchecked access by reference @since version 2.0.2 */ template::value, int>::type = 0> ValueType value(const json_pointer& ptr, ValueType default_value) const { // at only works for objects if (is_object()) { // if pointer resolves a value, return it or use default value JSON_TRY { return ptr.get_checked(this); } JSON_CATCH (std::out_of_range&) { return default_value; } } JSON_THROW(std::domain_error("cannot use value() with " + type_name())); } /*! @brief overload for a default value of type const char* @copydoc basic_json::value(const json_pointer&, ValueType) const */ string_t value(const json_pointer& ptr, const char* default_value) const { return value(ptr, string_t(default_value)); } /*! @brief access the first element Returns a reference to the first element in the container. For a JSON container `c`, the expression `c.front()` is equivalent to `*c.begin()`. @return In case of a structured type (array or object), a reference to the first element is returned. In case of number, string, or boolean values, a reference to the value is returned. @complexity Constant. @pre The JSON value must not be `null` (would throw `std::out_of_range`) or an empty array or object (undefined behavior, **guarded by assertions**). @post The JSON value remains unchanged. @throw std::out_of_range when called on `null` value @liveexample{The following code shows an example for `front()`.,front} @sa @ref back() -- access the last element @since version 1.0.0 */ reference front() { return *begin(); } /*! @copydoc basic_json::front() */ const_reference front() const { return *cbegin(); } /*! @brief access the last element Returns a reference to the last element in the container. For a JSON container `c`, the expression `c.back()` is equivalent to @code {.cpp} auto tmp = c.end(); --tmp; return *tmp; @endcode @return In case of a structured type (array or object), a reference to the last element is returned. In case of number, string, or boolean values, a reference to the value is returned. @complexity Constant. @pre The JSON value must not be `null` (would throw `std::out_of_range`) or an empty array or object (undefined behavior, **guarded by assertions**). @post The JSON value remains unchanged. @throw std::out_of_range when called on `null` value. @liveexample{The following code shows an example for `back()`.,back} @sa @ref front() -- access the first element @since version 1.0.0 */ reference back() { auto tmp = end(); --tmp; return *tmp; } /*! @copydoc basic_json::back() */ const_reference back() const { auto tmp = cend(); --tmp; return *tmp; } /*! @brief remove element given an iterator Removes the element specified by iterator @a pos. The iterator @a pos must be valid and dereferenceable. Thus the `end()` iterator (which is valid, but is not dereferenceable) cannot be used as a value for @a pos. If called on a primitive type other than `null`, the resulting JSON value will be `null`. @param[in] pos iterator to the element to remove @return Iterator following the last removed element. If the iterator @a pos refers to the last element, the `end()` iterator is returned. @tparam IteratorType an @ref iterator or @ref const_iterator @post Invalidates iterators and references at or after the point of the erase, including the `end()` iterator. @throw std::domain_error if called on a `null` value; example: `"cannot use erase() with null"` @throw std::domain_error if called on an iterator which does not belong to the current JSON value; example: `"iterator does not fit current value"` @throw std::out_of_range if called on a primitive type with invalid iterator (i.e., any iterator which is not `begin()`); example: `"iterator out of range"` @complexity The complexity depends on the type: - objects: amortized constant - arrays: linear in distance between @a pos and the end of the container - strings: linear in the length of the string - other types: constant @liveexample{The example shows the result of `erase()` for different JSON types.,erase__IteratorType} @sa @ref erase(IteratorType, IteratorType) -- removes the elements in the given range @sa @ref erase(const typename object_t::key_type&) -- removes the element from an object at the given key @sa @ref erase(const size_type) -- removes the element from an array at the given index @since version 1.0.0 */ template::value or std::is_same::value, int>::type = 0> IteratorType erase(IteratorType pos) { // make sure iterator fits the current value if (this != pos.m_object) { JSON_THROW(std::domain_error("iterator does not fit current value")); } IteratorType result = end(); switch (m_type) { case value_t::boolean: case value_t::number_float: case value_t::number_integer: case value_t::number_unsigned: case value_t::string: { if (not pos.m_it.primitive_iterator.is_begin()) { JSON_THROW(std::out_of_range("iterator out of range")); } if (is_string()) { AllocatorType alloc; alloc.destroy(m_value.string); alloc.deallocate(m_value.string, 1); m_value.string = nullptr; } m_type = value_t::null; assert_invariant(); break; } case value_t::object: { result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); break; } case value_t::array: { result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); break; } default: { JSON_THROW(std::domain_error("cannot use erase() with " + type_name())); } } return result; } /*! @brief remove elements given an iterator range Removes the element specified by the range `[first; last)`. The iterator @a first does not need to be dereferenceable if `first == last`: erasing an empty range is a no-op. If called on a primitive type other than `null`, the resulting JSON value will be `null`. @param[in] first iterator to the beginning of the range to remove @param[in] last iterator past the end of the range to remove @return Iterator following the last removed element. If the iterator @a second refers to the last element, the `end()` iterator is returned. @tparam IteratorType an @ref iterator or @ref const_iterator @post Invalidates iterators and references at or after the point of the erase, including the `end()` iterator. @throw std::domain_error if called on a `null` value; example: `"cannot use erase() with null"` @throw std::domain_error if called on iterators which does not belong to the current JSON value; example: `"iterators do not fit current value"` @throw std::out_of_range if called on a primitive type with invalid iterators (i.e., if `first != begin()` and `last != end()`); example: `"iterators out of range"` @complexity The complexity depends on the type: - objects: `log(size()) + std::distance(first, last)` - arrays: linear in the distance between @a first and @a last, plus linear in the distance between @a last and end of the container - strings: linear in the length of the string - other types: constant @liveexample{The example shows the result of `erase()` for different JSON types.,erase__IteratorType_IteratorType} @sa @ref erase(IteratorType) -- removes the element at a given position @sa @ref erase(const typename object_t::key_type&) -- removes the element from an object at the given key @sa @ref erase(const size_type) -- removes the element from an array at the given index @since version 1.0.0 */ template::value or std::is_same::value, int>::type = 0> IteratorType erase(IteratorType first, IteratorType last) { // make sure iterator fits the current value if (this != first.m_object or this != last.m_object) { JSON_THROW(std::domain_error("iterators do not fit current value")); } IteratorType result = end(); switch (m_type) { case value_t::boolean: case value_t::number_float: case value_t::number_integer: case value_t::number_unsigned: case value_t::string: { if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) { JSON_THROW(std::out_of_range("iterators out of range")); } if (is_string()) { AllocatorType alloc; alloc.destroy(m_value.string); alloc.deallocate(m_value.string, 1); m_value.string = nullptr; } m_type = value_t::null; assert_invariant(); break; } case value_t::object: { result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator); break; } case value_t::array: { result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator); break; } default: { JSON_THROW(std::domain_error("cannot use erase() with " + type_name())); } } return result; } /*! @brief remove element from a JSON object given a key Removes elements from a JSON object with the key value @a key. @param[in] key value of the elements to remove @return Number of elements removed. If @a ObjectType is the default `std::map` type, the return value will always be `0` (@a key was not found) or `1` (@a key was found). @post References and iterators to the erased elements are invalidated. Other references and iterators are not affected. @throw std::domain_error when called on a type other than JSON object; example: `"cannot use erase() with null"` @complexity `log(size()) + count(key)` @liveexample{The example shows the effect of `erase()`.,erase__key_type} @sa @ref erase(IteratorType) -- removes the element at a given position @sa @ref erase(IteratorType, IteratorType) -- removes the elements in the given range @sa @ref erase(const size_type) -- removes the element from an array at the given index @since version 1.0.0 */ size_type erase(const typename object_t::key_type& key) { // this erase only works for objects if (is_object()) { return m_value.object->erase(key); } JSON_THROW(std::domain_error("cannot use erase() with " + type_name())); } /*! @brief remove element from a JSON array given an index Removes element from a JSON array at the index @a idx. @param[in] idx index of the element to remove @throw std::domain_error when called on a type other than JSON array; example: `"cannot use erase() with null"` @throw std::out_of_range when `idx >= size()`; example: `"array index 17 is out of range"` @complexity Linear in distance between @a idx and the end of the container. @liveexample{The example shows the effect of `erase()`.,erase__size_type} @sa @ref erase(IteratorType) -- removes the element at a given position @sa @ref erase(IteratorType, IteratorType) -- removes the elements in the given range @sa @ref erase(const typename object_t::key_type&) -- removes the element from an object at the given key @since version 1.0.0 */ void erase(const size_type idx) { // this erase only works for arrays if (is_array()) { if (idx >= size()) { JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range")); } m_value.array->erase(m_value.array->begin() + static_cast(idx)); } else { JSON_THROW(std::domain_error("cannot use erase() with " + type_name())); } } /// @} //////////// // lookup // //////////// /// @name lookup /// @{ /*! @brief find an element in a JSON object Finds an element in a JSON object with key equivalent to @a key. If the element is not found or the JSON value is not an object, end() is returned. @note This method always returns @ref end() when executed on a JSON type that is not an object. @param[in] key key value of the element to search for @return Iterator to an element with key equivalent to @a key. If no such element is found or the JSON value is not an object, past-the-end (see @ref end()) iterator is returned. @complexity Logarithmic in the size of the JSON object. @liveexample{The example shows how `find()` is used.,find__key_type} @since version 1.0.0 */ iterator find(typename object_t::key_type key) { auto result = end(); if (is_object()) { result.m_it.object_iterator = m_value.object->find(key); } return result; } /*! @brief find an element in a JSON object @copydoc find(typename object_t::key_type) */ const_iterator find(typename object_t::key_type key) const { auto result = cend(); if (is_object()) { result.m_it.object_iterator = m_value.object->find(key); } return result; } /*! @brief returns the number of occurrences of a key in a JSON object Returns the number of elements with key @a key. If ObjectType is the default `std::map` type, the return value will always be `0` (@a key was not found) or `1` (@a key was found). @note This method always returns `0` when executed on a JSON type that is not an object. @param[in] key key value of the element to count @return Number of elements with key @a key. If the JSON value is not an object, the return value will be `0`. @complexity Logarithmic in the size of the JSON object. @liveexample{The example shows how `count()` is used.,count} @since version 1.0.0 */ size_type count(typename object_t::key_type key) const { // return 0 for all nonobject types return is_object() ? m_value.object->count(key) : 0; } /// @} /////////////// // iterators // /////////////// /// @name iterators /// @{ /*! @brief returns an iterator to the first element Returns an iterator to the first element. @image html range-begin-end.svg "Illustration from cppreference.com" @return iterator to the first element @complexity Constant. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is constant. @liveexample{The following code shows an example for `begin()`.,begin} @sa @ref cbegin() -- returns a const iterator to the beginning @sa @ref end() -- returns an iterator to the end @sa @ref cend() -- returns a const iterator to the end @since version 1.0.0 */ iterator begin() noexcept { iterator result(this); result.set_begin(); return result; } /*! @copydoc basic_json::cbegin() */ const_iterator begin() const noexcept { return cbegin(); } /*! @brief returns a const iterator to the first element Returns a const iterator to the first element. @image html range-begin-end.svg "Illustration from cppreference.com" @return const iterator to the first element @complexity Constant. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is constant. - Has the semantics of `const_cast(*this).begin()`. @liveexample{The following code shows an example for `cbegin()`.,cbegin} @sa @ref begin() -- returns an iterator to the beginning @sa @ref end() -- returns an iterator to the end @sa @ref cend() -- returns a const iterator to the end @since version 1.0.0 */ const_iterator cbegin() const noexcept { const_iterator result(this); result.set_begin(); return result; } /*! @brief returns an iterator to one past the last element Returns an iterator to one past the last element. @image html range-begin-end.svg "Illustration from cppreference.com" @return iterator one past the last element @complexity Constant. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is constant. @liveexample{The following code shows an example for `end()`.,end} @sa @ref cend() -- returns a const iterator to the end @sa @ref begin() -- returns an iterator to the beginning @sa @ref cbegin() -- returns a const iterator to the beginning @since version 1.0.0 */ iterator end() noexcept { iterator result(this); result.set_end(); return result; } /*! @copydoc basic_json::cend() */ const_iterator end() const noexcept { return cend(); } /*! @brief returns a const iterator to one past the last element Returns a const iterator to one past the last element. @image html range-begin-end.svg "Illustration from cppreference.com" @return const iterator one past the last element @complexity Constant. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is constant. - Has the semantics of `const_cast(*this).end()`. @liveexample{The following code shows an example for `cend()`.,cend} @sa @ref end() -- returns an iterator to the end @sa @ref begin() -- returns an iterator to the beginning @sa @ref cbegin() -- returns a const iterator to the beginning @since version 1.0.0 */ const_iterator cend() const noexcept { const_iterator result(this); result.set_end(); return result; } /*! @brief returns an iterator to the reverse-beginning Returns an iterator to the reverse-beginning; that is, the last element. @image html range-rbegin-rend.svg "Illustration from cppreference.com" @complexity Constant. @requirement This function helps `basic_json` satisfying the [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) requirements: - The complexity is constant. - Has the semantics of `reverse_iterator(end())`. @liveexample{The following code shows an example for `rbegin()`.,rbegin} @sa @ref crbegin() -- returns a const reverse iterator to the beginning @sa @ref rend() -- returns a reverse iterator to the end @sa @ref crend() -- returns a const reverse iterator to the end @since version 1.0.0 */ reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } /*! @copydoc basic_json::crbegin() */ const_reverse_iterator rbegin() const noexcept { return crbegin(); } /*! @brief returns an iterator to the reverse-end Returns an iterator to the reverse-end; that is, one before the first element. @image html range-rbegin-rend.svg "Illustration from cppreference.com" @complexity Constant. @requirement This function helps `basic_json` satisfying the [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) requirements: - The complexity is constant. - Has the semantics of `reverse_iterator(begin())`. @liveexample{The following code shows an example for `rend()`.,rend} @sa @ref crend() -- returns a const reverse iterator to the end @sa @ref rbegin() -- returns a reverse iterator to the beginning @sa @ref crbegin() -- returns a const reverse iterator to the beginning @since version 1.0.0 */ reverse_iterator rend() noexcept { return reverse_iterator(begin()); } /*! @copydoc basic_json::crend() */ const_reverse_iterator rend() const noexcept { return crend(); } /*! @brief returns a const reverse iterator to the last element Returns a const iterator to the reverse-beginning; that is, the last element. @image html range-rbegin-rend.svg "Illustration from cppreference.com" @complexity Constant. @requirement This function helps `basic_json` satisfying the [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) requirements: - The complexity is constant. - Has the semantics of `const_cast(*this).rbegin()`. @liveexample{The following code shows an example for `crbegin()`.,crbegin} @sa @ref rbegin() -- returns a reverse iterator to the beginning @sa @ref rend() -- returns a reverse iterator to the end @sa @ref crend() -- returns a const reverse iterator to the end @since version 1.0.0 */ const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); } /*! @brief returns a const reverse iterator to one before the first Returns a const reverse iterator to the reverse-end; that is, one before the first element. @image html range-rbegin-rend.svg "Illustration from cppreference.com" @complexity Constant. @requirement This function helps `basic_json` satisfying the [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) requirements: - The complexity is constant. - Has the semantics of `const_cast(*this).rend()`. @liveexample{The following code shows an example for `crend()`.,crend} @sa @ref rend() -- returns a reverse iterator to the end @sa @ref rbegin() -- returns a reverse iterator to the beginning @sa @ref crbegin() -- returns a const reverse iterator to the beginning @since version 1.0.0 */ const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); } private: // forward declaration template class iteration_proxy; public: /*! @brief wrapper to access iterator member functions in range-based for This function allows to access @ref iterator::key() and @ref iterator::value() during range-based for loops. In these loops, a reference to the JSON values is returned, so there is no access to the underlying iterator. @note The name of this function is not yet final and may change in the future. */ static iteration_proxy iterator_wrapper(reference cont) { return iteration_proxy(cont); } /*! @copydoc iterator_wrapper(reference) */ static iteration_proxy iterator_wrapper(const_reference cont) { return iteration_proxy(cont); } /// @} ////////////// // capacity // ////////////// /// @name capacity /// @{ /*! @brief checks whether the container is empty Checks if a JSON value has no elements. @return The return value depends on the different types and is defined as follows: Value type | return value ----------- | ------------- null | `true` boolean | `false` string | `false` number | `false` object | result of function `object_t::empty()` array | result of function `array_t::empty()` @note This function does not return whether a string stored as JSON value is empty - it returns whether the JSON container itself is empty which is false in the case of a string. @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their `empty()` functions have constant complexity. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is constant. - Has the semantics of `begin() == end()`. @liveexample{The following code uses `empty()` to check if a JSON object contains any elements.,empty} @sa @ref size() -- returns the number of elements @since version 1.0.0 */ bool empty() const noexcept { switch (m_type) { case value_t::null: { // null values are empty return true; } case value_t::array: { // delegate call to array_t::empty() return m_value.array->empty(); } case value_t::object: { // delegate call to object_t::empty() return m_value.object->empty(); } default: { // all other types are nonempty return false; } } } /*! @brief returns the number of elements Returns the number of elements in a JSON value. @return The return value depends on the different types and is defined as follows: Value type | return value ----------- | ------------- null | `0` boolean | `1` string | `1` number | `1` object | result of function object_t::size() array | result of function array_t::size() @note This function does not return the length of a string stored as JSON value - it returns the number of elements in the JSON value which is 1 in the case of a string. @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their size() functions have constant complexity. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is constant. - Has the semantics of `std::distance(begin(), end())`. @liveexample{The following code calls `size()` on the different value types.,size} @sa @ref empty() -- checks whether the container is empty @sa @ref max_size() -- returns the maximal number of elements @since version 1.0.0 */ size_type size() const noexcept { switch (m_type) { case value_t::null: { // null values are empty return 0; } case value_t::array: { // delegate call to array_t::size() return m_value.array->size(); } case value_t::object: { // delegate call to object_t::size() return m_value.object->size(); } default: { // all other types have size 1 return 1; } } } /*! @brief returns the maximum possible number of elements Returns the maximum number of elements a JSON value is able to hold due to system or library implementation limitations, i.e. `std::distance(begin(), end())` for the JSON value. @return The return value depends on the different types and is defined as follows: Value type | return value ----------- | ------------- null | `0` (same as `size()`) boolean | `1` (same as `size()`) string | `1` (same as `size()`) number | `1` (same as `size()`) object | result of function `object_t::max_size()` array | result of function `array_t::max_size()` @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their `max_size()` functions have constant complexity. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is constant. - Has the semantics of returning `b.size()` where `b` is the largest possible JSON value. @liveexample{The following code calls `max_size()` on the different value types. Note the output is implementation specific.,max_size} @sa @ref size() -- returns the number of elements @since version 1.0.0 */ size_type max_size() const noexcept { switch (m_type) { case value_t::array: { // delegate call to array_t::max_size() return m_value.array->max_size(); } case value_t::object: { // delegate call to object_t::max_size() return m_value.object->max_size(); } default: { // all other types have max_size() == size() return size(); } } } /// @} /////////////// // modifiers // /////////////// /// @name modifiers /// @{ /*! @brief clears the contents Clears the content of a JSON value and resets it to the default value as if @ref basic_json(value_t) would have been called: Value type | initial value ----------- | ------------- null | `null` boolean | `false` string | `""` number | `0` object | `{}` array | `[]` @complexity Linear in the size of the JSON value. @liveexample{The example below shows the effect of `clear()` to different JSON types.,clear} @since version 1.0.0 */ void clear() noexcept { switch (m_type) { case value_t::number_integer: { m_value.number_integer = 0; break; } case value_t::number_unsigned: { m_value.number_unsigned = 0; break; } case value_t::number_float: { m_value.number_float = 0.0; break; } case value_t::boolean: { m_value.boolean = false; break; } case value_t::string: { m_value.string->clear(); break; } case value_t::array: { m_value.array->clear(); break; } case value_t::object: { m_value.object->clear(); break; } default: { break; } } } /*! @brief add an object to an array Appends the given element @a val to the end of the JSON value. If the function is called on a JSON null value, an empty array is created before appending @a val. @param[in] val the value to add to the JSON array @throw std::domain_error when called on a type other than JSON array or null; example: `"cannot use push_back() with number"` @complexity Amortized constant. @liveexample{The example shows how `push_back()` and `+=` can be used to add elements to a JSON array. Note how the `null` value was silently converted to a JSON array.,push_back} @since version 1.0.0 */ void push_back(basic_json&& val) { // push_back only works for null objects or arrays if (not(is_null() or is_array())) { JSON_THROW(std::domain_error("cannot use push_back() with " + type_name())); } // transform null object into an array if (is_null()) { m_type = value_t::array; m_value = value_t::array; assert_invariant(); } // add element to array (move semantics) m_value.array->push_back(std::move(val)); // invalidate object val.m_type = value_t::null; } /*! @brief add an object to an array @copydoc push_back(basic_json&&) */ reference operator+=(basic_json&& val) { push_back(std::move(val)); return *this; } /*! @brief add an object to an array @copydoc push_back(basic_json&&) */ void push_back(const basic_json& val) { // push_back only works for null objects or arrays if (not(is_null() or is_array())) { JSON_THROW(std::domain_error("cannot use push_back() with " + type_name())); } // transform null object into an array if (is_null()) { m_type = value_t::array; m_value = value_t::array; assert_invariant(); } // add element to array m_value.array->push_back(val); } /*! @brief add an object to an array @copydoc push_back(basic_json&&) */ reference operator+=(const basic_json& val) { push_back(val); return *this; } /*! @brief add an object to an object Inserts the given element @a val to the JSON object. If the function is called on a JSON null value, an empty object is created before inserting @a val. @param[in] val the value to add to the JSON object @throw std::domain_error when called on a type other than JSON object or null; example: `"cannot use push_back() with number"` @complexity Logarithmic in the size of the container, O(log(`size()`)). @liveexample{The example shows how `push_back()` and `+=` can be used to add elements to a JSON object. Note how the `null` value was silently converted to a JSON object.,push_back__object_t__value} @since version 1.0.0 */ void push_back(const typename object_t::value_type& val) { // push_back only works for null objects or objects if (not(is_null() or is_object())) { JSON_THROW(std::domain_error("cannot use push_back() with " + type_name())); } // transform null object into an object if (is_null()) { m_type = value_t::object; m_value = value_t::object; assert_invariant(); } // add element to array m_value.object->insert(val); } /*! @brief add an object to an object @copydoc push_back(const typename object_t::value_type&) */ reference operator+=(const typename object_t::value_type& val) { push_back(val); return *this; } /*! @brief add an object to an object This function allows to use `push_back` with an initializer list. In case 1. the current value is an object, 2. the initializer list @a init contains only two elements, and 3. the first element of @a init is a string, @a init is converted into an object element and added using @ref push_back(const typename object_t::value_type&). Otherwise, @a init is converted to a JSON value and added using @ref push_back(basic_json&&). @param init an initializer list @complexity Linear in the size of the initializer list @a init. @note This function is required to resolve an ambiguous overload error, because pairs like `{"key", "value"}` can be both interpreted as `object_t::value_type` or `std::initializer_list`, see https://github.com/nlohmann/json/issues/235 for more information. @liveexample{The example shows how initializer lists are treated as objects when possible.,push_back__initializer_list} */ void push_back(std::initializer_list init) { if (is_object() and init.size() == 2 and init.begin()->is_string()) { const string_t key = *init.begin(); push_back(typename object_t::value_type(key, *(init.begin() + 1))); } else { push_back(basic_json(init)); } } /*! @brief add an object to an object @copydoc push_back(std::initializer_list) */ reference operator+=(std::initializer_list init) { push_back(init); return *this; } /*! @brief add an object to an array Creates a JSON value from the passed parameters @a args to the end of the JSON value. If the function is called on a JSON null value, an empty array is created before appending the value created from @a args. @param[in] args arguments to forward to a constructor of @ref basic_json @tparam Args compatible types to create a @ref basic_json object @throw std::domain_error when called on a type other than JSON array or null; example: `"cannot use emplace_back() with number"` @complexity Amortized constant. @liveexample{The example shows how `push_back()` can be used to add elements to a JSON array. Note how the `null` value was silently converted to a JSON array.,emplace_back} @since version 2.0.8 */ template void emplace_back(Args&& ... args) { // emplace_back only works for null objects or arrays if (not(is_null() or is_array())) { JSON_THROW(std::domain_error("cannot use emplace_back() with " + type_name())); } // transform null object into an array if (is_null()) { m_type = value_t::array; m_value = value_t::array; assert_invariant(); } // add element to array (perfect forwarding) m_value.array->emplace_back(std::forward(args)...); } /*! @brief add an object to an object if key does not exist Inserts a new element into a JSON object constructed in-place with the given @a args if there is no element with the key in the container. If the function is called on a JSON null value, an empty object is created before appending the value created from @a args. @param[in] args arguments to forward to a constructor of @ref basic_json @tparam Args compatible types to create a @ref basic_json object @return a pair consisting of an iterator to the inserted element, or the already-existing element if no insertion happened, and a bool denoting whether the insertion took place. @throw std::domain_error when called on a type other than JSON object or null; example: `"cannot use emplace() with number"` @complexity Logarithmic in the size of the container, O(log(`size()`)). @liveexample{The example shows how `emplace()` can be used to add elements to a JSON object. Note how the `null` value was silently converted to a JSON object. Further note how no value is added if there was already one value stored with the same key.,emplace} @since version 2.0.8 */ template std::pair emplace(Args&& ... args) { // emplace only works for null objects or arrays if (not(is_null() or is_object())) { JSON_THROW(std::domain_error("cannot use emplace() with " + type_name())); } // transform null object into an object if (is_null()) { m_type = value_t::object; m_value = value_t::object; assert_invariant(); } // add element to array (perfect forwarding) auto res = m_value.object->emplace(std::forward(args)...); // create result iterator and set iterator to the result of emplace auto it = begin(); it.m_it.object_iterator = res.first; // return pair of iterator and boolean return {it, res.second}; } /*! @brief inserts element Inserts element @a val before iterator @a pos. @param[in] pos iterator before which the content will be inserted; may be the end() iterator @param[in] val element to insert @return iterator pointing to the inserted @a val. @throw std::domain_error if called on JSON values other than arrays; example: `"cannot use insert() with string"` @throw std::domain_error if @a pos is not an iterator of *this; example: `"iterator does not fit current value"` @complexity Constant plus linear in the distance between @a pos and end of the container. @liveexample{The example shows how `insert()` is used.,insert} @since version 1.0.0 */ iterator insert(const_iterator pos, const basic_json& val) { // insert only works for arrays if (is_array()) { // check if iterator pos fits to this JSON value if (pos.m_object != this) { JSON_THROW(std::domain_error("iterator does not fit current value")); } // insert to array and return iterator iterator result(this); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); return result; } JSON_THROW(std::domain_error("cannot use insert() with " + type_name())); } /*! @brief inserts element @copydoc insert(const_iterator, const basic_json&) */ iterator insert(const_iterator pos, basic_json&& val) { return insert(pos, val); } /*! @brief inserts elements Inserts @a cnt copies of @a val before iterator @a pos. @param[in] pos iterator before which the content will be inserted; may be the end() iterator @param[in] cnt number of copies of @a val to insert @param[in] val element to insert @return iterator pointing to the first element inserted, or @a pos if `cnt==0` @throw std::domain_error if called on JSON values other than arrays; example: `"cannot use insert() with string"` @throw std::domain_error if @a pos is not an iterator of *this; example: `"iterator does not fit current value"` @complexity Linear in @a cnt plus linear in the distance between @a pos and end of the container. @liveexample{The example shows how `insert()` is used.,insert__count} @since version 1.0.0 */ iterator insert(const_iterator pos, size_type cnt, const basic_json& val) { // insert only works for arrays if (is_array()) { // check if iterator pos fits to this JSON value if (pos.m_object != this) { JSON_THROW(std::domain_error("iterator does not fit current value")); } // insert to array and return iterator iterator result(this); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); return result; } JSON_THROW(std::domain_error("cannot use insert() with " + type_name())); } /*! @brief inserts elements Inserts elements from range `[first, last)` before iterator @a pos. @param[in] pos iterator before which the content will be inserted; may be the end() iterator @param[in] first begin of the range of elements to insert @param[in] last end of the range of elements to insert @throw std::domain_error if called on JSON values other than arrays; example: `"cannot use insert() with string"` @throw std::domain_error if @a pos is not an iterator of *this; example: `"iterator does not fit current value"` @throw std::domain_error if @a first and @a last do not belong to the same JSON value; example: `"iterators do not fit"` @throw std::domain_error if @a first or @a last are iterators into container for which insert is called; example: `"passed iterators may not belong to container"` @return iterator pointing to the first element inserted, or @a pos if `first==last` @complexity Linear in `std::distance(first, last)` plus linear in the distance between @a pos and end of the container. @liveexample{The example shows how `insert()` is used.,insert__range} @since version 1.0.0 */ iterator insert(const_iterator pos, const_iterator first, const_iterator last) { // insert only works for arrays if (not is_array()) { JSON_THROW(std::domain_error("cannot use insert() with " + type_name())); } // check if iterator pos fits to this JSON value if (pos.m_object != this) { JSON_THROW(std::domain_error("iterator does not fit current value")); } // check if range iterators belong to the same JSON object if (first.m_object != last.m_object) { JSON_THROW(std::domain_error("iterators do not fit")); } if (first.m_object == this or last.m_object == this) { JSON_THROW(std::domain_error("passed iterators may not belong to container")); } // insert to array and return iterator iterator result(this); result.m_it.array_iterator = m_value.array->insert( pos.m_it.array_iterator, first.m_it.array_iterator, last.m_it.array_iterator); return result; } /*! @brief inserts elements Inserts elements from initializer list @a ilist before iterator @a pos. @param[in] pos iterator before which the content will be inserted; may be the end() iterator @param[in] ilist initializer list to insert the values from @throw std::domain_error if called on JSON values other than arrays; example: `"cannot use insert() with string"` @throw std::domain_error if @a pos is not an iterator of *this; example: `"iterator does not fit current value"` @return iterator pointing to the first element inserted, or @a pos if `ilist` is empty @complexity Linear in `ilist.size()` plus linear in the distance between @a pos and end of the container. @liveexample{The example shows how `insert()` is used.,insert__ilist} @since version 1.0.0 */ iterator insert(const_iterator pos, std::initializer_list ilist) { // insert only works for arrays if (not is_array()) { JSON_THROW(std::domain_error("cannot use insert() with " + type_name())); } // check if iterator pos fits to this JSON value if (pos.m_object != this) { JSON_THROW(std::domain_error("iterator does not fit current value")); } // insert to array and return iterator iterator result(this); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist); return result; } /*! @brief exchanges the values Exchanges the contents of the JSON value with those of @a other. Does not invoke any move, copy, or swap operations on individual elements. All iterators and references remain valid. The past-the-end iterator is invalidated. @param[in,out] other JSON value to exchange the contents with @complexity Constant. @liveexample{The example below shows how JSON values can be swapped with `swap()`.,swap__reference} @since version 1.0.0 */ void swap(reference other) noexcept ( std::is_nothrow_move_constructible::value and std::is_nothrow_move_assignable::value and std::is_nothrow_move_constructible::value and std::is_nothrow_move_assignable::value ) { std::swap(m_type, other.m_type); std::swap(m_value, other.m_value); assert_invariant(); } /*! @brief exchanges the values Exchanges the contents of a JSON array with those of @a other. Does not invoke any move, copy, or swap operations on individual elements. All iterators and references remain valid. The past-the-end iterator is invalidated. @param[in,out] other array to exchange the contents with @throw std::domain_error when JSON value is not an array; example: `"cannot use swap() with string"` @complexity Constant. @liveexample{The example below shows how arrays can be swapped with `swap()`.,swap__array_t} @since version 1.0.0 */ void swap(array_t& other) { // swap only works for arrays if (is_array()) { std::swap(*(m_value.array), other); } else { JSON_THROW(std::domain_error("cannot use swap() with " + type_name())); } } /*! @brief exchanges the values Exchanges the contents of a JSON object with those of @a other. Does not invoke any move, copy, or swap operations on individual elements. All iterators and references remain valid. The past-the-end iterator is invalidated. @param[in,out] other object to exchange the contents with @throw std::domain_error when JSON value is not an object; example: `"cannot use swap() with string"` @complexity Constant. @liveexample{The example below shows how objects can be swapped with `swap()`.,swap__object_t} @since version 1.0.0 */ void swap(object_t& other) { // swap only works for objects if (is_object()) { std::swap(*(m_value.object), other); } else { JSON_THROW(std::domain_error("cannot use swap() with " + type_name())); } } /*! @brief exchanges the values Exchanges the contents of a JSON string with those of @a other. Does not invoke any move, copy, or swap operations on individual elements. All iterators and references remain valid. The past-the-end iterator is invalidated. @param[in,out] other string to exchange the contents with @throw std::domain_error when JSON value is not a string; example: `"cannot use swap() with boolean"` @complexity Constant. @liveexample{The example below shows how strings can be swapped with `swap()`.,swap__string_t} @since version 1.0.0 */ void swap(string_t& other) { // swap only works for strings if (is_string()) { std::swap(*(m_value.string), other); } else { JSON_THROW(std::domain_error("cannot use swap() with " + type_name())); } } /// @} public: ////////////////////////////////////////// // lexicographical comparison operators // ////////////////////////////////////////// /// @name lexicographical comparison operators /// @{ /*! @brief comparison: equal Compares two JSON values for equality according to the following rules: - Two JSON values are equal if (1) they are from the same type and (2) their stored values are the same. - Integer and floating-point numbers are automatically converted before comparison. Floating-point numbers are compared indirectly: two floating-point numbers `f1` and `f2` are considered equal if neither `f1 > f2` nor `f2 > f1` holds. - Two JSON null values are equal. @param[in] lhs first JSON value to consider @param[in] rhs second JSON value to consider @return whether the values @a lhs and @a rhs are equal @complexity Linear. @liveexample{The example demonstrates comparing several JSON types.,operator__equal} @since version 1.0.0 */ friend bool operator==(const_reference lhs, const_reference rhs) noexcept { const auto lhs_type = lhs.type(); const auto rhs_type = rhs.type(); if (lhs_type == rhs_type) { switch (lhs_type) { case value_t::array: { return *lhs.m_value.array == *rhs.m_value.array; } case value_t::object: { return *lhs.m_value.object == *rhs.m_value.object; } case value_t::null: { return true; } case value_t::string: { return *lhs.m_value.string == *rhs.m_value.string; } case value_t::boolean: { return lhs.m_value.boolean == rhs.m_value.boolean; } case value_t::number_integer: { return lhs.m_value.number_integer == rhs.m_value.number_integer; } case value_t::number_unsigned: { return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; } case value_t::number_float: { return lhs.m_value.number_float == rhs.m_value.number_float; } default: { return false; } } } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) { return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; } else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) { return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); } else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) { return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; } else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) { return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); } else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) { return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) { return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); } return false; } /*! @brief comparison: equal @copydoc operator==(const_reference, const_reference) */ template::value, int>::type = 0> friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept { return (lhs == basic_json(rhs)); } /*! @brief comparison: equal @copydoc operator==(const_reference, const_reference) */ template::value, int>::type = 0> friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept { return (basic_json(lhs) == rhs); } /*! @brief comparison: not equal Compares two JSON values for inequality by calculating `not (lhs == rhs)`. @param[in] lhs first JSON value to consider @param[in] rhs second JSON value to consider @return whether the values @a lhs and @a rhs are not equal @complexity Linear. @liveexample{The example demonstrates comparing several JSON types.,operator__notequal} @since version 1.0.0 */ friend bool operator!=(const_reference lhs, const_reference rhs) noexcept { return not (lhs == rhs); } /*! @brief comparison: not equal @copydoc operator!=(const_reference, const_reference) */ template::value, int>::type = 0> friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept { return (lhs != basic_json(rhs)); } /*! @brief comparison: not equal @copydoc operator!=(const_reference, const_reference) */ template::value, int>::type = 0> friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept { return (basic_json(lhs) != rhs); } /*! @brief comparison: less than Compares whether one JSON value @a lhs is less than another JSON value @a rhs according to the following rules: - If @a lhs and @a rhs have the same type, the values are compared using the default `<` operator. - Integer and floating-point numbers are automatically converted before comparison - In case @a lhs and @a rhs have different types, the values are ignored and the order of the types is considered, see @ref operator<(const value_t, const value_t). @param[in] lhs first JSON value to consider @param[in] rhs second JSON value to consider @return whether @a lhs is less than @a rhs @complexity Linear. @liveexample{The example demonstrates comparing several JSON types.,operator__less} @since version 1.0.0 */ friend bool operator<(const_reference lhs, const_reference rhs) noexcept { const auto lhs_type = lhs.type(); const auto rhs_type = rhs.type(); if (lhs_type == rhs_type) { switch (lhs_type) { case value_t::array: { return *lhs.m_value.array < *rhs.m_value.array; } case value_t::object: { return *lhs.m_value.object < *rhs.m_value.object; } case value_t::null: { return false; } case value_t::string: { return *lhs.m_value.string < *rhs.m_value.string; } case value_t::boolean: { return lhs.m_value.boolean < rhs.m_value.boolean; } case value_t::number_integer: { return lhs.m_value.number_integer < rhs.m_value.number_integer; } case value_t::number_unsigned: { return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned; } case value_t::number_float: { return lhs.m_value.number_float < rhs.m_value.number_float; } default: { return false; } } } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) { return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; } else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) { return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); } else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) { return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; } else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) { return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) { return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); } else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) { return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; } // We only reach this line if we cannot compare values. In that case, // we compare types. Note we have to call the operator explicitly, // because MSVC has problems otherwise. return operator<(lhs_type, rhs_type); } /*! @brief comparison: less than or equal Compares whether one JSON value @a lhs is less than or equal to another JSON value by calculating `not (rhs < lhs)`. @param[in] lhs first JSON value to consider @param[in] rhs second JSON value to consider @return whether @a lhs is less than or equal to @a rhs @complexity Linear. @liveexample{The example demonstrates comparing several JSON types.,operator__greater} @since version 1.0.0 */ friend bool operator<=(const_reference lhs, const_reference rhs) noexcept { return not (rhs < lhs); } /*! @brief comparison: greater than Compares whether one JSON value @a lhs is greater than another JSON value by calculating `not (lhs <= rhs)`. @param[in] lhs first JSON value to consider @param[in] rhs second JSON value to consider @return whether @a lhs is greater than to @a rhs @complexity Linear. @liveexample{The example demonstrates comparing several JSON types.,operator__lessequal} @since version 1.0.0 */ friend bool operator>(const_reference lhs, const_reference rhs) noexcept { return not (lhs <= rhs); } /*! @brief comparison: greater than or equal Compares whether one JSON value @a lhs is greater than or equal to another JSON value by calculating `not (lhs < rhs)`. @param[in] lhs first JSON value to consider @param[in] rhs second JSON value to consider @return whether @a lhs is greater than or equal to @a rhs @complexity Linear. @liveexample{The example demonstrates comparing several JSON types.,operator__greaterequal} @since version 1.0.0 */ friend bool operator>=(const_reference lhs, const_reference rhs) noexcept { return not (lhs < rhs); } /// @} /////////////////// // serialization // /////////////////// /// @name serialization /// @{ /*! @brief serialize to stream Serialize the given JSON value @a j to the output stream @a o. The JSON value will be serialized using the @ref dump member function. The indentation of the output can be controlled with the member variable `width` of the output stream @a o. For instance, using the manipulator `std::setw(4)` on @a o sets the indentation level to `4` and the serialization result is the same as calling `dump(4)`. @param[in,out] o stream to serialize to @param[in] j JSON value to serialize @return the stream @a o @complexity Linear. @liveexample{The example below shows the serialization with different parameters to `width` to adjust the indentation level.,operator_serialize} @since version 1.0.0 */ friend std::ostream& operator<<(std::ostream& o, const basic_json& j) { // read width member and use it as indentation parameter if nonzero const bool pretty_print = (o.width() > 0); const auto indentation = (pretty_print ? o.width() : 0); // reset width to 0 for subsequent calls to this stream o.width(0); // do the actual serialization j.dump(o, pretty_print, static_cast(indentation)); return o; } /*! @brief serialize to stream @copydoc operator<<(std::ostream&, const basic_json&) */ friend std::ostream& operator>>(const basic_json& j, std::ostream& o) { return o << j; } /// @} ///////////////////// // deserialization // ///////////////////// /// @name deserialization /// @{ /*! @brief deserialize from an array This function reads from an array of 1-byte values. @pre Each element of the container has a size of 1 byte. Violating this precondition yields undefined behavior. **This precondition is enforced with a static assertion.** @param[in] array array to read from @param[in] cb a parser callback function of type @ref parser_callback_t which is used to control the deserialization by filtering unwanted values (optional) @return result of the deserialization @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @note A UTF-8 byte order mark is silently ignored. @liveexample{The example below demonstrates the `parse()` function reading from an array.,parse__array__parser_callback_t} @since version 2.0.3 */ template static basic_json parse(T (&array)[N], const parser_callback_t cb = nullptr) { // delegate the call to the iterator-range parse overload return parse(std::begin(array), std::end(array), cb); } /*! @brief deserialize from string literal @tparam CharT character/literal type with size of 1 byte @param[in] s string literal to read a serialized JSON value from @param[in] cb a parser callback function of type @ref parser_callback_t which is used to control the deserialization by filtering unwanted values (optional) @return result of the deserialization @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @note A UTF-8 byte order mark is silently ignored. @note String containers like `std::string` or @ref string_t can be parsed with @ref parse(const ContiguousContainer&, const parser_callback_t) @liveexample{The example below demonstrates the `parse()` function with and without callback function.,parse__string__parser_callback_t} @sa @ref parse(std::istream&, const parser_callback_t) for a version that reads from an input stream @since version 1.0.0 (originally for @ref string_t) */ template::value and std::is_integral::type>::value and sizeof(typename std::remove_pointer::type) == 1, int>::type = 0> static basic_json parse(const CharT s, const parser_callback_t cb = nullptr) { return parser(reinterpret_cast(s), cb).parse(); } /*! @brief deserialize from stream @param[in,out] i stream to read a serialized JSON value from @param[in] cb a parser callback function of type @ref parser_callback_t which is used to control the deserialization by filtering unwanted values (optional) @return result of the deserialization @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @note A UTF-8 byte order mark is silently ignored. @liveexample{The example below demonstrates the `parse()` function with and without callback function.,parse__istream__parser_callback_t} @sa @ref parse(const CharT, const parser_callback_t) for a version that reads from a string @since version 1.0.0 */ static basic_json parse(std::istream& i, const parser_callback_t cb = nullptr) { return parser(i, cb).parse(); } /*! @copydoc parse(std::istream&, const parser_callback_t) */ static basic_json parse(std::istream&& i, const parser_callback_t cb = nullptr) { return parser(i, cb).parse(); } /*! @brief deserialize from an iterator range with contiguous storage This function reads from an iterator range of a container with contiguous storage of 1-byte values. Compatible container types include `std::vector`, `std::string`, `std::array`, `std::valarray`, and `std::initializer_list`. Furthermore, C-style arrays can be used with `std::begin()`/`std::end()`. User-defined containers can be used as long as they implement random-access iterators and a contiguous storage. @pre The iterator range is contiguous. Violating this precondition yields undefined behavior. **This precondition is enforced with an assertion.** @pre Each element in the range has a size of 1 byte. Violating this precondition yields undefined behavior. **This precondition is enforced with a static assertion.** @warning There is no way to enforce all preconditions at compile-time. If the function is called with noncompliant iterators and with assertions switched off, the behavior is undefined and will most likely yield segmentation violation. @tparam IteratorType iterator of container with contiguous storage @param[in] first begin of the range to parse (included) @param[in] last end of the range to parse (excluded) @param[in] cb a parser callback function of type @ref parser_callback_t which is used to control the deserialization by filtering unwanted values (optional) @return result of the deserialization @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @note A UTF-8 byte order mark is silently ignored. @liveexample{The example below demonstrates the `parse()` function reading from an iterator range.,parse__iteratortype__parser_callback_t} @since version 2.0.3 */ template::iterator_category>::value, int>::type = 0> static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr) { // assertion to check that the iterator range is indeed contiguous, // see http://stackoverflow.com/a/35008842/266378 for more discussion assert(std::accumulate(first, last, std::pair(true, 0), [&first](std::pair res, decltype(*first) val) { res.first &= (val == *(std::next(std::addressof(*first), res.second++))); return res; }).first); // assertion to check that each element is 1 byte long static_assert(sizeof(typename std::iterator_traits::value_type) == 1, "each element in the iterator range must have the size of 1 byte"); // if iterator range is empty, create a parser with an empty string // to generate "unexpected EOF" error message if (std::distance(first, last) <= 0) { return parser("").parse(); } return parser(first, last, cb).parse(); } /*! @brief deserialize from a container with contiguous storage This function reads from a container with contiguous storage of 1-byte values. Compatible container types include `std::vector`, `std::string`, `std::array`, and `std::initializer_list`. User-defined containers can be used as long as they implement random-access iterators and a contiguous storage. @pre The container storage is contiguous. Violating this precondition yields undefined behavior. **This precondition is enforced with an assertion.** @pre Each element of the container has a size of 1 byte. Violating this precondition yields undefined behavior. **This precondition is enforced with a static assertion.** @warning There is no way to enforce all preconditions at compile-time. If the function is called with a noncompliant container and with assertions switched off, the behavior is undefined and will most likely yield segmentation violation. @tparam ContiguousContainer container type with contiguous storage @param[in] c container to read from @param[in] cb a parser callback function of type @ref parser_callback_t which is used to control the deserialization by filtering unwanted values (optional) @return result of the deserialization @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @note A UTF-8 byte order mark is silently ignored. @liveexample{The example below demonstrates the `parse()` function reading from a contiguous container.,parse__contiguouscontainer__parser_callback_t} @since version 2.0.3 */ template::value and std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits()))>::iterator_category>::value , int>::type = 0> static basic_json parse(const ContiguousContainer& c, const parser_callback_t cb = nullptr) { // delegate the call to the iterator-range parse overload return parse(std::begin(c), std::end(c), cb); } /*! @brief deserialize from stream Deserializes an input stream to a JSON value. @param[in,out] i input stream to read a serialized JSON value from @param[in,out] j JSON value to write the deserialized input to @throw std::invalid_argument in case of parse errors @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. @note A UTF-8 byte order mark is silently ignored. @liveexample{The example below shows how a JSON value is constructed by reading a serialization from a stream.,operator_deserialize} @sa parse(std::istream&, const parser_callback_t) for a variant with a parser callback function to filter values while parsing @since version 1.0.0 */ friend std::istream& operator<<(basic_json& j, std::istream& i) { j = parser(i).parse(); return i; } /*! @brief deserialize from stream @copydoc operator<<(basic_json&, std::istream&) */ friend std::istream& operator>>(std::istream& i, basic_json& j) { j = parser(i).parse(); return i; } /// @} ////////////////////////////////////////// // binary serialization/deserialization // ////////////////////////////////////////// /// @name binary serialization/deserialization support /// @{ private: /*! @note Some code in the switch cases has been copied, because otherwise copilers would complain about implicit fallthrough and there is no portable attribute to mute such warnings. */ template static void add_to_vector(std::vector& vec, size_t bytes, const T number) { assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8); switch (bytes) { case 8: { vec.push_back(static_cast((static_cast(number) >> 070) & 0xff)); vec.push_back(static_cast((static_cast(number) >> 060) & 0xff)); vec.push_back(static_cast((static_cast(number) >> 050) & 0xff)); vec.push_back(static_cast((static_cast(number) >> 040) & 0xff)); vec.push_back(static_cast((number >> 030) & 0xff)); vec.push_back(static_cast((number >> 020) & 0xff)); vec.push_back(static_cast((number >> 010) & 0xff)); vec.push_back(static_cast(number & 0xff)); break; } case 4: { vec.push_back(static_cast((number >> 030) & 0xff)); vec.push_back(static_cast((number >> 020) & 0xff)); vec.push_back(static_cast((number >> 010) & 0xff)); vec.push_back(static_cast(number & 0xff)); break; } case 2: { vec.push_back(static_cast((number >> 010) & 0xff)); vec.push_back(static_cast(number & 0xff)); break; } case 1: { vec.push_back(static_cast(number & 0xff)); break; } } } /*! @brief take sufficient bytes from a vector to fill an integer variable In the context of binary serialization formats, we need to read several bytes from a byte vector and combine them to multi-byte integral data types. @param[in] vec byte vector to read from @param[in] current_index the position in the vector after which to read @return the next sizeof(T) bytes from @a vec, in reverse order as T @tparam T the integral return type @throw std::out_of_range if there are less than sizeof(T)+1 bytes in the vector @a vec to read In the for loop, the bytes from the vector are copied in reverse order into the return value. In the figures below, let sizeof(T)=4 and `i` be the loop variable. Precondition: vec: | | | a | b | c | d | T: | | | | | ^ ^ ^ ^ current_index i ptr sizeof(T) Postcondition: vec: | | | a | b | c | d | T: | d | c | b | a | ^ ^ ^ | i ptr current_index @sa Code adapted from . */ template static T get_from_vector(const std::vector& vec, const size_t current_index) { if (current_index + sizeof(T) + 1 > vec.size()) { JSON_THROW(std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector")); } T result; auto* ptr = reinterpret_cast(&result); for (size_t i = 0; i < sizeof(T); ++i) { *ptr++ = vec[current_index + sizeof(T) - i]; } return result; } /*! @brief create a MessagePack serialization of a given JSON value This is a straightforward implementation of the MessagePack specification. @param[in] j JSON value to serialize @param[in,out] v byte vector to write the serialization to @sa https://github.com/msgpack/msgpack/blob/master/spec.md */ static void to_msgpack_internal(const basic_json& j, std::vector& v) { switch (j.type()) { case value_t::null: { // nil v.push_back(0xc0); break; } case value_t::boolean: { // true and false v.push_back(j.m_value.boolean ? 0xc3 : 0xc2); break; } case value_t::number_integer: { if (j.m_value.number_integer >= 0) { // MessagePack does not differentiate between positive // signed integers and unsigned integers. Therefore, we // used the code from the value_t::number_unsigned case // here. if (j.m_value.number_unsigned < 128) { // positive fixnum add_to_vector(v, 1, j.m_value.number_unsigned); } else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 8 v.push_back(0xcc); add_to_vector(v, 1, j.m_value.number_unsigned); } else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 16 v.push_back(0xcd); add_to_vector(v, 2, j.m_value.number_unsigned); } else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 32 v.push_back(0xce); add_to_vector(v, 4, j.m_value.number_unsigned); } else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 64 v.push_back(0xcf); add_to_vector(v, 8, j.m_value.number_unsigned); } } else { if (j.m_value.number_integer >= -32) { // negative fixnum add_to_vector(v, 1, j.m_value.number_integer); } else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) { // int 8 v.push_back(0xd0); add_to_vector(v, 1, j.m_value.number_integer); } else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) { // int 16 v.push_back(0xd1); add_to_vector(v, 2, j.m_value.number_integer); } else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) { // int 32 v.push_back(0xd2); add_to_vector(v, 4, j.m_value.number_integer); } else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) { // int 64 v.push_back(0xd3); add_to_vector(v, 8, j.m_value.number_integer); } } break; } case value_t::number_unsigned: { if (j.m_value.number_unsigned < 128) { // positive fixnum add_to_vector(v, 1, j.m_value.number_unsigned); } else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 8 v.push_back(0xcc); add_to_vector(v, 1, j.m_value.number_unsigned); } else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 16 v.push_back(0xcd); add_to_vector(v, 2, j.m_value.number_unsigned); } else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 32 v.push_back(0xce); add_to_vector(v, 4, j.m_value.number_unsigned); } else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 64 v.push_back(0xcf); add_to_vector(v, 8, j.m_value.number_unsigned); } break; } case value_t::number_float: { // float 64 v.push_back(0xcb); const auto* helper = reinterpret_cast(&(j.m_value.number_float)); for (size_t i = 0; i < 8; ++i) { v.push_back(helper[7 - i]); } break; } case value_t::string: { const auto N = j.m_value.string->size(); if (N <= 31) { // fixstr v.push_back(static_cast(0xa0 | N)); } else if (N <= 255) { // str 8 v.push_back(0xd9); add_to_vector(v, 1, N); } else if (N <= 65535) { // str 16 v.push_back(0xda); add_to_vector(v, 2, N); } else if (N <= 4294967295) { // str 32 v.push_back(0xdb); add_to_vector(v, 4, N); } // append string std::copy(j.m_value.string->begin(), j.m_value.string->end(), std::back_inserter(v)); break; } case value_t::array: { const auto N = j.m_value.array->size(); if (N <= 15) { // fixarray v.push_back(static_cast(0x90 | N)); } else if (N <= 0xffff) { // array 16 v.push_back(0xdc); add_to_vector(v, 2, N); } else if (N <= 0xffffffff) { // array 32 v.push_back(0xdd); add_to_vector(v, 4, N); } // append each element for (const auto& el : *j.m_value.array) { to_msgpack_internal(el, v); } break; } case value_t::object: { const auto N = j.m_value.object->size(); if (N <= 15) { // fixmap v.push_back(static_cast(0x80 | (N & 0xf))); } else if (N <= 65535) { // map 16 v.push_back(0xde); add_to_vector(v, 2, N); } else if (N <= 4294967295) { // map 32 v.push_back(0xdf); add_to_vector(v, 4, N); } // append each element for (const auto& el : *j.m_value.object) { to_msgpack_internal(el.first, v); to_msgpack_internal(el.second, v); } break; } default: { break; } } } /*! @brief create a CBOR serialization of a given JSON value This is a straightforward implementation of the CBOR specification. @param[in] j JSON value to serialize @param[in,out] v byte vector to write the serialization to @sa https://tools.ietf.org/html/rfc7049 */ static void to_cbor_internal(const basic_json& j, std::vector& v) { switch (j.type()) { case value_t::null: { v.push_back(0xf6); break; } case value_t::boolean: { v.push_back(j.m_value.boolean ? 0xf5 : 0xf4); break; } case value_t::number_integer: { if (j.m_value.number_integer >= 0) { // CBOR does not differentiate between positive signed // integers and unsigned integers. Therefore, we used the // code from the value_t::number_unsigned case here. if (j.m_value.number_integer <= 0x17) { add_to_vector(v, 1, j.m_value.number_integer); } else if (j.m_value.number_integer <= std::numeric_limits::max()) { v.push_back(0x18); // one-byte uint8_t add_to_vector(v, 1, j.m_value.number_integer); } else if (j.m_value.number_integer <= std::numeric_limits::max()) { v.push_back(0x19); // two-byte uint16_t add_to_vector(v, 2, j.m_value.number_integer); } else if (j.m_value.number_integer <= std::numeric_limits::max()) { v.push_back(0x1a); // four-byte uint32_t add_to_vector(v, 4, j.m_value.number_integer); } else { v.push_back(0x1b); // eight-byte uint64_t add_to_vector(v, 8, j.m_value.number_integer); } } else { // The conversions below encode the sign in the first // byte, and the value is converted to a positive number. const auto positive_number = -1 - j.m_value.number_integer; if (j.m_value.number_integer >= -24) { v.push_back(static_cast(0x20 + positive_number)); } else if (positive_number <= std::numeric_limits::max()) { // int 8 v.push_back(0x38); add_to_vector(v, 1, positive_number); } else if (positive_number <= std::numeric_limits::max()) { // int 16 v.push_back(0x39); add_to_vector(v, 2, positive_number); } else if (positive_number <= std::numeric_limits::max()) { // int 32 v.push_back(0x3a); add_to_vector(v, 4, positive_number); } else { // int 64 v.push_back(0x3b); add_to_vector(v, 8, positive_number); } } break; } case value_t::number_unsigned: { if (j.m_value.number_unsigned <= 0x17) { v.push_back(static_cast(j.m_value.number_unsigned)); } else if (j.m_value.number_unsigned <= 0xff) { v.push_back(0x18); // one-byte uint8_t add_to_vector(v, 1, j.m_value.number_unsigned); } else if (j.m_value.number_unsigned <= 0xffff) { v.push_back(0x19); // two-byte uint16_t add_to_vector(v, 2, j.m_value.number_unsigned); } else if (j.m_value.number_unsigned <= 0xffffffff) { v.push_back(0x1a); // four-byte uint32_t add_to_vector(v, 4, j.m_value.number_unsigned); } else if (j.m_value.number_unsigned <= 0xffffffffffffffff) { v.push_back(0x1b); // eight-byte uint64_t add_to_vector(v, 8, j.m_value.number_unsigned); } break; } case value_t::number_float: { // Double-Precision Float v.push_back(0xfb); const auto* helper = reinterpret_cast(&(j.m_value.number_float)); for (size_t i = 0; i < 8; ++i) { v.push_back(helper[7 - i]); } break; } case value_t::string: { const auto N = j.m_value.string->size(); if (N <= 0x17) { v.push_back(0x60 + static_cast(N)); // 1 byte for string + size } else if (N <= 0xff) { v.push_back(0x78); // one-byte uint8_t for N add_to_vector(v, 1, N); } else if (N <= 0xffff) { v.push_back(0x79); // two-byte uint16_t for N add_to_vector(v, 2, N); } else if (N <= 0xffffffff) { v.push_back(0x7a); // four-byte uint32_t for N add_to_vector(v, 4, N); } // LCOV_EXCL_START else if (N <= 0xffffffffffffffff) { v.push_back(0x7b); // eight-byte uint64_t for N add_to_vector(v, 8, N); } // LCOV_EXCL_STOP // append string std::copy(j.m_value.string->begin(), j.m_value.string->end(), std::back_inserter(v)); break; } case value_t::array: { const auto N = j.m_value.array->size(); if (N <= 0x17) { v.push_back(0x80 + static_cast(N)); // 1 byte for array + size } else if (N <= 0xff) { v.push_back(0x98); // one-byte uint8_t for N add_to_vector(v, 1, N); } else if (N <= 0xffff) { v.push_back(0x99); // two-byte uint16_t for N add_to_vector(v, 2, N); } else if (N <= 0xffffffff) { v.push_back(0x9a); // four-byte uint32_t for N add_to_vector(v, 4, N); } // LCOV_EXCL_START else if (N <= 0xffffffffffffffff) { v.push_back(0x9b); // eight-byte uint64_t for N add_to_vector(v, 8, N); } // LCOV_EXCL_STOP // append each element for (const auto& el : *j.m_value.array) { to_cbor_internal(el, v); } break; } case value_t::object: { const auto N = j.m_value.object->size(); if (N <= 0x17) { v.push_back(0xa0 + static_cast(N)); // 1 byte for object + size } else if (N <= 0xff) { v.push_back(0xb8); add_to_vector(v, 1, N); // one-byte uint8_t for N } else if (N <= 0xffff) { v.push_back(0xb9); add_to_vector(v, 2, N); // two-byte uint16_t for N } else if (N <= 0xffffffff) { v.push_back(0xba); add_to_vector(v, 4, N); // four-byte uint32_t for N } // LCOV_EXCL_START else if (N <= 0xffffffffffffffff) { v.push_back(0xbb); add_to_vector(v, 8, N); // eight-byte uint64_t for N } // LCOV_EXCL_STOP // append each element for (const auto& el : *j.m_value.object) { to_cbor_internal(el.first, v); to_cbor_internal(el.second, v); } break; } default: { break; } } } /* @brief checks if given lengths do not exceed the size of a given vector To secure the access to the byte vector during CBOR/MessagePack deserialization, bytes are copied from the vector into buffers. This function checks if the number of bytes to copy (@a len) does not exceed the size @s size of the vector. Additionally, an @a offset is given from where to start reading the bytes. This function checks whether reading the bytes is safe; that is, offset is a valid index in the vector, offset+len @param[in] size size of the byte vector @param[in] len number of bytes to read @param[in] offset offset where to start reading vec: x x x x x X X X X X ^ ^ ^ 0 offset len @throws out_of_range if `len > v.size()` */ static void check_length(const size_t size, const size_t len, const size_t offset) { // simple case: requested length is greater than the vector's length if (len > size or offset > size) { JSON_THROW(std::out_of_range("len out of range")); } // second case: adding offset would result in overflow if ((size > (std::numeric_limits::max() - offset))) { JSON_THROW(std::out_of_range("len+offset out of range")); } // last case: reading past the end of the vector if (len + offset > size) { JSON_THROW(std::out_of_range("len+offset out of range")); } } /*! @brief create a JSON value from a given MessagePack vector @param[in] v MessagePack serialization @param[in] idx byte index to start reading from @a v @return deserialized JSON value @throw std::invalid_argument if unsupported features from MessagePack were used in the given vector @a v or if the input is not valid MessagePack @throw std::out_of_range if the given vector ends prematurely @sa https://github.com/msgpack/msgpack/blob/master/spec.md */ static basic_json from_msgpack_internal(const std::vector& v, size_t& idx) { // make sure reading 1 byte is safe check_length(v.size(), 1, idx); // store and increment index const size_t current_idx = idx++; if (v[current_idx] <= 0xbf) { if (v[current_idx] <= 0x7f) // positive fixint { return v[current_idx]; } if (v[current_idx] <= 0x8f) // fixmap { basic_json result = value_t::object; const size_t len = v[current_idx] & 0x0f; for (size_t i = 0; i < len; ++i) { std::string key = from_msgpack_internal(v, idx); result[key] = from_msgpack_internal(v, idx); } return result; } else if (v[current_idx] <= 0x9f) // fixarray { basic_json result = value_t::array; const size_t len = v[current_idx] & 0x0f; for (size_t i = 0; i < len; ++i) { result.push_back(from_msgpack_internal(v, idx)); } return result; } else // fixstr { const size_t len = v[current_idx] & 0x1f; const size_t offset = current_idx + 1; idx += len; // skip content bytes check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } } else if (v[current_idx] >= 0xe0) // negative fixint { return static_cast(v[current_idx]); } else { switch (v[current_idx]) { case 0xc0: // nil { return value_t::null; } case 0xc2: // false { return false; } case 0xc3: // true { return true; } case 0xca: // float 32 { // copy bytes in reverse order into the double variable float res; for (size_t byte = 0; byte < sizeof(float); ++byte) { reinterpret_cast(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte); } idx += sizeof(float); // skip content bytes return res; } case 0xcb: // float 64 { // copy bytes in reverse order into the double variable double res; for (size_t byte = 0; byte < sizeof(double); ++byte) { reinterpret_cast(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte); } idx += sizeof(double); // skip content bytes return res; } case 0xcc: // uint 8 { idx += 1; // skip content byte return get_from_vector(v, current_idx); } case 0xcd: // uint 16 { idx += 2; // skip 2 content bytes return get_from_vector(v, current_idx); } case 0xce: // uint 32 { idx += 4; // skip 4 content bytes return get_from_vector(v, current_idx); } case 0xcf: // uint 64 { idx += 8; // skip 8 content bytes return get_from_vector(v, current_idx); } case 0xd0: // int 8 { idx += 1; // skip content byte return get_from_vector(v, current_idx); } case 0xd1: // int 16 { idx += 2; // skip 2 content bytes return get_from_vector(v, current_idx); } case 0xd2: // int 32 { idx += 4; // skip 4 content bytes return get_from_vector(v, current_idx); } case 0xd3: // int 64 { idx += 8; // skip 8 content bytes return get_from_vector(v, current_idx); } case 0xd9: // str 8 { const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } case 0xda: // str 16 { const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } case 0xdb: // str 32 { const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } case 0xdc: // array 16 { basic_json result = value_t::array; const auto len = static_cast(get_from_vector(v, current_idx)); idx += 2; // skip 2 size bytes for (size_t i = 0; i < len; ++i) { result.push_back(from_msgpack_internal(v, idx)); } return result; } case 0xdd: // array 32 { basic_json result = value_t::array; const auto len = static_cast(get_from_vector(v, current_idx)); idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { result.push_back(from_msgpack_internal(v, idx)); } return result; } case 0xde: // map 16 { basic_json result = value_t::object; const auto len = static_cast(get_from_vector(v, current_idx)); idx += 2; // skip 2 size bytes for (size_t i = 0; i < len; ++i) { std::string key = from_msgpack_internal(v, idx); result[key] = from_msgpack_internal(v, idx); } return result; } case 0xdf: // map 32 { basic_json result = value_t::object; const auto len = static_cast(get_from_vector(v, current_idx)); idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { std::string key = from_msgpack_internal(v, idx); result[key] = from_msgpack_internal(v, idx); } return result; } default: { JSON_THROW(std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast(v[current_idx])))); } } } } /*! @brief create a JSON value from a given CBOR vector @param[in] v CBOR serialization @param[in] idx byte index to start reading from @a v @return deserialized JSON value @throw std::invalid_argument if unsupported features from CBOR were used in the given vector @a v or if the input is not valid CBOR @throw std::out_of_range if the given vector ends prematurely @sa https://tools.ietf.org/html/rfc7049 */ static basic_json from_cbor_internal(const std::vector& v, size_t& idx) { // store and increment index const size_t current_idx = idx++; switch (v.at(current_idx)) { // Integer 0x00..0x17 (0..23) case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: { return v[current_idx]; } case 0x18: // Unsigned integer (one-byte uint8_t follows) { idx += 1; // skip content byte return get_from_vector(v, current_idx); } case 0x19: // Unsigned integer (two-byte uint16_t follows) { idx += 2; // skip 2 content bytes return get_from_vector(v, current_idx); } case 0x1a: // Unsigned integer (four-byte uint32_t follows) { idx += 4; // skip 4 content bytes return get_from_vector(v, current_idx); } case 0x1b: // Unsigned integer (eight-byte uint64_t follows) { idx += 8; // skip 8 content bytes return get_from_vector(v, current_idx); } // Negative integer -1-0x00..-1-0x17 (-1..-24) case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: { return static_cast(0x20 - 1 - v[current_idx]); } case 0x38: // Negative integer (one-byte uint8_t follows) { idx += 1; // skip content byte // must be uint8_t ! return static_cast(-1) - get_from_vector(v, current_idx); } case 0x39: // Negative integer -1-n (two-byte uint16_t follows) { idx += 2; // skip 2 content bytes return static_cast(-1) - get_from_vector(v, current_idx); } case 0x3a: // Negative integer -1-n (four-byte uint32_t follows) { idx += 4; // skip 4 content bytes return static_cast(-1) - get_from_vector(v, current_idx); } case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows) { idx += 8; // skip 8 content bytes return static_cast(-1) - static_cast(get_from_vector(v, current_idx)); } // UTF-8 string (0x00..0x17 bytes follow) case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: { const auto len = static_cast(v[current_idx] - 0x60); const size_t offset = current_idx + 1; idx += len; // skip content bytes check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } case 0x78: // UTF-8 string (one-byte uint8_t for n follows) { const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } case 0x79: // UTF-8 string (two-byte uint16_t for n follow) { const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } case 0x7a: // UTF-8 string (four-byte uint32_t for n follow) { const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow) { const auto len = static_cast(get_from_vector(v, current_idx)); const size_t offset = current_idx + 9; idx += len + 8; // skip 8 size bytes + content bytes check_length(v.size(), len, offset); return std::string(reinterpret_cast(v.data()) + offset, len); } case 0x7f: // UTF-8 string (indefinite length) { std::string result; while (v.at(idx) != 0xff) { string_t s = from_cbor_internal(v, idx); result += s; } // skip break byte (0xFF) idx += 1; return result; } // array (0x00..0x17 data items follow) case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: { basic_json result = value_t::array; const auto len = static_cast(v[current_idx] - 0x80); for (size_t i = 0; i < len; ++i) { result.push_back(from_cbor_internal(v, idx)); } return result; } case 0x98: // array (one-byte uint8_t for n follows) { basic_json result = value_t::array; const auto len = static_cast(get_from_vector(v, current_idx)); idx += 1; // skip 1 size byte for (size_t i = 0; i < len; ++i) { result.push_back(from_cbor_internal(v, idx)); } return result; } case 0x99: // array (two-byte uint16_t for n follow) { basic_json result = value_t::array; const auto len = static_cast(get_from_vector(v, current_idx)); idx += 2; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { result.push_back(from_cbor_internal(v, idx)); } return result; } case 0x9a: // array (four-byte uint32_t for n follow) { basic_json result = value_t::array; const auto len = static_cast(get_from_vector(v, current_idx)); idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { result.push_back(from_cbor_internal(v, idx)); } return result; } case 0x9b: // array (eight-byte uint64_t for n follow) { basic_json result = value_t::array; const auto len = static_cast(get_from_vector(v, current_idx)); idx += 8; // skip 8 size bytes for (size_t i = 0; i < len; ++i) { result.push_back(from_cbor_internal(v, idx)); } return result; } case 0x9f: // array (indefinite length) { basic_json result = value_t::array; while (v.at(idx) != 0xff) { result.push_back(from_cbor_internal(v, idx)); } // skip break byte (0xFF) idx += 1; return result; } // map (0x00..0x17 pairs of data items follow) case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: { basic_json result = value_t::object; const auto len = static_cast(v[current_idx] - 0xa0); for (size_t i = 0; i < len; ++i) { std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); } return result; } case 0xb8: // map (one-byte uint8_t for n follows) { basic_json result = value_t::object; const auto len = static_cast(get_from_vector(v, current_idx)); idx += 1; // skip 1 size byte for (size_t i = 0; i < len; ++i) { std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); } return result; } case 0xb9: // map (two-byte uint16_t for n follow) { basic_json result = value_t::object; const auto len = static_cast(get_from_vector(v, current_idx)); idx += 2; // skip 2 size bytes for (size_t i = 0; i < len; ++i) { std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); } return result; } case 0xba: // map (four-byte uint32_t for n follow) { basic_json result = value_t::object; const auto len = static_cast(get_from_vector(v, current_idx)); idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); } return result; } case 0xbb: // map (eight-byte uint64_t for n follow) { basic_json result = value_t::object; const auto len = static_cast(get_from_vector(v, current_idx)); idx += 8; // skip 8 size bytes for (size_t i = 0; i < len; ++i) { std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); } return result; } case 0xbf: // map (indefinite length) { basic_json result = value_t::object; while (v.at(idx) != 0xff) { std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); } // skip break byte (0xFF) idx += 1; return result; } case 0xf4: // false { return false; } case 0xf5: // true { return true; } case 0xf6: // null { return value_t::null; } case 0xf9: // Half-Precision Float (two-byte IEEE 754) { idx += 2; // skip two content bytes // code from RFC 7049, Appendix D, Figure 3: // As half-precision floating-point numbers were only added to // IEEE 754 in 2008, today's programming platforms often still // only have limited support for them. It is very easy to // include at least decoding support for them even without such // support. An example of a small decoder for half-precision // floating-point numbers in the C language is shown in Fig. 3. const int half = (v.at(current_idx + 1) << 8) + v.at(current_idx + 2); const int exp = (half >> 10) & 0x1f; const int mant = half & 0x3ff; double val; if (exp == 0) { val = std::ldexp(mant, -24); } else if (exp != 31) { val = std::ldexp(mant + 1024, exp - 25); } else { val = mant == 0 ? std::numeric_limits::infinity() : std::numeric_limits::quiet_NaN(); } return (half & 0x8000) != 0 ? -val : val; } case 0xfa: // Single-Precision Float (four-byte IEEE 754) { // copy bytes in reverse order into the float variable float res; for (size_t byte = 0; byte < sizeof(float); ++byte) { reinterpret_cast(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte); } idx += sizeof(float); // skip content bytes return res; } case 0xfb: // Double-Precision Float (eight-byte IEEE 754) { // copy bytes in reverse order into the double variable double res; for (size_t byte = 0; byte < sizeof(double); ++byte) { reinterpret_cast(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte); } idx += sizeof(double); // skip content bytes return res; } default: // anything else (0xFF is handled inside the other types) { JSON_THROW(std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast(v[current_idx])))); } } } public: /*! @brief create a MessagePack serialization of a given JSON value Serializes a given JSON value @a j to a byte vector using the MessagePack serialization format. MessagePack is a binary serialization format which aims to be more compact than JSON itself, yet more efficient to parse. @param[in] j JSON value to serialize @return MessagePack serialization as byte vector @complexity Linear in the size of the JSON value @a j. @liveexample{The example shows the serialization of a JSON value to a byte vector in MessagePack format.,to_msgpack} @sa http://msgpack.org @sa @ref from_msgpack(const std::vector&, const size_t) for the analogous deserialization @sa @ref to_cbor(const basic_json& for the related CBOR format @since version 2.0.9 */ static std::vector to_msgpack(const basic_json& j) { std::vector result; to_msgpack_internal(j, result); return result; } /*! @brief create a JSON value from a byte vector in MessagePack format Deserializes a given byte vector @a v to a JSON value using the MessagePack serialization format. @param[in] v a byte vector in MessagePack format @param[in] start_index the index to start reading from @a v (0 by default) @return deserialized JSON value @throw std::invalid_argument if unsupported features from MessagePack were used in the given vector @a v or if the input is not valid MessagePack @throw std::out_of_range if the given vector ends prematurely @complexity Linear in the size of the byte vector @a v. @liveexample{The example shows the deserialization of a byte vector in MessagePack format to a JSON value.,from_msgpack} @sa http://msgpack.org @sa @ref to_msgpack(const basic_json&) for the analogous serialization @sa @ref from_cbor(const std::vector&, const size_t) for the related CBOR format @since version 2.0.9, parameter @a start_index since 2.1.1 */ static basic_json from_msgpack(const std::vector& v, const size_t start_index = 0) { size_t i = start_index; return from_msgpack_internal(v, i); } /*! @brief create a MessagePack serialization of a given JSON value Serializes a given JSON value @a j to a byte vector using the CBOR (Concise Binary Object Representation) serialization format. CBOR is a binary serialization format which aims to be more compact than JSON itself, yet more efficient to parse. @param[in] j JSON value to serialize @return MessagePack serialization as byte vector @complexity Linear in the size of the JSON value @a j. @liveexample{The example shows the serialization of a JSON value to a byte vector in CBOR format.,to_cbor} @sa http://cbor.io @sa @ref from_cbor(const std::vector&, const size_t) for the analogous deserialization @sa @ref to_msgpack(const basic_json& for the related MessagePack format @since version 2.0.9 */ static std::vector to_cbor(const basic_json& j) { std::vector result; to_cbor_internal(j, result); return result; } /*! @brief create a JSON value from a byte vector in CBOR format Deserializes a given byte vector @a v to a JSON value using the CBOR (Concise Binary Object Representation) serialization format. @param[in] v a byte vector in CBOR format @param[in] start_index the index to start reading from @a v (0 by default) @return deserialized JSON value @throw std::invalid_argument if unsupported features from CBOR were used in the given vector @a v or if the input is not valid MessagePack @throw std::out_of_range if the given vector ends prematurely @complexity Linear in the size of the byte vector @a v. @liveexample{The example shows the deserialization of a byte vector in CBOR format to a JSON value.,from_cbor} @sa http://cbor.io @sa @ref to_cbor(const basic_json&) for the analogous serialization @sa @ref from_msgpack(const std::vector&, const size_t) for the related MessagePack format @since version 2.0.9, parameter @a start_index since 2.1.1 */ static basic_json from_cbor(const std::vector& v, const size_t start_index = 0) { size_t i = start_index; return from_cbor_internal(v, i); } /// @} /////////////////////////// // convenience functions // /////////////////////////// /*! @brief return the type as string Returns the type name as string to be used in error messages - usually to indicate that a function was called on a wrong JSON type. @return basically a string representation of a the @a m_type member @complexity Constant. @liveexample{The following code exemplifies `type_name()` for all JSON types.,type_name} @since version 1.0.0, public since 2.1.0 */ std::string type_name() const { { switch (m_type) { case value_t::null: return "null"; case value_t::object: return "object"; case value_t::array: return "array"; case value_t::string: return "string"; case value_t::boolean: return "boolean"; case value_t::discarded: return "discarded"; default: return "number"; } } } private: /*! @brief calculates the extra space to escape a JSON string @param[in] s the string to escape @return the number of characters required to escape string @a s @complexity Linear in the length of string @a s. */ static std::size_t extra_space(const string_t& s) noexcept { return std::accumulate(s.begin(), s.end(), size_t{}, [](size_t res, typename string_t::value_type c) { switch (c) { case '"': case '\\': case '\b': case '\f': case '\n': case '\r': case '\t': { // from c (1 byte) to \x (2 bytes) return res + 1; } default: { if (c >= 0x00 and c <= 0x1f) { // from c (1 byte) to \uxxxx (6 bytes) return res + 5; } return res; } } }); } /*! @brief escape a string Escape a string by replacing certain special characters by a sequence of an escape character (backslash) and another character and other control characters by a sequence of "\u" followed by a four-digit hex representation. @param[in] s the string to escape @return the escaped string @complexity Linear in the length of string @a s. */ static string_t escape_string(const string_t& s) { const auto space = extra_space(s); if (space == 0) { return s; } // create a result string of necessary size string_t result(s.size() + space, '\\'); std::size_t pos = 0; for (const auto& c : s) { switch (c) { // quotation mark (0x22) case '"': { result[pos + 1] = '"'; pos += 2; break; } // reverse solidus (0x5c) case '\\': { // nothing to change pos += 2; break; } // backspace (0x08) case '\b': { result[pos + 1] = 'b'; pos += 2; break; } // formfeed (0x0c) case '\f': { result[pos + 1] = 'f'; pos += 2; break; } // newline (0x0a) case '\n': { result[pos + 1] = 'n'; pos += 2; break; } // carriage return (0x0d) case '\r': { result[pos + 1] = 'r'; pos += 2; break; } // horizontal tab (0x09) case '\t': { result[pos + 1] = 't'; pos += 2; break; } default: { if (c >= 0x00 and c <= 0x1f) { // convert a number 0..15 to its hex representation // (0..f) static const char hexify[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; // print character c as \uxxxx for (const char m : { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f] }) { result[++pos] = m; } ++pos; } else { // all other characters are added as-is result[pos++] = c; } break; } } } return result; } /*! @brief locale-independent serialization for built-in arithmetic types */ struct numtostr { public: template numtostr(NumberType value) { x_write(value, std::is_integral()); } const char* c_str() const { return m_buf.data(); } private: /// a (hopefully) large enough character buffer std::array < char, 64 > m_buf{{}}; template void x_write(NumberType x, /*is_integral=*/std::true_type) { // special case for "0" if (x == 0) { m_buf[0] = '0'; return; } const bool is_negative = x < 0; size_t i = 0; // spare 1 byte for '\0' while (x != 0 and i < m_buf.size() - 1) { const auto digit = std::labs(static_cast(x % 10)); m_buf[i++] = static_cast('0' + digit); x /= 10; } // make sure the number has been processed completely assert(x == 0); if (is_negative) { // make sure there is capacity for the '-' assert(i < m_buf.size() - 2); m_buf[i++] = '-'; } std::reverse(m_buf.begin(), m_buf.begin() + i); } template void x_write(NumberType x, /*is_integral=*/std::false_type) { // special case for 0.0 and -0.0 if (x == 0) { size_t i = 0; if (std::signbit(x)) { m_buf[i++] = '-'; } m_buf[i++] = '0'; m_buf[i++] = '.'; m_buf[i] = '0'; return; } // get number of digits for a text -> float -> text round-trip static constexpr auto d = std::numeric_limits::digits10; // the actual conversion const auto written_bytes = snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x); // negative value indicates an error assert(written_bytes > 0); // check if buffer was large enough assert(static_cast(written_bytes) < m_buf.size()); // read information from locale const auto loc = localeconv(); assert(loc != nullptr); const char thousands_sep = !loc->thousands_sep ? '\0' : loc->thousands_sep[0]; const char decimal_point = !loc->decimal_point ? '\0' : loc->decimal_point[0]; // erase thousands separator if (thousands_sep != '\0') { const auto end = std::remove(m_buf.begin(), m_buf.begin() + written_bytes, thousands_sep); std::fill(end, m_buf.end(), '\0'); } // convert decimal point to '.' if (decimal_point != '\0' and decimal_point != '.') { for (auto& c : m_buf) { if (c == decimal_point) { c = '.'; break; } } } // determine if need to append ".0" size_t i = 0; bool value_is_int_like = true; for (i = 0; i < m_buf.size(); ++i) { // break when end of number is reached if (m_buf[i] == '\0') { break; } // check if we find non-int character value_is_int_like = value_is_int_like and m_buf[i] != '.' and m_buf[i] != 'e' and m_buf[i] != 'E'; } if (value_is_int_like) { // there must be 2 bytes left for ".0" assert((i + 2) < m_buf.size()); // we write to the end of the number assert(m_buf[i] == '\0'); assert(m_buf[i - 1] != '\0'); // add ".0" m_buf[i] = '.'; m_buf[i + 1] = '0'; // the resulting string is properly terminated assert(m_buf[i + 2] == '\0'); } } }; /*! @brief internal implementation of the serialization function This function is called by the public member function dump and organizes the serialization internally. The indentation level is propagated as additional parameter. In case of arrays and objects, the function is called recursively. Note that - strings and object keys are escaped using `escape_string()` - integer numbers are converted implicitly via `operator<<` - floating-point numbers are converted to a string using `"%g"` format @param[out] o stream to write to @param[in] pretty_print whether the output shall be pretty-printed @param[in] indent_step the indent level @param[in] current_indent the current indent level (only used internally) */ void dump(std::ostream& o, const bool pretty_print, const unsigned int indent_step, const unsigned int current_indent = 0) const { // variable to hold indentation for recursive calls unsigned int new_indent = current_indent; switch (m_type) { case value_t::object: { if (m_value.object->empty()) { o << "{}"; return; } o << "{"; // increase indentation if (pretty_print) { new_indent += indent_step; o << "\n"; } for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i) { if (i != m_value.object->cbegin()) { o << (pretty_print ? ",\n" : ","); } o << string_t(new_indent, ' ') << "\"" << escape_string(i->first) << "\":" << (pretty_print ? " " : ""); i->second.dump(o, pretty_print, indent_step, new_indent); } // decrease indentation if (pretty_print) { new_indent -= indent_step; o << "\n"; } o << string_t(new_indent, ' ') + "}"; return; } case value_t::array: { if (m_value.array->empty()) { o << "[]"; return; } o << "["; // increase indentation if (pretty_print) { new_indent += indent_step; o << "\n"; } for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i) { if (i != m_value.array->cbegin()) { o << (pretty_print ? ",\n" : ","); } o << string_t(new_indent, ' '); i->dump(o, pretty_print, indent_step, new_indent); } // decrease indentation if (pretty_print) { new_indent -= indent_step; o << "\n"; } o << string_t(new_indent, ' ') << "]"; return; } case value_t::string: { o << string_t("\"") << escape_string(*m_value.string) << "\""; return; } case value_t::boolean: { o << (m_value.boolean ? "true" : "false"); return; } case value_t::number_integer: { o << numtostr(m_value.number_integer).c_str(); return; } case value_t::number_unsigned: { o << numtostr(m_value.number_unsigned).c_str(); return; } case value_t::number_float: { o << numtostr(m_value.number_float).c_str(); return; } case value_t::discarded: { o << ""; return; } case value_t::null: { o << "null"; return; } } } private: ////////////////////// // member variables // ////////////////////// /// the type of the current element value_t m_type = value_t::null; /// the value of the current element json_value m_value = {}; private: /////////////// // iterators // /////////////// /*! @brief an iterator for primitive JSON types This class models an iterator for primitive JSON types (boolean, number, string). It's only purpose is to allow the iterator/const_iterator classes to "iterate" over primitive values. Internally, the iterator is modeled by a `difference_type` variable. Value begin_value (`0`) models the begin, end_value (`1`) models past the end. */ class primitive_iterator_t { public: difference_type get_value() const noexcept { return m_it; } /// set iterator to a defined beginning void set_begin() noexcept { m_it = begin_value; } /// set iterator to a defined past the end void set_end() noexcept { m_it = end_value; } /// return whether the iterator can be dereferenced constexpr bool is_begin() const noexcept { return (m_it == begin_value); } /// return whether the iterator is at end constexpr bool is_end() const noexcept { return (m_it == end_value); } friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { return lhs.m_it == rhs.m_it; } friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { return !(lhs == rhs); } friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { return lhs.m_it < rhs.m_it; } friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { return lhs.m_it <= rhs.m_it; } friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { return lhs.m_it > rhs.m_it; } friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { return lhs.m_it >= rhs.m_it; } primitive_iterator_t operator+(difference_type i) { auto result = *this; result += i; return result; } friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { return lhs.m_it - rhs.m_it; } friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it) { return os << it.m_it; } primitive_iterator_t& operator++() { ++m_it; return *this; } primitive_iterator_t operator++(int) { auto result = *this; m_it++; return result; } primitive_iterator_t& operator--() { --m_it; return *this; } primitive_iterator_t operator--(int) { auto result = *this; m_it--; return result; } primitive_iterator_t& operator+=(difference_type n) { m_it += n; return *this; } primitive_iterator_t& operator-=(difference_type n) { m_it -= n; return *this; } private: static constexpr difference_type begin_value = 0; static constexpr difference_type end_value = begin_value + 1; /// iterator as signed integer type difference_type m_it = std::numeric_limits::denorm_min(); }; /*! @brief an iterator value @note This structure could easily be a union, but MSVC currently does not allow unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. */ struct internal_iterator { /// iterator for JSON objects typename object_t::iterator object_iterator; /// iterator for JSON arrays typename array_t::iterator array_iterator; /// generic iterator for all other types primitive_iterator_t primitive_iterator; /// create an uninitialized internal_iterator internal_iterator() noexcept : object_iterator(), array_iterator(), primitive_iterator() {} }; /// proxy class for the iterator_wrapper functions template class iteration_proxy { private: /// helper class for iteration class iteration_proxy_internal { private: /// the iterator IteratorType anchor; /// an index for arrays (used to create key names) size_t array_index = 0; public: explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {} /// dereference operator (needed for range-based for) iteration_proxy_internal& operator*() { return *this; } /// increment operator (needed for range-based for) iteration_proxy_internal& operator++() { ++anchor; ++array_index; return *this; } /// inequality operator (needed for range-based for) bool operator!= (const iteration_proxy_internal& o) const { return anchor != o.anchor; } /// return key of the iterator typename basic_json::string_t key() const { assert(anchor.m_object != nullptr); switch (anchor.m_object->type()) { // use integer array index as key case value_t::array: { return std::to_string(array_index); } // use key from the object case value_t::object: { return anchor.key(); } // use an empty key for all primitive types default: { return ""; } } } /// return value of the iterator typename IteratorType::reference value() const { return anchor.value(); } }; /// the container to iterate typename IteratorType::reference container; public: /// construct iteration proxy from a container explicit iteration_proxy(typename IteratorType::reference cont) : container(cont) {} /// return iterator begin (needed for range-based for) iteration_proxy_internal begin() noexcept { return iteration_proxy_internal(container.begin()); } /// return iterator end (needed for range-based for) iteration_proxy_internal end() noexcept { return iteration_proxy_internal(container.end()); } }; public: /*! @brief a template for a random access iterator for the @ref basic_json class This class implements a both iterators (iterator and const_iterator) for the @ref basic_json class. @note An iterator is called *initialized* when a pointer to a JSON value has been set (e.g., by a constructor or a copy assignment). If the iterator is default-constructed, it is *uninitialized* and most methods are undefined. **The library uses assertions to detect calls on uninitialized iterators.** @requirement The class satisfies the following concept requirements: - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator): The iterator that can be moved to point (forward and backward) to any element in constant time. @since version 1.0.0, simplified in version 2.0.9 */ template class iter_impl : public std::iterator { /// allow basic_json to access private members friend class basic_json; // make sure U is basic_json or const basic_json static_assert(std::is_same::value or std::is_same::value, "iter_impl only accepts (const) basic_json"); public: /// the type of the values when the iterator is dereferenced using value_type = typename basic_json::value_type; /// a type to represent differences between iterators using difference_type = typename basic_json::difference_type; /// defines a pointer to the type iterated over (value_type) using pointer = typename std::conditional::value, typename basic_json::const_pointer, typename basic_json::pointer>::type; /// defines a reference to the type iterated over (value_type) using reference = typename std::conditional::value, typename basic_json::const_reference, typename basic_json::reference>::type; /// the category of the iterator using iterator_category = std::bidirectional_iterator_tag; /// default constructor iter_impl() = default; /*! @brief constructor for a given JSON instance @param[in] object pointer to a JSON object for this iterator @pre object != nullptr @post The iterator is initialized; i.e. `m_object != nullptr`. */ explicit iter_impl(pointer object) noexcept : m_object(object) { assert(m_object != nullptr); switch (m_object->m_type) { case basic_json::value_t::object: { m_it.object_iterator = typename object_t::iterator(); break; } case basic_json::value_t::array: { m_it.array_iterator = typename array_t::iterator(); break; } default: { m_it.primitive_iterator = primitive_iterator_t(); break; } } } /* Use operator `const_iterator` instead of `const_iterator(const iterator& other) noexcept` to avoid two class definitions for @ref iterator and @ref const_iterator. This function is only called if this class is an @ref iterator. If this class is a @ref const_iterator this function is not called. */ operator const_iterator() const { const_iterator ret; if (m_object) { ret.m_object = m_object; ret.m_it = m_it; } return ret; } /*! @brief copy constructor @param[in] other iterator to copy from @note It is not checked whether @a other is initialized. */ iter_impl(const iter_impl& other) noexcept : m_object(other.m_object), m_it(other.m_it) {} /*! @brief copy assignment @param[in,out] other iterator to copy from @note It is not checked whether @a other is initialized. */ iter_impl& operator=(iter_impl other) noexcept( std::is_nothrow_move_constructible::value and std::is_nothrow_move_assignable::value and std::is_nothrow_move_constructible::value and std::is_nothrow_move_assignable::value ) { std::swap(m_object, other.m_object); std::swap(m_it, other.m_it); return *this; } private: /*! @brief set the iterator to the first value @pre The iterator is initialized; i.e. `m_object != nullptr`. */ void set_begin() noexcept { assert(m_object != nullptr); switch (m_object->m_type) { case basic_json::value_t::object: { m_it.object_iterator = m_object->m_value.object->begin(); break; } case basic_json::value_t::array: { m_it.array_iterator = m_object->m_value.array->begin(); break; } case basic_json::value_t::null: { // set to end so begin()==end() is true: null is empty m_it.primitive_iterator.set_end(); break; } default: { m_it.primitive_iterator.set_begin(); break; } } } /*! @brief set the iterator past the last value @pre The iterator is initialized; i.e. `m_object != nullptr`. */ void set_end() noexcept { assert(m_object != nullptr); switch (m_object->m_type) { case basic_json::value_t::object: { m_it.object_iterator = m_object->m_value.object->end(); break; } case basic_json::value_t::array: { m_it.array_iterator = m_object->m_value.array->end(); break; } default: { m_it.primitive_iterator.set_end(); break; } } } public: /*! @brief return a reference to the value pointed to by the iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ reference operator*() const { assert(m_object != nullptr); switch (m_object->m_type) { case basic_json::value_t::object: { assert(m_it.object_iterator != m_object->m_value.object->end()); return m_it.object_iterator->second; } case basic_json::value_t::array: { assert(m_it.array_iterator != m_object->m_value.array->end()); return *m_it.array_iterator; } case basic_json::value_t::null: { JSON_THROW(std::out_of_range("cannot get value")); } default: { if (m_it.primitive_iterator.is_begin()) { return *m_object; } JSON_THROW(std::out_of_range("cannot get value")); } } } /*! @brief dereference the iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ pointer operator->() const { assert(m_object != nullptr); switch (m_object->m_type) { case basic_json::value_t::object: { assert(m_it.object_iterator != m_object->m_value.object->end()); return &(m_it.object_iterator->second); } case basic_json::value_t::array: { assert(m_it.array_iterator != m_object->m_value.array->end()); return &*m_it.array_iterator; } default: { if (m_it.primitive_iterator.is_begin()) { return m_object; } JSON_THROW(std::out_of_range("cannot get value")); } } } /*! @brief post-increment (it++) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl operator++(int) { auto result = *this; ++(*this); return result; } /*! @brief pre-increment (++it) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl& operator++() { assert(m_object != nullptr); switch (m_object->m_type) { case basic_json::value_t::object: { std::advance(m_it.object_iterator, 1); break; } case basic_json::value_t::array: { std::advance(m_it.array_iterator, 1); break; } default: { ++m_it.primitive_iterator; break; } } return *this; } /*! @brief post-decrement (it--) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl operator--(int) { auto result = *this; --(*this); return result; } /*! @brief pre-decrement (--it) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl& operator--() { assert(m_object != nullptr); switch (m_object->m_type) { case basic_json::value_t::object: { std::advance(m_it.object_iterator, -1); break; } case basic_json::value_t::array: { std::advance(m_it.array_iterator, -1); break; } default: { --m_it.primitive_iterator; break; } } return *this; } /*! @brief comparison: equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator==(const iter_impl& other) const { // if objects are not the same, the comparison is undefined if (m_object != other.m_object) { JSON_THROW(std::domain_error("cannot compare iterators of different containers")); } assert(m_object != nullptr); switch (m_object->m_type) { case basic_json::value_t::object: { return (m_it.object_iterator == other.m_it.object_iterator); } case basic_json::value_t::array: { return (m_it.array_iterator == other.m_it.array_iterator); } default: { return (m_it.primitive_iterator == other.m_it.primitive_iterator); } } } /*! @brief comparison: not equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator!=(const iter_impl& other) const { return not operator==(other); } /*! @brief comparison: smaller @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator<(const iter_impl& other) const { // if objects are not the same, the comparison is undefined if (m_object != other.m_object) { JSON_THROW(std::domain_error("cannot compare iterators of different containers")); } assert(m_object != nullptr); switch (m_object->m_type) { case basic_json::value_t::object: { JSON_THROW(std::domain_error("cannot compare order of object iterators")); } case basic_json::value_t::array: { return (m_it.array_iterator < other.m_it.array_iterator); } default: { return (m_it.primitive_iterator < other.m_it.primitive_iterator); } } } /*! @brief comparison: less than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator<=(const iter_impl& other) const { return not other.operator < (*this); } /*! @brief comparison: greater than @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator>(const iter_impl& other) const { return not operator<=(other); } /*! @brief comparison: greater than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ bool operator>=(const iter_impl& other) const { return not operator<(other); } /*! @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl& operator+=(difference_type i) { assert(m_object != nullptr); switch (m_object->m_type) { case basic_json::value_t::object: { JSON_THROW(std::domain_error("cannot use offsets with object iterators")); } case basic_json::value_t::array: { std::advance(m_it.array_iterator, i); break; } default: { m_it.primitive_iterator += i; break; } } return *this; } /*! @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl& operator-=(difference_type i) { return operator+=(-i); } /*! @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl operator+(difference_type i) { auto result = *this; result += i; return result; } /*! @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ iter_impl operator-(difference_type i) { auto result = *this; result -= i; return result; } /*! @brief return difference @pre The iterator is initialized; i.e. `m_object != nullptr`. */ difference_type operator-(const iter_impl& other) const { assert(m_object != nullptr); switch (m_object->m_type) { case basic_json::value_t::object: { JSON_THROW(std::domain_error("cannot use offsets with object iterators")); } case basic_json::value_t::array: { return m_it.array_iterator - other.m_it.array_iterator; } default: { return m_it.primitive_iterator - other.m_it.primitive_iterator; } } } /*! @brief access to successor @pre The iterator is initialized; i.e. `m_object != nullptr`. */ reference operator[](difference_type n) const { assert(m_object != nullptr); switch (m_object->m_type) { case basic_json::value_t::object: { JSON_THROW(std::domain_error("cannot use operator[] for object iterators")); } case basic_json::value_t::array: { return *std::next(m_it.array_iterator, n); } case basic_json::value_t::null: { JSON_THROW(std::out_of_range("cannot get value")); } default: { if (m_it.primitive_iterator.get_value() == -n) { return *m_object; } JSON_THROW(std::out_of_range("cannot get value")); } } } /*! @brief return the key of an object iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ typename object_t::key_type key() const { assert(m_object != nullptr); if (m_object->is_object()) { return m_it.object_iterator->first; } JSON_THROW(std::domain_error("cannot use key() for non-object iterators")); } /*! @brief return the value of an iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ reference value() const { return operator*(); } private: /// associated JSON instance pointer m_object = nullptr; /// the actual iterator of the associated instance internal_iterator m_it = internal_iterator(); }; /*! @brief a template for a reverse iterator class @tparam Base the base iterator type to reverse. Valid types are @ref iterator (to create @ref reverse_iterator) and @ref const_iterator (to create @ref const_reverse_iterator). @requirement The class satisfies the following concept requirements: - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator): The iterator that can be moved to point (forward and backward) to any element in constant time. - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator): It is possible to write to the pointed-to element (only if @a Base is @ref iterator). @since version 1.0.0 */ template class json_reverse_iterator : public std::reverse_iterator { public: /// shortcut to the reverse iterator adaptor using base_iterator = std::reverse_iterator; /// the reference type for the pointed-to element using reference = typename Base::reference; /// create reverse iterator from iterator json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept : base_iterator(it) {} /// create reverse iterator from base class json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} /// post-increment (it++) json_reverse_iterator operator++(int) { return base_iterator::operator++(1); } /// pre-increment (++it) json_reverse_iterator& operator++() { base_iterator::operator++(); return *this; } /// post-decrement (it--) json_reverse_iterator operator--(int) { return base_iterator::operator--(1); } /// pre-decrement (--it) json_reverse_iterator& operator--() { base_iterator::operator--(); return *this; } /// add to iterator json_reverse_iterator& operator+=(difference_type i) { base_iterator::operator+=(i); return *this; } /// add to iterator json_reverse_iterator operator+(difference_type i) const { auto result = *this; result += i; return result; } /// subtract from iterator json_reverse_iterator operator-(difference_type i) const { auto result = *this; result -= i; return result; } /// return difference difference_type operator-(const json_reverse_iterator& other) const { return this->base() - other.base(); } /// access to successor reference operator[](difference_type n) const { return *(this->operator+(n)); } /// return the key of an object iterator typename object_t::key_type key() const { auto it = --this->base(); return it.key(); } /// return the value of an iterator reference value() const { auto it = --this->base(); return it.operator * (); } }; private: ////////////////////// // lexer and parser // ////////////////////// /*! @brief lexical analysis This class organizes the lexical analysis during JSON deserialization. The core of it is a scanner generated by [re2c](http://re2c.org) that processes a buffer and recognizes tokens according to RFC 7159. */ class lexer { public: /// token types for the parser enum class token_type { uninitialized, ///< indicating the scanner is uninitialized literal_true, ///< the `true` literal literal_false, ///< the `false` literal literal_null, ///< the `null` literal value_string, ///< a string -- use get_string() for actual value value_unsigned, ///< an unsigned integer -- use get_number() for actual value value_integer, ///< a signed integer -- use get_number() for actual value value_float, ///< an floating point number -- use get_number() for actual value begin_array, ///< the character for array begin `[` begin_object, ///< the character for object begin `{` end_array, ///< the character for array end `]` end_object, ///< the character for object end `}` name_separator, ///< the name separator `:` value_separator, ///< the value separator `,` parse_error, ///< indicating a parse error end_of_input ///< indicating the end of the input buffer }; /// the char type to use in the lexer using lexer_char_t = unsigned char; /// a lexer from a buffer with given length lexer(const lexer_char_t* buff, const size_t len) noexcept : m_content(buff) { assert(m_content != nullptr); m_start = m_cursor = m_content; m_limit = m_content + len; } /// a lexer from an input stream explicit lexer(std::istream& s) : m_stream(&s), m_line_buffer() { // immediately abort if stream is erroneous if (s.fail()) { JSON_THROW(std::invalid_argument("stream error")); } // fill buffer fill_line_buffer(); // skip UTF-8 byte-order mark if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF") { m_line_buffer[0] = ' '; m_line_buffer[1] = ' '; m_line_buffer[2] = ' '; } } // switch off unwanted functions (due to pointer members) lexer() = delete; lexer(const lexer&) = delete; lexer operator=(const lexer&) = delete; /*! @brief create a string from one or two Unicode code points There are two cases: (1) @a codepoint1 is in the Basic Multilingual Plane (U+0000 through U+FFFF) and @a codepoint2 is 0, or (2) @a codepoint1 and @a codepoint2 are a UTF-16 surrogate pair to represent a code point above U+FFFF. @param[in] codepoint1 the code point (can be high surrogate) @param[in] codepoint2 the code point (can be low surrogate or 0) @return string representation of the code point; the length of the result string is between 1 and 4 characters. @throw std::out_of_range if code point is > 0x10ffff; example: `"code points above 0x10FFFF are invalid"` @throw std::invalid_argument if the low surrogate is invalid; example: `""missing or wrong low surrogate""` @complexity Constant. @see */ static string_t to_unicode(const std::size_t codepoint1, const std::size_t codepoint2 = 0) { // calculate the code point from the given code points std::size_t codepoint = codepoint1; // check if codepoint1 is a high surrogate if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF) { // check if codepoint2 is a low surrogate if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF) { codepoint = // high surrogate occupies the most significant 22 bits (codepoint1 << 10) // low surrogate occupies the least significant 15 bits + codepoint2 // there is still the 0xD800, 0xDC00 and 0x10000 noise // in the result so we have to subtract with: // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 - 0x35FDC00; } else { JSON_THROW(std::invalid_argument("missing or wrong low surrogate")); } } string_t result; if (codepoint < 0x80) { // 1-byte characters: 0xxxxxxx (ASCII) result.append(1, static_cast(codepoint)); } else if (codepoint <= 0x7ff) { // 2-byte characters: 110xxxxx 10xxxxxx result.append(1, static_cast(0xC0 | ((codepoint >> 6) & 0x1F))); result.append(1, static_cast(0x80 | (codepoint & 0x3F))); } else if (codepoint <= 0xffff) { // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx result.append(1, static_cast(0xE0 | ((codepoint >> 12) & 0x0F))); result.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); result.append(1, static_cast(0x80 | (codepoint & 0x3F))); } else if (codepoint <= 0x10ffff) { // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx result.append(1, static_cast(0xF0 | ((codepoint >> 18) & 0x07))); result.append(1, static_cast(0x80 | ((codepoint >> 12) & 0x3F))); result.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); result.append(1, static_cast(0x80 | (codepoint & 0x3F))); } else { JSON_THROW(std::out_of_range("code points above 0x10FFFF are invalid")); } return result; } /// return name of values of type token_type (only used for errors) static std::string token_type_name(const token_type t) { switch (t) { case token_type::uninitialized: return ""; case token_type::literal_true: return "true literal"; case token_type::literal_false: return "false literal"; case token_type::literal_null: return "null literal"; case token_type::value_string: return "string literal"; case lexer::token_type::value_unsigned: case lexer::token_type::value_integer: case lexer::token_type::value_float: return "number literal"; case token_type::begin_array: return "'['"; case token_type::begin_object: return "'{'"; case token_type::end_array: return "']'"; case token_type::end_object: return "'}'"; case token_type::name_separator: return "':'"; case token_type::value_separator: return "','"; case token_type::parse_error: return ""; case token_type::end_of_input: return "end of input"; default: { // catch non-enum values return "unknown token"; // LCOV_EXCL_LINE } } } /*! This function implements a scanner for JSON. It is specified using regular expressions that try to follow RFC 7159 as close as possible. These regular expressions are then translated into a minimized deterministic finite automaton (DFA) by the tool [re2c](http://re2c.org). As a result, the translated code for this function consists of a large block of code with `goto` jumps. @return the class of the next token read from the buffer @complexity Linear in the length of the input.\n Proposition: The loop below will always terminate for finite input.\n Proof (by contradiction): Assume a finite input. To loop forever, the loop must never hit code with a `break` statement. The only code snippets without a `break` statement are the continue statements for whitespace and byte-order-marks. To loop forever, the input must be an infinite sequence of whitespace or byte-order-marks. This contradicts the assumption of finite input, q.e.d. */ token_type scan() { while (true) { // pointer for backtracking information m_marker = nullptr; // remember the begin of the token m_start = m_cursor; assert(m_start != nullptr); { lexer_char_t yych; unsigned int yyaccept = 0; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; if ((m_limit - m_cursor) < 5) { fill_line_buffer(5); // LCOV_EXCL_LINE } yych = *m_cursor; if (yybm[0 + yych] & 32) { goto basic_json_parser_6; } if (yych <= '[') { if (yych <= '-') { if (yych <= '"') { if (yych <= 0x00) { goto basic_json_parser_2; } if (yych <= '!') { goto basic_json_parser_4; } goto basic_json_parser_9; } else { if (yych <= '+') { goto basic_json_parser_4; } if (yych <= ',') { goto basic_json_parser_10; } goto basic_json_parser_12; } } else { if (yych <= '9') { if (yych <= '/') { goto basic_json_parser_4; } if (yych <= '0') { goto basic_json_parser_13; } goto basic_json_parser_15; } else { if (yych <= ':') { goto basic_json_parser_17; } if (yych <= 'Z') { goto basic_json_parser_4; } goto basic_json_parser_19; } } } else { if (yych <= 'n') { if (yych <= 'e') { if (yych == ']') { goto basic_json_parser_21; } goto basic_json_parser_4; } else { if (yych <= 'f') { goto basic_json_parser_23; } if (yych <= 'm') { goto basic_json_parser_4; } goto basic_json_parser_24; } } else { if (yych <= 'z') { if (yych == 't') { goto basic_json_parser_25; } goto basic_json_parser_4; } else { if (yych <= '{') { goto basic_json_parser_26; } if (yych == '}') { goto basic_json_parser_28; } goto basic_json_parser_4; } } } basic_json_parser_2: ++m_cursor; { last_token_type = token_type::end_of_input; break; } basic_json_parser_4: ++m_cursor; basic_json_parser_5: { last_token_type = token_type::parse_error; break; } basic_json_parser_6: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yybm[0 + yych] & 32) { goto basic_json_parser_6; } { continue; } basic_json_parser_9: yyaccept = 0; yych = *(m_marker = ++m_cursor); if (yych <= 0x1F) { goto basic_json_parser_5; } if (yych <= 0x7F) { goto basic_json_parser_31; } if (yych <= 0xC1) { goto basic_json_parser_5; } if (yych <= 0xF4) { goto basic_json_parser_31; } goto basic_json_parser_5; basic_json_parser_10: ++m_cursor; { last_token_type = token_type::value_separator; break; } basic_json_parser_12: yych = *++m_cursor; if (yych <= '/') { goto basic_json_parser_5; } if (yych <= '0') { goto basic_json_parser_43; } if (yych <= '9') { goto basic_json_parser_45; } goto basic_json_parser_5; basic_json_parser_13: yyaccept = 1; yych = *(m_marker = ++m_cursor); if (yych <= '9') { if (yych == '.') { goto basic_json_parser_47; } if (yych >= '0') { goto basic_json_parser_48; } } else { if (yych <= 'E') { if (yych >= 'E') { goto basic_json_parser_51; } } else { if (yych == 'e') { goto basic_json_parser_51; } } } basic_json_parser_14: { last_token_type = token_type::value_unsigned; break; } basic_json_parser_15: yyaccept = 1; m_marker = ++m_cursor; if ((m_limit - m_cursor) < 3) { fill_line_buffer(3); // LCOV_EXCL_LINE } yych = *m_cursor; if (yybm[0 + yych] & 64) { goto basic_json_parser_15; } if (yych <= 'D') { if (yych == '.') { goto basic_json_parser_47; } goto basic_json_parser_14; } else { if (yych <= 'E') { goto basic_json_parser_51; } if (yych == 'e') { goto basic_json_parser_51; } goto basic_json_parser_14; } basic_json_parser_17: ++m_cursor; { last_token_type = token_type::name_separator; break; } basic_json_parser_19: ++m_cursor; { last_token_type = token_type::begin_array; break; } basic_json_parser_21: ++m_cursor; { last_token_type = token_type::end_array; break; } basic_json_parser_23: yyaccept = 0; yych = *(m_marker = ++m_cursor); if (yych == 'a') { goto basic_json_parser_52; } goto basic_json_parser_5; basic_json_parser_24: yyaccept = 0; yych = *(m_marker = ++m_cursor); if (yych == 'u') { goto basic_json_parser_53; } goto basic_json_parser_5; basic_json_parser_25: yyaccept = 0; yych = *(m_marker = ++m_cursor); if (yych == 'r') { goto basic_json_parser_54; } goto basic_json_parser_5; basic_json_parser_26: ++m_cursor; { last_token_type = token_type::begin_object; break; } basic_json_parser_28: ++m_cursor; { last_token_type = token_type::end_object; break; } basic_json_parser_30: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; basic_json_parser_31: if (yybm[0 + yych] & 128) { goto basic_json_parser_30; } if (yych <= 0xE0) { if (yych <= '\\') { if (yych <= 0x1F) { goto basic_json_parser_32; } if (yych <= '"') { goto basic_json_parser_33; } goto basic_json_parser_35; } else { if (yych <= 0xC1) { goto basic_json_parser_32; } if (yych <= 0xDF) { goto basic_json_parser_36; } goto basic_json_parser_37; } } else { if (yych <= 0xEF) { if (yych == 0xED) { goto basic_json_parser_39; } goto basic_json_parser_38; } else { if (yych <= 0xF0) { goto basic_json_parser_40; } if (yych <= 0xF3) { goto basic_json_parser_41; } if (yych <= 0xF4) { goto basic_json_parser_42; } } } basic_json_parser_32: m_cursor = m_marker; if (yyaccept <= 1) { if (yyaccept == 0) { goto basic_json_parser_5; } else { goto basic_json_parser_14; } } else { if (yyaccept == 2) { goto basic_json_parser_44; } else { goto basic_json_parser_58; } } basic_json_parser_33: ++m_cursor; { last_token_type = token_type::value_string; break; } basic_json_parser_35: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= 'e') { if (yych <= '/') { if (yych == '"') { goto basic_json_parser_30; } if (yych <= '.') { goto basic_json_parser_32; } goto basic_json_parser_30; } else { if (yych <= '\\') { if (yych <= '[') { goto basic_json_parser_32; } goto basic_json_parser_30; } else { if (yych == 'b') { goto basic_json_parser_30; } goto basic_json_parser_32; } } } else { if (yych <= 'q') { if (yych <= 'f') { goto basic_json_parser_30; } if (yych == 'n') { goto basic_json_parser_30; } goto basic_json_parser_32; } else { if (yych <= 's') { if (yych <= 'r') { goto basic_json_parser_30; } goto basic_json_parser_32; } else { if (yych <= 't') { goto basic_json_parser_30; } if (yych <= 'u') { goto basic_json_parser_55; } goto basic_json_parser_32; } } } basic_json_parser_36: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= 0x7F) { goto basic_json_parser_32; } if (yych <= 0xBF) { goto basic_json_parser_30; } goto basic_json_parser_32; basic_json_parser_37: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= 0x9F) { goto basic_json_parser_32; } if (yych <= 0xBF) { goto basic_json_parser_36; } goto basic_json_parser_32; basic_json_parser_38: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= 0x7F) { goto basic_json_parser_32; } if (yych <= 0xBF) { goto basic_json_parser_36; } goto basic_json_parser_32; basic_json_parser_39: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= 0x7F) { goto basic_json_parser_32; } if (yych <= 0x9F) { goto basic_json_parser_36; } goto basic_json_parser_32; basic_json_parser_40: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= 0x8F) { goto basic_json_parser_32; } if (yych <= 0xBF) { goto basic_json_parser_38; } goto basic_json_parser_32; basic_json_parser_41: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= 0x7F) { goto basic_json_parser_32; } if (yych <= 0xBF) { goto basic_json_parser_38; } goto basic_json_parser_32; basic_json_parser_42: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= 0x7F) { goto basic_json_parser_32; } if (yych <= 0x8F) { goto basic_json_parser_38; } goto basic_json_parser_32; basic_json_parser_43: yyaccept = 2; yych = *(m_marker = ++m_cursor); if (yych <= '9') { if (yych == '.') { goto basic_json_parser_47; } if (yych >= '0') { goto basic_json_parser_48; } } else { if (yych <= 'E') { if (yych >= 'E') { goto basic_json_parser_51; } } else { if (yych == 'e') { goto basic_json_parser_51; } } } basic_json_parser_44: { last_token_type = token_type::value_integer; break; } basic_json_parser_45: yyaccept = 2; m_marker = ++m_cursor; if ((m_limit - m_cursor) < 3) { fill_line_buffer(3); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= '9') { if (yych == '.') { goto basic_json_parser_47; } if (yych <= '/') { goto basic_json_parser_44; } goto basic_json_parser_45; } else { if (yych <= 'E') { if (yych <= 'D') { goto basic_json_parser_44; } goto basic_json_parser_51; } else { if (yych == 'e') { goto basic_json_parser_51; } goto basic_json_parser_44; } } basic_json_parser_47: yych = *++m_cursor; if (yych <= '/') { goto basic_json_parser_32; } if (yych <= '9') { goto basic_json_parser_56; } goto basic_json_parser_32; basic_json_parser_48: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= '/') { goto basic_json_parser_50; } if (yych <= '9') { goto basic_json_parser_48; } basic_json_parser_50: { last_token_type = token_type::parse_error; break; } basic_json_parser_51: yych = *++m_cursor; if (yych <= ',') { if (yych == '+') { goto basic_json_parser_59; } goto basic_json_parser_32; } else { if (yych <= '-') { goto basic_json_parser_59; } if (yych <= '/') { goto basic_json_parser_32; } if (yych <= '9') { goto basic_json_parser_60; } goto basic_json_parser_32; } basic_json_parser_52: yych = *++m_cursor; if (yych == 'l') { goto basic_json_parser_62; } goto basic_json_parser_32; basic_json_parser_53: yych = *++m_cursor; if (yych == 'l') { goto basic_json_parser_63; } goto basic_json_parser_32; basic_json_parser_54: yych = *++m_cursor; if (yych == 'u') { goto basic_json_parser_64; } goto basic_json_parser_32; basic_json_parser_55: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= '@') { if (yych <= '/') { goto basic_json_parser_32; } if (yych <= '9') { goto basic_json_parser_65; } goto basic_json_parser_32; } else { if (yych <= 'F') { goto basic_json_parser_65; } if (yych <= '`') { goto basic_json_parser_32; } if (yych <= 'f') { goto basic_json_parser_65; } goto basic_json_parser_32; } basic_json_parser_56: yyaccept = 3; m_marker = ++m_cursor; if ((m_limit - m_cursor) < 3) { fill_line_buffer(3); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= 'D') { if (yych <= '/') { goto basic_json_parser_58; } if (yych <= '9') { goto basic_json_parser_56; } } else { if (yych <= 'E') { goto basic_json_parser_51; } if (yych == 'e') { goto basic_json_parser_51; } } basic_json_parser_58: { last_token_type = token_type::value_float; break; } basic_json_parser_59: yych = *++m_cursor; if (yych <= '/') { goto basic_json_parser_32; } if (yych >= ':') { goto basic_json_parser_32; } basic_json_parser_60: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= '/') { goto basic_json_parser_58; } if (yych <= '9') { goto basic_json_parser_60; } goto basic_json_parser_58; basic_json_parser_62: yych = *++m_cursor; if (yych == 's') { goto basic_json_parser_66; } goto basic_json_parser_32; basic_json_parser_63: yych = *++m_cursor; if (yych == 'l') { goto basic_json_parser_67; } goto basic_json_parser_32; basic_json_parser_64: yych = *++m_cursor; if (yych == 'e') { goto basic_json_parser_69; } goto basic_json_parser_32; basic_json_parser_65: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= '@') { if (yych <= '/') { goto basic_json_parser_32; } if (yych <= '9') { goto basic_json_parser_71; } goto basic_json_parser_32; } else { if (yych <= 'F') { goto basic_json_parser_71; } if (yych <= '`') { goto basic_json_parser_32; } if (yych <= 'f') { goto basic_json_parser_71; } goto basic_json_parser_32; } basic_json_parser_66: yych = *++m_cursor; if (yych == 'e') { goto basic_json_parser_72; } goto basic_json_parser_32; basic_json_parser_67: ++m_cursor; { last_token_type = token_type::literal_null; break; } basic_json_parser_69: ++m_cursor; { last_token_type = token_type::literal_true; break; } basic_json_parser_71: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= '@') { if (yych <= '/') { goto basic_json_parser_32; } if (yych <= '9') { goto basic_json_parser_74; } goto basic_json_parser_32; } else { if (yych <= 'F') { goto basic_json_parser_74; } if (yych <= '`') { goto basic_json_parser_32; } if (yych <= 'f') { goto basic_json_parser_74; } goto basic_json_parser_32; } basic_json_parser_72: ++m_cursor; { last_token_type = token_type::literal_false; break; } basic_json_parser_74: ++m_cursor; if (m_limit <= m_cursor) { fill_line_buffer(1); // LCOV_EXCL_LINE } yych = *m_cursor; if (yych <= '@') { if (yych <= '/') { goto basic_json_parser_32; } if (yych <= '9') { goto basic_json_parser_30; } goto basic_json_parser_32; } else { if (yych <= 'F') { goto basic_json_parser_30; } if (yych <= '`') { goto basic_json_parser_32; } if (yych <= 'f') { goto basic_json_parser_30; } goto basic_json_parser_32; } } } return last_token_type; } /*! @brief append data from the stream to the line buffer This function is called by the scan() function when the end of the buffer (`m_limit`) is reached and the `m_cursor` pointer cannot be incremented without leaving the limits of the line buffer. Note re2c decides when to call this function. If the lexer reads from contiguous storage, there is no trailing null byte. Therefore, this function must make sure to add these padding null bytes. If the lexer reads from an input stream, this function reads the next line of the input. @pre p p p p p p u u u u u x . . . . . . ^ ^ ^ ^ m_content m_start | m_limit m_cursor @post u u u u u x x x x x x x . . . . . . ^ ^ ^ | m_cursor m_limit m_start m_content */ void fill_line_buffer(size_t n = 0) { // if line buffer is used, m_content points to its data assert(m_line_buffer.empty() or m_content == reinterpret_cast(m_line_buffer.data())); // if line buffer is used, m_limit is set past the end of its data assert(m_line_buffer.empty() or m_limit == m_content + m_line_buffer.size()); // pointer relationships assert(m_content <= m_start); assert(m_start <= m_cursor); assert(m_cursor <= m_limit); assert(m_marker == nullptr or m_marker <= m_limit); // number of processed characters (p) const auto num_processed_chars = static_cast(m_start - m_content); // offset for m_marker wrt. to m_start const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start; // number of unprocessed characters (u) const auto offset_cursor = m_cursor - m_start; // no stream is used or end of file is reached if (m_stream == nullptr or m_stream->eof()) { // m_start may or may not be pointing into m_line_buffer at // this point. We trust the standard library to do the right // thing. See http://stackoverflow.com/q/28142011/266378 m_line_buffer.assign(m_start, m_limit); // append n characters to make sure that there is sufficient // space between m_cursor and m_limit m_line_buffer.append(1, '\x00'); if (n > 0) { m_line_buffer.append(n - 1, '\x01'); } } else { // delete processed characters from line buffer m_line_buffer.erase(0, num_processed_chars); // read next line from input stream m_line_buffer_tmp.clear(); std::getline(*m_stream, m_line_buffer_tmp, '\n'); // add line with newline symbol to the line buffer m_line_buffer += m_line_buffer_tmp; m_line_buffer.push_back('\n'); } // set pointers m_content = reinterpret_cast(m_line_buffer.data()); assert(m_content != nullptr); m_start = m_content; m_marker = m_start + offset_marker; m_cursor = m_start + offset_cursor; m_limit = m_start + m_line_buffer.size(); } /// return string representation of last read token string_t get_token_string() const { assert(m_start != nullptr); return string_t(reinterpret_cast(m_start), static_cast(m_cursor - m_start)); } /*! @brief return string value for string tokens The function iterates the characters between the opening and closing quotes of the string value. The complete string is the range [m_start,m_cursor). Consequently, we iterate from m_start+1 to m_cursor-1. We differentiate two cases: 1. Escaped characters. In this case, a new character is constructed according to the nature of the escape. Some escapes create new characters (e.g., `"\\n"` is replaced by `"\n"`), some are copied as is (e.g., `"\\\\"`). Furthermore, Unicode escapes of the shape `"\\uxxxx"` need special care. In this case, to_unicode takes care of the construction of the values. 2. Unescaped characters are copied as is. @pre `m_cursor - m_start >= 2`, meaning the length of the last token is at least 2 bytes which is trivially true for any string (which consists of at least two quotes). " c1 c2 c3 ... " ^ ^ m_start m_cursor @complexity Linear in the length of the string.\n Lemma: The loop body will always terminate.\n Proof (by contradiction): Assume the loop body does not terminate. As the loop body does not contain another loop, one of the called functions must never return. The called functions are `std::strtoul` and to_unicode. Neither function can loop forever, so the loop body will never loop forever which contradicts the assumption that the loop body does not terminate, q.e.d.\n Lemma: The loop condition for the for loop is eventually false.\n Proof (by contradiction): Assume the loop does not terminate. Due to the above lemma, this can only be due to a tautological loop condition; that is, the loop condition i < m_cursor - 1 must always be true. Let x be the change of i for any loop iteration. Then m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. This can be rephrased to m_cursor - m_start - 2 > x. With the precondition, we x <= 0, meaning that the loop condition holds indefinitely if i is always decreased. However, observe that the value of i is strictly increasing with each iteration, as it is incremented by 1 in the iteration expression and never decremented inside the loop body. Hence, the loop condition will eventually be false which contradicts the assumption that the loop condition is a tautology, q.e.d. @return string value of current token without opening and closing quotes @throw std::out_of_range if to_unicode fails */ string_t get_string() const { assert(m_cursor - m_start >= 2); string_t result; result.reserve(static_cast(m_cursor - m_start - 2)); // iterate the result between the quotes for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i) { // find next escape character auto e = std::find(i, m_cursor - 1, '\\'); if (e != i) { // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705 for (auto k = i; k < e; k++) { result.push_back(static_cast(*k)); } i = e - 1; // -1 because of ++i } else { // processing escaped character // read next character ++i; switch (*i) { // the default escapes case 't': { result += "\t"; break; } case 'b': { result += "\b"; break; } case 'f': { result += "\f"; break; } case 'n': { result += "\n"; break; } case 'r': { result += "\r"; break; } case '\\': { result += "\\"; break; } case '/': { result += "/"; break; } case '"': { result += "\""; break; } // unicode case 'u': { // get code xxxx from uxxxx auto codepoint = std::strtoul(std::string(reinterpret_cast(i + 1), 4).c_str(), nullptr, 16); // check if codepoint is a high surrogate if (codepoint >= 0xD800 and codepoint <= 0xDBFF) { // make sure there is a subsequent unicode if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u') { JSON_THROW(std::invalid_argument("missing low surrogate")); } // get code yyyy from uxxxx\uyyyy auto codepoint2 = std::strtoul(std::string(reinterpret_cast (i + 7), 4).c_str(), nullptr, 16); result += to_unicode(codepoint, codepoint2); // skip the next 10 characters (xxxx\uyyyy) i += 10; } else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF) { // we found a lone low surrogate JSON_THROW(std::invalid_argument("missing high surrogate")); } else { // add unicode character(s) result += to_unicode(codepoint); // skip the next four characters (xxxx) i += 4; } break; } } } } return result; } /*! @brief parse string into a built-in arithmetic type as if the current locale is POSIX. @note in floating-point case strtod may parse past the token's end - this is not an error @note any leading blanks are not handled */ struct strtonum { public: strtonum(const char* start, const char* end) : m_start(start), m_end(end) {} /*! @return true iff parsed successfully as number of type T @param[in,out] val shall contain parsed value, or undefined value if could not parse */ template::value>::type> bool to(T& val) const { return parse(val, std::is_integral()); } private: const char* const m_start = nullptr; const char* const m_end = nullptr; // floating-point conversion // overloaded wrappers for strtod/strtof/strtold // that will be called from parse static void strtof(float& f, const char* str, char** endptr) { f = std::strtof(str, endptr); } static void strtof(double& f, const char* str, char** endptr) { f = std::strtod(str, endptr); } static void strtof(long double& f, const char* str, char** endptr) { f = std::strtold(str, endptr); } template bool parse(T& value, /*is_integral=*/std::false_type) const { // replace decimal separator with locale-specific version, // when necessary; data will point to either the original // string, or buf, or tempstr containing the fixed string. std::string tempstr; std::array buf; const size_t len = static_cast(m_end - m_start); // lexer will reject empty numbers assert(len > 0); // since dealing with strtod family of functions, we're // getting the decimal point char from the C locale facilities // instead of C++'s numpunct facet of the current std::locale const auto loc = localeconv(); assert(loc != nullptr); const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0]; const char* data = m_start; if (decimal_point_char != '.') { const size_t ds_pos = static_cast(std::find(m_start, m_end, '.') - m_start); if (ds_pos != len) { // copy the data into the local buffer or tempstr, if // buffer is too small; replace decimal separator, and // update data to point to the modified bytes if ((len + 1) < buf.size()) { std::copy(m_start, m_end, buf.begin()); buf[len] = 0; buf[ds_pos] = decimal_point_char; data = buf.data(); } else { tempstr.assign(m_start, m_end); tempstr[ds_pos] = decimal_point_char; data = tempstr.c_str(); } } } char* endptr = nullptr; value = 0; // this calls appropriate overload depending on T strtof(value, data, &endptr); // parsing was successful iff strtof parsed exactly the number // of characters determined by the lexer (len) const bool ok = (endptr == (data + len)); if (ok and (value == static_cast(0.0)) and (*data == '-')) { // some implementations forget to negate the zero value = -0.0; } return ok; } // integral conversion signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const { return std::strtoll(m_start, endptr, 10); } unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const { return std::strtoull(m_start, endptr, 10); } template bool parse(T& value, /*is_integral=*/std::true_type) const { char* endptr = nullptr; errno = 0; // these are thread-local const auto x = parse_integral(&endptr, std::is_signed()); // called right overload? static_assert(std::is_signed() == std::is_signed(), ""); value = static_cast(x); return (x == static_cast(value)) // x fits into destination T and (x < 0) == (value < 0) // preserved sign //and ((x != 0) or is_integral()) // strto[u]ll did nto fail and (errno == 0) // strto[u]ll did not overflow and (m_start < m_end) // token was not empty and (endptr == m_end); // parsed entire token exactly } }; /*! @brief return number value for number tokens This function translates the last token into the most appropriate number type (either integer, unsigned integer or floating point), which is passed back to the caller via the result parameter. integral numbers that don't fit into the the range of the respective type are parsed as number_float_t floating-point values do not satisfy std::isfinite predicate are converted to value_t::null throws if the entire string [m_start .. m_cursor) cannot be interpreted as a number @param[out] result @ref basic_json object to receive the number. @param[in] token the type of the number token */ bool get_number(basic_json& result, const token_type token) const { assert(m_start != nullptr); assert(m_start < m_cursor); assert((token == token_type::value_unsigned) or (token == token_type::value_integer) or (token == token_type::value_float)); strtonum num_converter(reinterpret_cast(m_start), reinterpret_cast(m_cursor)); switch (token) { case lexer::token_type::value_unsigned: { number_unsigned_t val; if (num_converter.to(val)) { // parsing successful result.m_type = value_t::number_unsigned; result.m_value = val; return true; } break; } case lexer::token_type::value_integer: { number_integer_t val; if (num_converter.to(val)) { // parsing successful result.m_type = value_t::number_integer; result.m_value = val; return true; } break; } default: { break; } } // parse float (either explicitly or because a previous conversion // failed) number_float_t val; if (num_converter.to(val)) { // parsing successful result.m_type = value_t::number_float; result.m_value = val; // replace infinity and NAN by null if (not std::isfinite(result.m_value.number_float)) { result.m_type = value_t::null; result.m_value = basic_json::json_value(); } return true; } // couldn't parse number in any format return false; } private: /// optional input stream std::istream* m_stream = nullptr; /// line buffer buffer for m_stream string_t m_line_buffer {}; /// used for filling m_line_buffer string_t m_line_buffer_tmp {}; /// the buffer pointer const lexer_char_t* m_content = nullptr; /// pointer to the beginning of the current symbol const lexer_char_t* m_start = nullptr; /// pointer for backtracking information const lexer_char_t* m_marker = nullptr; /// pointer to the current symbol const lexer_char_t* m_cursor = nullptr; /// pointer to the end of the buffer const lexer_char_t* m_limit = nullptr; /// the last token type token_type last_token_type = token_type::end_of_input; }; /*! @brief syntax analysis This class implements a recursive decent parser. */ class parser { public: /// a parser reading from a string literal parser(const char* buff, const parser_callback_t cb = nullptr) : callback(cb), m_lexer(reinterpret_cast(buff), std::strlen(buff)) {} /// a parser reading from an input stream parser(std::istream& is, const parser_callback_t cb = nullptr) : callback(cb), m_lexer(is) {} /// a parser reading from an iterator range with contiguous storage template::iterator_category, std::random_access_iterator_tag>::value , int>::type = 0> parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr) : callback(cb), m_lexer(reinterpret_cast(&(*first)), static_cast(std::distance(first, last))) {} /// public parser interface basic_json parse() { // read first token get_token(); basic_json result = parse_internal(true); result.assert_invariant(); expect(lexer::token_type::end_of_input); // return parser result and replace it with null in case the // top-level value was discarded by the callback function return result.is_discarded() ? basic_json() : std::move(result); } private: /// the actual parser basic_json parse_internal(bool keep) { auto result = basic_json(value_t::discarded); switch (last_token) { case lexer::token_type::begin_object: { if (keep and (not callback or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0))) { // explicitly set result to object to cope with {} result.m_type = value_t::object; result.m_value = value_t::object; } // read next token get_token(); // closing } -> we are done if (last_token == lexer::token_type::end_object) { get_token(); if (keep and callback and not callback(--depth, parse_event_t::object_end, result)) { result = basic_json(value_t::discarded); } return result; } // no comma is expected here unexpect(lexer::token_type::value_separator); // otherwise: parse key-value pairs do { // ugly, but could be fixed with loop reorganization if (last_token == lexer::token_type::value_separator) { get_token(); } // store key expect(lexer::token_type::value_string); const auto key = m_lexer.get_string(); bool keep_tag = false; if (keep) { if (callback) { basic_json k(key); keep_tag = callback(depth, parse_event_t::key, k); } else { keep_tag = true; } } // parse separator (:) get_token(); expect(lexer::token_type::name_separator); // parse and add value get_token(); auto value = parse_internal(keep); if (keep and keep_tag and not value.is_discarded()) { result[key] = std::move(value); } } while (last_token == lexer::token_type::value_separator); // closing } expect(lexer::token_type::end_object); get_token(); if (keep and callback and not callback(--depth, parse_event_t::object_end, result)) { result = basic_json(value_t::discarded); } return result; } case lexer::token_type::begin_array: { if (keep and (not callback or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0))) { // explicitly set result to object to cope with [] result.m_type = value_t::array; result.m_value = value_t::array; } // read next token get_token(); // closing ] -> we are done if (last_token == lexer::token_type::end_array) { get_token(); if (callback and not callback(--depth, parse_event_t::array_end, result)) { result = basic_json(value_t::discarded); } return result; } // no comma is expected here unexpect(lexer::token_type::value_separator); // otherwise: parse values do { // ugly, but could be fixed with loop reorganization if (last_token == lexer::token_type::value_separator) { get_token(); } // parse value auto value = parse_internal(keep); if (keep and not value.is_discarded()) { result.push_back(std::move(value)); } } while (last_token == lexer::token_type::value_separator); // closing ] expect(lexer::token_type::end_array); get_token(); if (keep and callback and not callback(--depth, parse_event_t::array_end, result)) { result = basic_json(value_t::discarded); } return result; } case lexer::token_type::literal_null: { get_token(); result.m_type = value_t::null; break; } case lexer::token_type::value_string: { const auto s = m_lexer.get_string(); get_token(); result = basic_json(s); break; } case lexer::token_type::literal_true: { get_token(); result.m_type = value_t::boolean; result.m_value = true; break; } case lexer::token_type::literal_false: { get_token(); result.m_type = value_t::boolean; result.m_value = false; break; } case lexer::token_type::value_unsigned: case lexer::token_type::value_integer: case lexer::token_type::value_float: { m_lexer.get_number(result, last_token); get_token(); break; } default: { // the last token was unexpected unexpect(last_token); } } if (keep and callback and not callback(depth, parse_event_t::value, result)) { result = basic_json(value_t::discarded); } return result; } /// get next token from lexer typename lexer::token_type get_token() { last_token = m_lexer.scan(); return last_token; } void expect(typename lexer::token_type t) const { if (t != last_token) { std::string error_msg = "parse error - unexpected "; error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + "'") : lexer::token_type_name(last_token)); error_msg += "; expected " + lexer::token_type_name(t); JSON_THROW(std::invalid_argument(error_msg)); } } void unexpect(typename lexer::token_type t) const { if (t == last_token) { std::string error_msg = "parse error - unexpected "; error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + "'") : lexer::token_type_name(last_token)); JSON_THROW(std::invalid_argument(error_msg)); } } private: /// current level of recursion int depth = 0; /// callback function const parser_callback_t callback = nullptr; /// the type of the last read token typename lexer::token_type last_token = lexer::token_type::uninitialized; /// the lexer lexer m_lexer; }; public: /*! @brief JSON Pointer A JSON pointer defines a string syntax for identifying a specific value within a JSON document. It can be used with functions `at` and `operator[]`. Furthermore, JSON pointers are the base for JSON patches. @sa [RFC 6901](https://tools.ietf.org/html/rfc6901) @since version 2.0.0 */ class json_pointer { /// allow basic_json to access private members friend class basic_json; public: /*! @brief create JSON pointer Create a JSON pointer according to the syntax described in [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3). @param[in] s string representing the JSON pointer; if omitted, the empty string is assumed which references the whole JSON value @throw std::domain_error if reference token is nonempty and does not begin with a slash (`/`); example: `"JSON pointer must be empty or begin with /"` @throw std::domain_error if a tilde (`~`) is not followed by `0` (representing `~`) or `1` (representing `/`); example: `"escape error: ~ must be followed with 0 or 1"` @liveexample{The example shows the construction several valid JSON pointers as well as the exceptional behavior.,json_pointer} @since version 2.0.0 */ explicit json_pointer(const std::string& s = "") : reference_tokens(split(s)) {} /*! @brief return a string representation of the JSON pointer @invariant For each JSON pointer `ptr`, it holds: @code {.cpp} ptr == json_pointer(ptr.to_string()); @endcode @return a string representation of the JSON pointer @liveexample{The example shows the result of `to_string`., json_pointer__to_string} @since version 2.0.0 */ std::string to_string() const noexcept { return std::accumulate(reference_tokens.begin(), reference_tokens.end(), std::string{}, [](const std::string & a, const std::string & b) { return a + "/" + escape(b); }); } /// @copydoc to_string() operator std::string() const { return to_string(); } private: /// remove and return last reference pointer std::string pop_back() { if (is_root()) { JSON_THROW(std::domain_error("JSON pointer has no parent")); } auto last = reference_tokens.back(); reference_tokens.pop_back(); return last; } /// return whether pointer points to the root document bool is_root() const { return reference_tokens.empty(); } json_pointer top() const { if (is_root()) { JSON_THROW(std::domain_error("JSON pointer has no parent")); } json_pointer result = *this; result.reference_tokens = {reference_tokens[0]}; return result; } /*! @brief create and return a reference to the pointed to value @complexity Linear in the number of reference tokens. */ reference get_and_create(reference j) const { pointer result = &j; // in case no reference tokens exist, return a reference to the // JSON value j which will be overwritten by a primitive value for (const auto& reference_token : reference_tokens) { switch (result->m_type) { case value_t::null: { if (reference_token == "0") { // start a new array if reference token is 0 result = &result->operator[](0); } else { // start a new object otherwise result = &result->operator[](reference_token); } break; } case value_t::object: { // create an entry in the object result = &result->operator[](reference_token); break; } case value_t::array: { // create an entry in the array result = &result->operator[](static_cast(std::stoi(reference_token))); break; } /* The following code is only reached if there exists a reference token _and_ the current value is primitive. In this case, we have an error situation, because primitive values may only occur as single value; that is, with an empty list of reference tokens. */ default: { JSON_THROW(std::domain_error("invalid value to unflatten")); } } } return *result; } /*! @brief return a reference to the pointed to value @note This version does not throw if a value is not present, but tries to create nested values instead. For instance, calling this function with pointer `"/this/that"` on a null value is equivalent to calling `operator[]("this").operator[]("that")` on that value, effectively changing the null value to an object. @param[in] ptr a JSON value @return reference to the JSON value pointed to by the JSON pointer @complexity Linear in the length of the JSON pointer. @throw std::out_of_range if the JSON pointer can not be resolved @throw std::domain_error if an array index begins with '0' @throw std::invalid_argument if an array index was not a number */ reference get_unchecked(pointer ptr) const { for (const auto& reference_token : reference_tokens) { // convert null values to arrays or objects before continuing if (ptr->m_type == value_t::null) { // check if reference token is a number const bool nums = std::all_of(reference_token.begin(), reference_token.end(), [](const char x) { return std::isdigit(x); }); // change value to array for numbers or "-" or to object // otherwise if (nums or reference_token == "-") { *ptr = value_t::array; } else { *ptr = value_t::object; } } switch (ptr->m_type) { case value_t::object: { // use unchecked object access ptr = &ptr->operator[](reference_token); break; } case value_t::array: { // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { JSON_THROW(std::domain_error("array index must not begin with '0'")); } if (reference_token == "-") { // explicitly treat "-" as index beyond the end ptr = &ptr->operator[](ptr->m_value.array->size()); } else { // convert array index to number; unchecked access ptr = &ptr->operator[](static_cast(std::stoi(reference_token))); } break; } default: { JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'")); } } } return *ptr; } reference get_checked(pointer ptr) const { for (const auto& reference_token : reference_tokens) { switch (ptr->m_type) { case value_t::object: { // note: at performs range check ptr = &ptr->at(reference_token); break; } case value_t::array: { if (reference_token == "-") { // "-" always fails the range check JSON_THROW(std::out_of_range("array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { JSON_THROW(std::domain_error("array index must not begin with '0'")); } // note: at performs range check ptr = &ptr->at(static_cast(std::stoi(reference_token))); break; } default: { JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'")); } } } return *ptr; } /*! @brief return a const reference to the pointed to value @param[in] ptr a JSON value @return const reference to the JSON value pointed to by the JSON pointer */ const_reference get_unchecked(const_pointer ptr) const { for (const auto& reference_token : reference_tokens) { switch (ptr->m_type) { case value_t::object: { // use unchecked object access ptr = &ptr->operator[](reference_token); break; } case value_t::array: { if (reference_token == "-") { // "-" cannot be used for const access JSON_THROW(std::out_of_range("array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { JSON_THROW(std::domain_error("array index must not begin with '0'")); } // use unchecked array access ptr = &ptr->operator[](static_cast(std::stoi(reference_token))); break; } default: { JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'")); } } } return *ptr; } const_reference get_checked(const_pointer ptr) const { for (const auto& reference_token : reference_tokens) { switch (ptr->m_type) { case value_t::object: { // note: at performs range check ptr = &ptr->at(reference_token); break; } case value_t::array: { if (reference_token == "-") { // "-" always fails the range check JSON_THROW(std::out_of_range("array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { JSON_THROW(std::domain_error("array index must not begin with '0'")); } // note: at performs range check ptr = &ptr->at(static_cast(std::stoi(reference_token))); break; } default: { JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'")); } } } return *ptr; } /// split the string input to reference tokens static std::vector split(const std::string& reference_string) { std::vector result; // special case: empty reference string -> no reference tokens if (reference_string.empty()) { return result; } // check if nonempty reference string begins with slash if (reference_string[0] != '/') { JSON_THROW(std::domain_error("JSON pointer must be empty or begin with '/'")); } // extract the reference tokens: // - slash: position of the last read slash (or end of string) // - start: position after the previous slash for ( // search for the first slash after the first character size_t slash = reference_string.find_first_of('/', 1), // set the beginning of the first reference token start = 1; // we can stop if start == string::npos+1 = 0 start != 0; // set the beginning of the next reference token // (will eventually be 0 if slash == std::string::npos) start = slash + 1, // find next slash slash = reference_string.find_first_of('/', start)) { // use the text between the beginning of the reference token // (start) and the last slash (slash). auto reference_token = reference_string.substr(start, slash - start); // check reference tokens are properly escaped for (size_t pos = reference_token.find_first_of('~'); pos != std::string::npos; pos = reference_token.find_first_of('~', pos + 1)) { assert(reference_token[pos] == '~'); // ~ must be followed by 0 or 1 if (pos == reference_token.size() - 1 or (reference_token[pos + 1] != '0' and reference_token[pos + 1] != '1')) { JSON_THROW(std::domain_error("escape error: '~' must be followed with '0' or '1'")); } } // finally, store the reference token unescape(reference_token); result.push_back(reference_token); } return result; } private: /*! @brief replace all occurrences of a substring by another string @param[in,out] s the string to manipulate; changed so that all occurrences of @a f are replaced with @a t @param[in] f the substring to replace with @a t @param[in] t the string to replace @a f @pre The search string @a f must not be empty. @since version 2.0.0 */ static void replace_substring(std::string& s, const std::string& f, const std::string& t) { assert(not f.empty()); for ( size_t pos = s.find(f); // find first occurrence of f pos != std::string::npos; // make sure f was found s.replace(pos, f.size(), t), // replace with t pos = s.find(f, pos + t.size()) // find next occurrence of f ); } /// escape tilde and slash static std::string escape(std::string s) { // escape "~"" to "~0" and "/" to "~1" replace_substring(s, "~", "~0"); replace_substring(s, "/", "~1"); return s; } /// unescape tilde and slash static void unescape(std::string& s) { // first transform any occurrence of the sequence '~1' to '/' replace_substring(s, "~1", "/"); // then transform any occurrence of the sequence '~0' to '~' replace_substring(s, "~0", "~"); } /*! @param[in] reference_string the reference string to the current value @param[in] value the value to consider @param[in,out] result the result object to insert values to @note Empty objects or arrays are flattened to `null`. */ static void flatten(const std::string& reference_string, const basic_json& value, basic_json& result) { switch (value.m_type) { case value_t::array: { if (value.m_value.array->empty()) { // flatten empty array as null result[reference_string] = nullptr; } else { // iterate array and use index as reference string for (size_t i = 0; i < value.m_value.array->size(); ++i) { flatten(reference_string + "/" + std::to_string(i), value.m_value.array->operator[](i), result); } } break; } case value_t::object: { if (value.m_value.object->empty()) { // flatten empty object as null result[reference_string] = nullptr; } else { // iterate object and use keys as reference string for (const auto& element : *value.m_value.object) { flatten(reference_string + "/" + escape(element.first), element.second, result); } } break; } default: { // add primitive value with its reference string result[reference_string] = value; break; } } } /*! @param[in] value flattened JSON @return unflattened JSON */ static basic_json unflatten(const basic_json& value) { if (not value.is_object()) { JSON_THROW(std::domain_error("only objects can be unflattened")); } basic_json result; // iterate the JSON object values for (const auto& element : *value.m_value.object) { if (not element.second.is_primitive()) { JSON_THROW(std::domain_error("values in object must be primitive")); } // assign value to reference pointed to by JSON pointer; Note // that if the JSON pointer is "" (i.e., points to the whole // value), function get_and_create returns a reference to // result itself. An assignment will then create a primitive // value. json_pointer(element.first).get_and_create(result) = element.second; } return result; } private: friend bool operator==(json_pointer const& lhs, json_pointer const& rhs) noexcept { return lhs.reference_tokens == rhs.reference_tokens; } friend bool operator!=(json_pointer const& lhs, json_pointer const& rhs) noexcept { return !(lhs == rhs); } /// the reference tokens std::vector reference_tokens {}; }; ////////////////////////// // JSON Pointer support // ////////////////////////// /// @name JSON Pointer functions /// @{ /*! @brief access specified element via JSON Pointer Uses a JSON pointer to retrieve a reference to the respective JSON value. No bound checking is performed. Similar to @ref operator[](const typename object_t::key_type&), `null` values are created in arrays and objects if necessary. In particular: - If the JSON pointer points to an object key that does not exist, it is created an filled with a `null` value before a reference to it is returned. - If the JSON pointer points to an array index that does not exist, it is created an filled with a `null` value before a reference to it is returned. All indices between the current maximum and the given index are also filled with `null`. - The special value `-` is treated as a synonym for the index past the end. @param[in] ptr a JSON pointer @return reference to the element pointed to by @a ptr @complexity Constant. @throw std::out_of_range if the JSON pointer can not be resolved @throw std::domain_error if an array index begins with '0' @throw std::invalid_argument if an array index was not a number @liveexample{The behavior is shown in the example.,operatorjson_pointer} @since version 2.0.0 */ reference operator[](const json_pointer& ptr) { return ptr.get_unchecked(this); } /*! @brief access specified element via JSON Pointer Uses a JSON pointer to retrieve a reference to the respective JSON value. No bound checking is performed. The function does not change the JSON value; no `null` values are created. In particular, the the special value `-` yields an exception. @param[in] ptr JSON pointer to the desired element @return const reference to the element pointed to by @a ptr @complexity Constant. @throw std::out_of_range if the JSON pointer can not be resolved @throw std::domain_error if an array index begins with '0' @throw std::invalid_argument if an array index was not a number @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} @since version 2.0.0 */ const_reference operator[](const json_pointer& ptr) const { return ptr.get_unchecked(this); } /*! @brief access specified element via JSON Pointer Returns a reference to the element at with specified JSON pointer @a ptr, with bounds checking. @param[in] ptr JSON pointer to the desired element @return reference to the element pointed to by @a ptr @complexity Constant. @throw std::out_of_range if the JSON pointer can not be resolved @throw std::domain_error if an array index begins with '0' @throw std::invalid_argument if an array index was not a number @liveexample{The behavior is shown in the example.,at_json_pointer} @since version 2.0.0 */ reference at(const json_pointer& ptr) { return ptr.get_checked(this); } /*! @brief access specified element via JSON Pointer Returns a const reference to the element at with specified JSON pointer @a ptr, with bounds checking. @param[in] ptr JSON pointer to the desired element @return reference to the element pointed to by @a ptr @complexity Constant. @throw std::out_of_range if the JSON pointer can not be resolved @throw std::domain_error if an array index begins with '0' @throw std::invalid_argument if an array index was not a number @liveexample{The behavior is shown in the example.,at_json_pointer_const} @since version 2.0.0 */ const_reference at(const json_pointer& ptr) const { return ptr.get_checked(this); } /*! @brief return flattened JSON value The function creates a JSON object whose keys are JSON pointers (see [RFC 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all primitive. The original JSON value can be restored using the @ref unflatten() function. @return an object that maps JSON pointers to primitive values @note Empty objects and arrays are flattened to `null` and will not be reconstructed correctly by the @ref unflatten() function. @complexity Linear in the size the JSON value. @liveexample{The following code shows how a JSON object is flattened to an object whose keys consist of JSON pointers.,flatten} @sa @ref unflatten() for the reverse function @since version 2.0.0 */ basic_json flatten() const { basic_json result(value_t::object); json_pointer::flatten("", *this, result); return result; } /*! @brief unflatten a previously flattened JSON value The function restores the arbitrary nesting of a JSON value that has been flattened before using the @ref flatten() function. The JSON value must meet certain constraints: 1. The value must be an object. 2. The keys must be JSON pointers (see [RFC 6901](https://tools.ietf.org/html/rfc6901)) 3. The mapped values must be primitive JSON types. @return the original JSON from a flattened version @note Empty objects and arrays are flattened by @ref flatten() to `null` values and can not unflattened to their original type. Apart from this example, for a JSON value `j`, the following is always true: `j == j.flatten().unflatten()`. @complexity Linear in the size the JSON value. @liveexample{The following code shows how a flattened JSON object is unflattened into the original nested JSON object.,unflatten} @sa @ref flatten() for the reverse function @since version 2.0.0 */ basic_json unflatten() const { return json_pointer::unflatten(*this); } /// @} ////////////////////////// // JSON Patch functions // ////////////////////////// /// @name JSON Patch functions /// @{ /*! @brief applies a JSON patch [JSON Patch](http://jsonpatch.com) defines a JSON document structure for expressing a sequence of operations to apply to a JSON) document. With this function, a JSON Patch is applied to the current JSON value by executing all operations from the patch. @param[in] json_patch JSON patch document @return patched document @note The application of a patch is atomic: Either all operations succeed and the patched document is returned or an exception is thrown. In any case, the original value is not changed: the patch is applied to a copy of the value. @throw std::out_of_range if a JSON pointer inside the patch could not be resolved successfully in the current JSON value; example: `"key baz not found"` @throw invalid_argument if the JSON patch is malformed (e.g., mandatory attributes are missing); example: `"operation add must have member path"` @complexity Linear in the size of the JSON value and the length of the JSON patch. As usually only a fraction of the JSON value is affected by the patch, the complexity can usually be neglected. @liveexample{The following code shows how a JSON patch is applied to a value.,patch} @sa @ref diff -- create a JSON patch by comparing two JSON values @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901) @since version 2.0.0 */ basic_json patch(const basic_json& json_patch) const { // make a working copy to apply the patch to basic_json result = *this; // the valid JSON Patch operations enum class patch_operations {add, remove, replace, move, copy, test, invalid}; const auto get_op = [](const std::string op) { if (op == "add") { return patch_operations::add; } if (op == "remove") { return patch_operations::remove; } if (op == "replace") { return patch_operations::replace; } if (op == "move") { return patch_operations::move; } if (op == "copy") { return patch_operations::copy; } if (op == "test") { return patch_operations::test; } return patch_operations::invalid; }; // wrapper for "add" operation; add value at ptr const auto operation_add = [&result](json_pointer & ptr, basic_json val) { // adding to the root of the target document means replacing it if (ptr.is_root()) { result = val; } else { // make sure the top element of the pointer exists json_pointer top_pointer = ptr.top(); if (top_pointer != ptr) { result.at(top_pointer); } // get reference to parent of JSON pointer ptr const auto last_path = ptr.pop_back(); basic_json& parent = result[ptr]; switch (parent.m_type) { case value_t::null: case value_t::object: { // use operator[] to add value parent[last_path] = val; break; } case value_t::array: { if (last_path == "-") { // special case: append to back parent.push_back(val); } else { const auto idx = std::stoi(last_path); if (static_cast(idx) > parent.size()) { // avoid undefined behavior JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range")); } else { // default case: insert add offset parent.insert(parent.begin() + static_cast(idx), val); } } break; } default: { // if there exists a parent it cannot be primitive assert(false); // LCOV_EXCL_LINE } } } }; // wrapper for "remove" operation; remove value at ptr const auto operation_remove = [&result](json_pointer & ptr) { // get reference to parent of JSON pointer ptr const auto last_path = ptr.pop_back(); basic_json& parent = result.at(ptr); // remove child if (parent.is_object()) { // perform range check auto it = parent.find(last_path); if (it != parent.end()) { parent.erase(it); } else { JSON_THROW(std::out_of_range("key '" + last_path + "' not found")); } } else if (parent.is_array()) { // note erase performs range check parent.erase(static_cast(std::stoi(last_path))); } }; // type check if (not json_patch.is_array()) { // a JSON patch must be an array of objects JSON_THROW(std::invalid_argument("JSON patch must be an array of objects")); } // iterate and apply the operations for (const auto& val : json_patch) { // wrapper to get a value for an operation const auto get_value = [&val](const std::string & op, const std::string & member, bool string_type) -> basic_json& { // find value auto it = val.m_value.object->find(member); // context-sensitive error message const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; // check if desired value is present if (it == val.m_value.object->end()) { JSON_THROW(std::invalid_argument(error_msg + " must have member '" + member + "'")); } // check if result is of type string if (string_type and not it->second.is_string()) { JSON_THROW(std::invalid_argument(error_msg + " must have string member '" + member + "'")); } // no error: return value return it->second; }; // type check if (not val.is_object()) { JSON_THROW(std::invalid_argument("JSON patch must be an array of objects")); } // collect mandatory members const std::string op = get_value("op", "op", true); const std::string path = get_value(op, "path", true); json_pointer ptr(path); switch (get_op(op)) { case patch_operations::add: { operation_add(ptr, get_value("add", "value", false)); break; } case patch_operations::remove: { operation_remove(ptr); break; } case patch_operations::replace: { // the "path" location must exist - use at() result.at(ptr) = get_value("replace", "value", false); break; } case patch_operations::move: { const std::string from_path = get_value("move", "from", true); json_pointer from_ptr(from_path); // the "from" location must exist - use at() basic_json v = result.at(from_ptr); // The move operation is functionally identical to a // "remove" operation on the "from" location, followed // immediately by an "add" operation at the target // location with the value that was just removed. operation_remove(from_ptr); operation_add(ptr, v); break; } case patch_operations::copy: { const std::string from_path = get_value("copy", "from", true);; const json_pointer from_ptr(from_path); // the "from" location must exist - use at() result[ptr] = result.at(from_ptr); break; } case patch_operations::test: { bool success = false; JSON_TRY { // check if "value" matches the one at "path" // the "path" location must exist - use at() success = (result.at(ptr) == get_value("test", "value", false)); } JSON_CATCH (std::out_of_range&) { // ignore out of range errors: success remains false } // throw an exception if test fails if (not success) { JSON_THROW(std::domain_error("unsuccessful: " + val.dump())); } break; } case patch_operations::invalid: { // op must be "add", "remove", "replace", "move", "copy", or // "test" JSON_THROW(std::invalid_argument("operation value '" + op + "' is invalid")); } } } return result; } /*! @brief creates a diff as a JSON patch Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can be changed into the value @a target by calling @ref patch function. @invariant For two JSON values @a source and @a target, the following code yields always `true`: @code {.cpp} source.patch(diff(source, target)) == target; @endcode @note Currently, only `remove`, `add`, and `replace` operations are generated. @param[in] source JSON value to compare from @param[in] target JSON value to compare against @param[in] path helper value to create JSON pointers @return a JSON patch to convert the @a source to @a target @complexity Linear in the lengths of @a source and @a target. @liveexample{The following code shows how a JSON patch is created as a diff for two JSON values.,diff} @sa @ref patch -- apply a JSON patch @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) @since version 2.0.0 */ static basic_json diff(const basic_json& source, const basic_json& target, const std::string& path = "") { // the patch basic_json result(value_t::array); // if the values are the same, return empty patch if (source == target) { return result; } if (source.type() != target.type()) { // different types: replace value result.push_back( { {"op", "replace"}, {"path", path}, {"value", target} }); } else { switch (source.type()) { case value_t::array: { // first pass: traverse common elements size_t i = 0; while (i < source.size() and i < target.size()) { // recursive call to compare array values at index i auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); result.insert(result.end(), temp_diff.begin(), temp_diff.end()); ++i; } // i now reached the end of at least one array // in a second pass, traverse the remaining elements // remove my remaining elements const auto end_index = static_cast(result.size()); while (i < source.size()) { // add operations in reverse order to avoid invalid // indices result.insert(result.begin() + end_index, object( { {"op", "remove"}, {"path", path + "/" + std::to_string(i)} })); ++i; } // add other remaining elements while (i < target.size()) { result.push_back( { {"op", "add"}, {"path", path + "/" + std::to_string(i)}, {"value", target[i]} }); ++i; } break; } case value_t::object: { // first pass: traverse this object's elements for (auto it = source.begin(); it != source.end(); ++it) { // escape the key name to be used in a JSON patch const auto key = json_pointer::escape(it.key()); if (target.find(it.key()) != target.end()) { // recursive call to compare object values at key it auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key); result.insert(result.end(), temp_diff.begin(), temp_diff.end()); } else { // found a key that is not in o -> remove it result.push_back(object( { {"op", "remove"}, {"path", path + "/" + key} })); } } // second pass: traverse other object's elements for (auto it = target.begin(); it != target.end(); ++it) { if (source.find(it.key()) == source.end()) { // found a key that is not in this -> add it const auto key = json_pointer::escape(it.key()); result.push_back( { {"op", "add"}, {"path", path + "/" + key}, {"value", it.value()} }); } } break; } default: { // both primitive type: replace value result.push_back( { {"op", "replace"}, {"path", path}, {"value", target} }); break; } } } return result; } /// @} }; ///////////// // presets // ///////////// /*! @brief default JSON class This type is the default specialization of the @ref basic_json class which uses the standard template types. @since version 1.0.0 */ using json = basic_json<>; } // namespace nlohmann /////////////////////// // nonmember support // /////////////////////// // specialization of std::swap, and std::hash namespace std { /*! @brief exchanges the values of two JSON objects @since version 1.0.0 */ template<> inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( is_nothrow_move_constructible::value and is_nothrow_move_assignable::value ) { j1.swap(j2); } /// hash value for JSON objects template<> struct hash { /*! @brief return a hash value for a JSON object @since version 1.0.0 */ std::size_t operator()(const nlohmann::json& j) const { // a naive hashing via the string representation const auto& h = hash(); return h(j.dump()); } }; } // namespace std /*! @brief user-defined string literal for JSON values This operator implements a user-defined string literal for JSON objects. It can be used by adding `"_json"` to a string literal and returns a JSON object if no parse error occurred. @param[in] s a string representation of a JSON object @param[in] n the length of string @a s @return a JSON object @since version 1.0.0 */ inline nlohmann::json operator "" _json(const char* s, std::size_t n) { return nlohmann::json::parse(s, s + n); } /*! @brief user-defined string literal for JSON pointer This operator implements a user-defined string literal for JSON Pointers. It can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer object if no parse error occurred. @param[in] s a string representation of a JSON Pointer @param[in] n the length of string @a s @return a JSON pointer object @since version 2.0.0 */ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) { return nlohmann::json::json_pointer(std::string(s, n)); } // restore GCC/clang diagnostic settings #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) #pragma GCC diagnostic pop #endif // clean up #undef JSON_CATCH #undef JSON_DEPRECATED #undef JSON_THROW #undef JSON_TRY #endif measurement-kit-0.7.1/include/measurement_kit/ext/sole.hpp000066400000000000000000000011241315356162600237310ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. // ============================================================= // Derivative work of r-lyeh/sole@c61c49f10d. // See NOTICE for original license. #ifndef MEASUREMENT_KIT_EXT_SOLE_HPP #define MEASUREMENT_KIT_EXT_SOLE_HPP #include namespace mk { namespace sole { class uuid { public: std::string str(); uint64_t ab; uint64_t cd; }; uuid uuid4(); } // namespace sole } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/http/000077500000000000000000000000001315356162600224375ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/http/http.hpp000066400000000000000000000203101315356162600241230ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_HTTP_HTTP_HPP #define MEASUREMENT_KIT_HTTP_HTTP_HPP // Documentation: doc/api/http.md #include #include namespace mk { namespace http { /* _____ | ____|_ __ _ __ ___ _ __ ___ | _| | '__| '__/ _ \| '__/ __| | |___| | | | | (_) | | \__ \ |_____|_| |_| \___/|_| |___/ Error codes in the HTTP module. */ MK_DEFINE_ERR(MK_ERR_HTTP(0), UpgradeError, "http_upgrade_error") MK_DEFINE_ERR(MK_ERR_HTTP(1), ParserError, "http_parser_error") MK_DEFINE_ERR(MK_ERR_HTTP(2), UrlParserError, "http_url_parser_error") MK_DEFINE_ERR(MK_ERR_HTTP(3), MissingUrlSchemaError, "http_missing_url_schema") MK_DEFINE_ERR(MK_ERR_HTTP(4), MissingUrlHostError, "http_missing_url_host") MK_DEFINE_ERR(MK_ERR_HTTP(5), MissingUrlError, "http_missing_url") MK_DEFINE_ERR(MK_ERR_HTTP(6), HttpRequestFailedError, "http_request_failed") MK_DEFINE_ERR(MK_ERR_HTTP(7), HeaderParserInternalError, "http_parser_internal_error") MK_DEFINE_ERR(MK_ERR_HTTP(8), InvalidMaxRedirectsError, "http_invalid_max_redirects_setting") MK_DEFINE_ERR(MK_ERR_HTTP(9), InvalidRedirectUrlError, "http_invalid_redirect_url") MK_DEFINE_ERR(MK_ERR_HTTP(10), EmptyLocationError, "http_empty_location_header") MK_DEFINE_ERR(MK_ERR_HTTP(11), TooManyRedirectsError, "http_too_many_redirects") MK_DEFINE_ERR(MK_ERR_HTTP(12), ParserInvalidEofStateError, "http_parser_invalid_eof_state") MK_DEFINE_ERR(MK_ERR_HTTP(13), ParserHeaderOverflowError, "http_parser_header_overflow") MK_DEFINE_ERR(MK_ERR_HTTP(14), ParserClosedConnectionError, "http_parser_connection_closed") MK_DEFINE_ERR(MK_ERR_HTTP(15), ParserInvalidVersionError, "http_parser_invalid_version") MK_DEFINE_ERR(MK_ERR_HTTP(16), ParserInvalidStatusError, "http_parser_invalid_status") MK_DEFINE_ERR(MK_ERR_HTTP(17), ParserInvalidMethodError, "http_parser_invalid_method") MK_DEFINE_ERR(MK_ERR_HTTP(18), ParserInvalidUrlError, "http_parser_invalid_url") MK_DEFINE_ERR(MK_ERR_HTTP(19), ParserInvalidHostError, "http_parser_invalid_host") MK_DEFINE_ERR(MK_ERR_HTTP(20), ParserInvalidPortError, "http_parser_invalid_port") MK_DEFINE_ERR(MK_ERR_HTTP(21), ParserInvalidPathError, "http_parser_invalid_path") MK_DEFINE_ERR(MK_ERR_HTTP(22), ParserInvalidQueryStringError, "http_parser_invalid_query_string") MK_DEFINE_ERR(MK_ERR_HTTP(23), ParserInvalidFragmentError, "http_parser_invalid_fragment") MK_DEFINE_ERR(MK_ERR_HTTP(24), ParserLfExpectedError, "http_parser_expected_lf") MK_DEFINE_ERR(MK_ERR_HTTP(25), ParserInvalidHeaderTokenError, "http_parser_invalid_header_token") MK_DEFINE_ERR(MK_ERR_HTTP(26), ParserInvalidContentLengthError, "http_parser_invalid_content_length") MK_DEFINE_ERR(MK_ERR_HTTP(27), ParserUnexpectedContentLengthError, "http_parser_unexpected_content_length") MK_DEFINE_ERR(MK_ERR_HTTP(28), ParserInvalidChunkSizeError, "http_parser_invalid_chunk_size") MK_DEFINE_ERR(MK_ERR_HTTP(29), ParserInvalidConstantError, "http_parser_invalid_constant") MK_DEFINE_ERR(MK_ERR_HTTP(30), ParserInvalidInternalStateError, "http_parser_invalid_internal_state") MK_DEFINE_ERR(MK_ERR_HTTP(31), ParserStrictModeAssertionError, "http_parser_strict_mode_assertion") MK_DEFINE_ERR(MK_ERR_HTTP(32), ParserPausedError, "http_parser_paused") MK_DEFINE_ERR(MK_ERR_HTTP(33), GenericParserError, "http_parser_generic_error") /* _ _ _ | | | |_ __| | | | | | '__| | | |_| | | | | \___/|_| |_| Code to parse URLs. */ class Url { public: std::string schema; std::string address; int port = 80; std::string path; std::string query; std::string pathquery; std::string str(); }; Url parse_url(std::string url); ErrorOr parse_url_noexcept(std::string url); /* _ _ __ ___ __ _ _ _ ___ ___| |_ | '__/ _ \/ _` | | | |/ _ \/ __| __| | | | __/ (_| | |_| | __/\__ \ |_ |_| \___|\__, |\__,_|\___||___/\__| |_| HTTP request and response structs, logic to make requests. */ class HeadersComparator { public: bool operator() (const std::string &l, const std::string &r) const; }; using Headers = std::map; class Request { public: std::string method; Url url; std::string url_path; // Allows to override `url.path` via Settings std::string protocol; Headers headers; std::string body; Request() {} Error init(Settings, Headers, std::string); void serialize(net::Buffer &, Var logger = Logger::global()); static ErrorOr> make(Settings, Headers, std::string); }; struct Response { Var request; Var previous; std::string response_line; unsigned short http_major = 0; // Initialize to know value unsigned short http_minor = 0; // Initialize to know value unsigned int status_code = 0; // Initialize to know value std::string reason; Headers headers; std::string body; }; ErrorOr redirect(const Url &orig_url, const std::string &location); void request_connect(Settings, Callback>, Var = Reactor::global(), Var = Logger::global()); void request_send(Var, Settings, Headers, std::string, Callback>); // Same as above except that the optional Request is passed in explicitly void request_maybe_send(ErrorOr>, Var, Callback>); void request_recv_response(Var, Callback>, Var = Reactor::global(), Var = Logger::global()); void request_sendrecv(Var, Settings, Headers, std::string, Callback>, Var = Reactor::global(), Var = Logger::global()); // Same as above except that the optional Request is passed in explicitly void request_maybe_sendrecv(ErrorOr>, Var, Callback>, Var = Reactor::global(), Var = Logger::global()); /* * For settings the following options are defined: * * { * {"http/max_redirects", integer (default is zero)}, * {"http/url", std::string}, * {"http/ignore_body", boolean}, * {"http/method", "GET|DELETE|PUT|POST|HEAD|..."}, * {"http/http_version", "HTTP/1.1"}, * {"http/path", by default is taken from the url} * } */ void request(Settings, Headers, std::string, Callback>, Var = Reactor::global(), Var = Logger::global(), Var previous = nullptr, int nredirects = 0); inline void get(std::string url, Callback> cb, Headers headers = {}, Settings settings = {}, Var reactor = Reactor::global(), Var lp = Logger::global(), Var previous = nullptr, int nredirects = 0) { settings["http/method"] = "GET"; settings["http/url"] = url; request(settings, headers, "", cb, reactor, lp, previous, nredirects); } /* _ (_)___ ___ _ __ | / __|/ _ \| '_ \ | \__ \ (_) | | | | _/ |___/\___/|_| |_| |__/ */ void request_json_string( std::string method, std::string url, std::string data, http::Headers headers, Callback, nlohmann::json> cb, Settings settings, Var reactor, Var logger); void request_json_no_body( std::string method, std::string url, http::Headers headers, Callback, nlohmann::json> cb, Settings settings, Var reactor, Var logger); void request_json_object( std::string method, std::string url, nlohmann::json jdata, http::Headers headers, Callback, nlohmann::json> cb, Settings settings, Var reactor, Var logger); } // namespace http } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/mlabns/000077500000000000000000000000001315356162600227345ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/mlabns/mlabns.hpp000066400000000000000000000025321315356162600247230ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_MLABNS_MLABNS_HPP #define MEASUREMENT_KIT_MLABNS_MLABNS_HPP #include namespace mk { namespace mlabns { MK_DEFINE_ERR(MK_ERR_MLABNS(0), InvalidPolicyError, "mlabns_invalid_policy") MK_DEFINE_ERR(MK_ERR_MLABNS(1), InvalidAddressFamilyError, "mlabns_invalid_address_family") MK_DEFINE_ERR(MK_ERR_MLABNS(2), InvalidMetroError, "mlabns_invalid_metro") MK_DEFINE_ERR(MK_ERR_MLABNS(3), InvalidToolNameError, "mlabns_invalid_tool") /// Reply to mlab-ns query. class Reply { public: std::string city; ///< City where sliver is. std::string url; ///< URL to access sliver using HTTP. std::vector ip; ///< List of IP addresses of sliver. std::string fqdn; ///< FQDN of sliver. std::string site; ///< Site where sliver is. std::string country; ///< Country where sliver is. }; /// Query mlab-ns and receive response. void query(std::string tool, Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); } // namespace mlabns } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/ndt/000077500000000000000000000000001315356162600222455ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/ndt/error.hpp000066400000000000000000000105761315356162600241200ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_NDT_ERROR_HPP #define MEASUREMENT_KIT_NDT_ERROR_HPP #include namespace mk { namespace ndt { MK_DEFINE_ERR(MK_ERR_NDT( 0), ReadingMessageTypeLengthError, "ndt_cannot_read_type_length") MK_DEFINE_ERR(MK_ERR_NDT( 1), ReadingMessagePayloadError, "ndt_cannot_read_payload") MK_DEFINE_ERR(MK_ERR_NDT( 2), MessageTooLongError, "ndt_message_too_long") MK_DEFINE_ERR(MK_ERR_NDT( 3), ConnectControlConnectionError, "ndt_cannot_establish_control_connection") MK_DEFINE_ERR(MK_ERR_NDT( 4), FormatExtendedLoginMessageError, "ndt_cannot_format_extended_login_message") MK_DEFINE_ERR(MK_ERR_NDT( 5), WriteExtendedLoginMessageError, "ndt_cannot_write_extended_login_message") MK_DEFINE_ERR(MK_ERR_NDT( 6), ReadingKickoffMessageError, "ndt_cannot_read_kickoff_message") MK_DEFINE_ERR(MK_ERR_NDT( 7), InvalidKickoffMessageError, "ndt_invalid_kickoff_message") MK_DEFINE_ERR(MK_ERR_NDT( 8), ReadingSrvQueueMessageError, "ndt_cannot_read_srv_queue_message") MK_DEFINE_ERR(MK_ERR_NDT( 9), NotSrvQueueMessageError, "ndt_missing_expected_srv_queue_message") MK_DEFINE_ERR(MK_ERR_NDT(10), InvalidSrvQueueMessageError, "ndt_invalid_srv_queue_message") MK_DEFINE_ERR(MK_ERR_NDT(11), QueueServerFaultError, "ndt_server_queue_fault") MK_DEFINE_ERR(MK_ERR_NDT(12), ReadingServerVersionMessageError, "ndt_cannot_read_server_version") MK_DEFINE_ERR(MK_ERR_NDT(13), NotServerVersionMessageError, "ndt_missing_expected_server_version") MK_DEFINE_ERR(MK_ERR_NDT(14), ReadingTestsIdMessageError, "ndt_cannot_read_tests_id") MK_DEFINE_ERR(MK_ERR_NDT(15), NotTestsIdMessageError, "ndt_missing_expected_tests_id_message") MK_DEFINE_ERR(MK_ERR_NDT(16), InvalidTestIdError, "ndt_invalid_tests_id_message") MK_DEFINE_ERR(MK_ERR_NDT(17), UnknownTestIdError, "ndt_received_unknown_test_id") MK_DEFINE_ERR(MK_ERR_NDT(18), TestFailedError, "ndt_test_failed") MK_DEFINE_ERR(MK_ERR_NDT(19), ReadingResultsOrLogoutError, "ndt_cannot_read_results_or_logout_message") MK_DEFINE_ERR(MK_ERR_NDT(20), NotResultsOrLogoutError, "ndt_missing_expected_results_or_logout_message") MK_DEFINE_ERR(MK_ERR_NDT(21), WaitingCloseError, "ndt_error_while_waiting_for_close_message") MK_DEFINE_ERR(MK_ERR_NDT(22), DataAfterLogoutError, "ndt_received_data_after_logout_message") MK_DEFINE_ERR(MK_ERR_NDT(23), InvalidPortError, "ndt_received_invalid_port") MK_DEFINE_ERR(MK_ERR_NDT(24), MlabnsQueryError, "ndt_error_querying_mlabns") MK_DEFINE_ERR(MK_ERR_NDT(25), ReadingTestPrepareError, "ndt_cannot_read_test_prepare_message") MK_DEFINE_ERR(MK_ERR_NDT(26), NotTestPrepareError, "ndt_missing_expected_test_prepare_message") MK_DEFINE_ERR(MK_ERR_NDT(27), ConnectTestConnectionError, "ndt_cannot_establish_testing_connection") MK_DEFINE_ERR(MK_ERR_NDT(28), ReadingTestStartError, "ndt_cannot_read_test_start_message") MK_DEFINE_ERR(MK_ERR_NDT(29), NotTestStartError, "ndt_missing_expected_test_start_error") MK_DEFINE_ERR(MK_ERR_NDT(30), ReadingTestMsgError, "ndt_cannot_read_test_msg_message") MK_DEFINE_ERR(MK_ERR_NDT(31), NotTestMsgError, "ndt_missing_expected_test_msg") MK_DEFINE_ERR(MK_ERR_NDT(32), ReadingTestFinalizeError, "ndt_cannot_read_test_finalize_message") MK_DEFINE_ERR(MK_ERR_NDT(33), NotTestFinalizeError, "ndt_missing_expected_test_finalize_message") MK_DEFINE_ERR(MK_ERR_NDT(34), SerializingClientVersionError, "ndt_cannot_serialize_client_version") MK_DEFINE_ERR(MK_ERR_NDT(35), SerializingClientApplicationError, "ndt_cannot_serialize_client_application") MK_DEFINE_ERR(MK_ERR_NDT(36), SerializingFinalMetaError, "ndt_cannot_serialize_final_meta_message") MK_DEFINE_ERR(MK_ERR_NDT(37), WritingMetaError, "ndt_cannot_write_meta_message") MK_DEFINE_ERR(MK_ERR_NDT(38), SerializingTestMsgError, "ndt_cannot_serialize_test_msg_message") MK_DEFINE_ERR(MK_ERR_NDT(39), WritingTestMsgError, "ndt_cannot_write_test_msg_message") MK_DEFINE_ERR(MK_ERR_NDT(40), QueueServerBusyError, "ndt_server_busy") MK_DEFINE_ERR(MK_ERR_NDT(41), FormatMsgWaitingError, "ndt_cannot_format_msg_waiting_message") MK_DEFINE_ERR(MK_ERR_NDT(42), InvalidDurationError, "ndt_invalid_duration_setting") MK_DEFINE_ERR(MK_ERR_NDT(43), InvalidSnapsDelayError, "ndt_invalid_snaps_delay_setting") MK_DEFINE_ERR(MK_ERR_NDT(44), InvalidNumStreamsError, "ndt_invalid_num_streams_setting") } // namespace ndt } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/ndt/run.hpp000066400000000000000000000023271315356162600235660ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_NDT_RUN_HPP #define MEASUREMENT_KIT_NDT_RUN_HPP #include namespace mk { namespace ndt { // By default we pass MK_NDT_UPLOAD|MK_NDT_DOWNLOAD as settings["test_suite"] // but you can tweak that by only requesting a single phase. #define MK_NDT_MIDDLEBOX 1 #define MK_NDT_UPLOAD 2 #define MK_NDT_DOWNLOAD 4 #define MK_NDT_SIMPLE_FIREWALL 8 #define MK_NDT_STATUS 16 #define MK_NDT_META 32 #define MK_NDT_UPLOAD_EXT 64 // not implemented #define MK_NDT_DOWNLOAD_EXT 128 void run_with_specific_server(Var entry, std::string address, int port, Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); void run(Var entry, Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); } // namespace ndt } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/net/000077500000000000000000000000001315356162600222465ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/net/buffer.hpp000066400000000000000000000054611315356162600242360ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_NET_BUFFER_HPP #define MEASUREMENT_KIT_NET_BUFFER_HPP #include struct evbuffer; namespace mk { namespace net { class Buffer { public: Buffer(); Buffer(evbuffer *b); Buffer(std::string); Buffer(const void *, size_t); ~Buffer() {} static Var make(); /* * I expect to read (write) from (into) the input (output) * evbuffer of a certain bufferevent. It seems to me natural * to use the insertion and extraction operators for that. */ Buffer &operator<<(evbuffer *source); Buffer &operator>>(evbuffer *dest); Buffer &operator<<(Buffer &source); Buffer &operator>>(Buffer &source); size_t length(); /* * The following is useful to feed a parser (e.g., the http-parser) * with all (or part of) the content of `this`. */ void for_each(std::function fn); /* * Discard(), read(), readline() and readn() are the common operations * that you need to implement a protocol (AFAICT). */ void discard(size_t count); void discard() { discard(length()); } std::string readpeek(bool ispeek, size_t upto); std::string read(size_t upto) { return readpeek(false, upto); } std::string read() { return read(length()); } std::string peek(size_t upto) { return readpeek(true, upto); } std::string peek() { return peek(length()); } /* * The semantic of readn() is that we return a string only * when we have exactly N bytes available. */ std::string readn(size_t n) { if (n > length()) return ""; return read(n); } ErrorOr readline(size_t maxline); /* * Wrappers for write, including a handy wrapper for sending * random bytes to the output stream. */ void write(std::string in) { write(in.c_str(), in.length()); } Buffer &operator<<(std::string in) { write(in); return *this; } void write(const char *in) { if (in == nullptr) throw std::runtime_error("in is nullptr"); write(in, strlen(in)); } Buffer &operator<<(const char *in) { write(in); return *this; } void write(const void *buf, size_t count); ErrorOr read_uint8(); void write_uint8(uint8_t); ErrorOr read_uint16(); void write_uint16(uint16_t); ErrorOr read_uint32(); void write_uint32(uint32_t); void write_rand(size_t count); void write(size_t count, std::function func); Var evbuf; }; } // namespace net } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/net/connect.hpp000066400000000000000000000017031315356162600244110ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_NET_CONNECT_HPP #define MEASUREMENT_KIT_NET_CONNECT_HPP #include #include struct bufferevent; namespace mk { namespace net { void connect(std::string address, int port, Callback> callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); using ConnectManyCb = Callback>>; void connect_many(std::string address, int port, int num, ConnectManyCb callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); } // namespace net } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/net/error.hpp000066400000000000000000000124441315356162600241150ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_NET_ERROR_HPP #define MEASUREMENT_KIT_NET_ERROR_HPP #include namespace mk { namespace net { MK_DEFINE_ERR(MK_ERR_NET(0), EofError, "eof_error") MK_DEFINE_ERR(MK_ERR_NET(1), TimeoutError, "generic_timeout_error") /* Unused: MK_ERR_NET(2) */ MK_DEFINE_ERR(MK_ERR_NET(3), ConnectFailedError, "connect_error") MK_DEFINE_ERR(MK_ERR_NET(4), DnsGenericError, "dns_lookup_error") MK_DEFINE_ERR(MK_ERR_NET(5), BadSocksVersionError, "socks_error") MK_DEFINE_ERR(MK_ERR_NET(6), SocksAddressTooLongError, "socks_address_too_long") MK_DEFINE_ERR(MK_ERR_NET(7), SocksInvalidPortError, "socks_invalid_port") MK_DEFINE_ERR(MK_ERR_NET(8), SocksGenericError, "socks_error") MK_DEFINE_ERR(MK_ERR_NET(9), EOLNotFoundError, "eol_not_found") MK_DEFINE_ERR(MK_ERR_NET(10), LineTooLongError, "line_too_long") MK_DEFINE_ERR(MK_ERR_NET(11), NetworkError, "generic_network_error") using SocketError = NetworkError; /* Alias */ MK_DEFINE_ERR(MK_ERR_NET(12), NoAvailableSocksAuthenticationError, "socks_no_available_authentication") MK_DEFINE_ERR(MK_ERR_NET(13), SocksError, "socks_error") MK_DEFINE_ERR(MK_ERR_NET(14), BadSocksReservedFieldError, "socks_bad_reserved_field") MK_DEFINE_ERR(MK_ERR_NET(15), BadSocksAtypeValueError, "socks_bad_address_type") MK_DEFINE_ERR(MK_ERR_NET(16), EvconnlistenerNewBindError, "bind_error") MK_DEFINE_ERR(MK_ERR_NET(17), BuffereventSocketNewError, "bufferevent_new_error") MK_DEFINE_ERR(MK_ERR_NET(18), SslInvalidCertificateError, "ssl_invalid_certificate") MK_DEFINE_ERR(MK_ERR_NET(19), SslNoCertificateError, "ssl_no_certificate") MK_DEFINE_ERR(MK_ERR_NET(20), SslInvalidHostnameError, "ssl_invalid_hostname") MK_DEFINE_ERR(MK_ERR_NET(21), SslError, "ssl_error") MK_DEFINE_ERR(MK_ERR_NET(22), NotEnoughDataError, "not_enough_data") MK_DEFINE_ERR(MK_ERR_NET(23), MissingCaBundlePathError, "missing_ca_bundle_path") /* Error code not used; was the old BrokenPipeError */ MK_DEFINE_ERR(MK_ERR_NET(25), SslNewError, "ssl_new_error") MK_DEFINE_ERR(MK_ERR_NET(26), SslCtxNewError, "ssl_ctx_new_error") MK_DEFINE_ERR(MK_ERR_NET(27), SslCtxLoadVerifyLocationsError, "ssl_ctx_load_verify_locations_error") MK_DEFINE_ERR(MK_ERR_NET(28), SslCtxLoadVerifyMemError, "ssl_ctx_load_verify_mem_error") /* * Maps std::errc from * * Note that EAGAIN is not handled here but in the .cpp file * and gets mapped to EWOULDBLOCK unconditionally like most modern * Unix systems already do in their or . */ #define MK_NET_ERRORS_XX \ XX(29, AddressFamilyNotSupportedError, address_family_not_supported) \ XX(30, AddressInUseError, address_in_use) \ XX(31, AddressNotAvailableError, address_not_available) \ XX(32, AlreadyConnectedError, already_connected) \ XX(33, BadAddressError, bad_address) \ XX(34, BadFileDescriptorError, bad_file_descriptor) \ XX(35, BrokenPipeError, broken_pipe) \ XX(36, ConnectionAbortedError, connection_aborted) \ XX(37, ConnectionAlreadyInProgressError, \ connection_already_in_progress) \ XX(38, ConnectionRefusedError, connection_refused) \ XX(39, ConnectionResetError, connection_reset) \ XX(40, DestinationAddressRequiredError, destination_address_required) \ XX(41, HostUnreachableError, host_unreachable) \ XX(42, InterruptedError, interrupted) \ XX(43, InvalidArgumentError, invalid_argument) \ XX(44, MessageSizeError, message_size) \ XX(45, NetworkDownError, network_down) \ XX(46, NetworkResetError, network_reset) \ XX(47, NetworkUnreachableError, network_unreachable) \ XX(48, NoBufferSpaceError, no_buffer_space) \ XX(49, NoProtocolOptionError, no_protocol_option) \ XX(50, NotASocketError, not_a_socket) \ XX(51, NotConnectedError, not_connected) \ XX(52, OperationWouldBlockError, operation_would_block) \ XX(53, PermissionDeniedError, permission_denied) \ XX(54, ProtocolErrorError, protocol_error) \ XX(55, ProtocolNotSupportedError, protocol_not_supported) \ XX(56, TimedOutError, timed_out) \ XX(57, WrongProtocolTypeError, wrong_protocol_type) #define XX(_code_, _name_, _descr_) \ MK_DEFINE_ERR(MK_ERR_NET(_code_), _name_, #_descr_) MK_NET_ERRORS_XX #undef XX MK_DEFINE_ERR(MK_ERR_NET(58), SslDirtyShutdownError, "ssl_dirty_shutdown") MK_DEFINE_ERR(MK_ERR_NET(59), SslMissingHostnameError, "ssl_missing_hostname") } // namespace net } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/net/transport.hpp000066400000000000000000000072051315356162600250170ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_NET_TRANSPORT_HPP #define MEASUREMENT_KIT_NET_TRANSPORT_HPP #include #include namespace mk { namespace dns { class ResolveHostnameResult; /* Forward declaration */ } // namespace dns namespace net { class TransportEmitter { public: virtual ~TransportEmitter(); virtual void emit_connect() = 0; virtual void emit_data(Buffer buf) = 0; virtual void emit_flush() = 0; virtual void emit_error(Error err) = 0; virtual void on_connect(Callback<>) = 0; virtual void on_data(Callback) = 0; virtual void on_flush(Callback<>) = 0; virtual void on_error(Callback) = 0; virtual void close(Callback<>) = 0; }; class TransportRecorder { public: virtual ~TransportRecorder(); virtual void record_received_data() = 0; virtual void dont_record_received_data() = 0; virtual Buffer &received_data() = 0; virtual void record_sent_data() = 0; virtual void dont_record_sent_data() = 0; virtual Buffer &sent_data() = 0; }; class TransportWriter { public: virtual ~TransportWriter(); virtual void write(const void *, size_t) = 0; virtual void write(std::string) = 0; virtual void write(Buffer) = 0; }; class TransportSocks5 { public: virtual ~TransportSocks5(); virtual std::string socks5_address() = 0; virtual std::string socks5_port() = 0; }; class TransportPollable { public: virtual ~TransportPollable(); virtual void set_timeout(double) = 0; virtual void clear_timeout() = 0; /* * This is the interface with the underlying I/O system. As such, it is * specified here, for clarity, but is also protected. */ protected: virtual void adjust_timeout(double) = 0; virtual void shutdown() = 0; /* * Writing is stopped automatically when the send buffer is empty * and, when this happens, the FLUSH event is emitted. */ virtual void start_reading() = 0; virtual void stop_reading() = 0; virtual void start_writing() = 0; }; class TransportConnectable { public: virtual ~TransportConnectable(); virtual double connect_time() = 0; virtual void set_connect_time_(double) = 0; virtual std::vector connect_errors() = 0; virtual void set_connect_errors_(std::vector) = 0; virtual dns::ResolveHostnameResult dns_result() = 0; virtual void set_dns_result_(dns::ResolveHostnameResult) = 0; }; class TransportSockNamePeerName { public: virtual ~TransportSockNamePeerName(); virtual Endpoint sockname() = 0; virtual Endpoint peername() = 0; }; class Transport : public TransportEmitter, public TransportRecorder, public TransportWriter, public TransportSocks5, public TransportPollable, public TransportConnectable, public TransportSockNamePeerName { public: virtual ~Transport(); }; /* * Syntactic sugar when you need only to write or read (vis a vis Transport, * required when you need read and write at the same time). */ void write(Var txp, Buffer buf, Callback cb); void readn(Var txp, Var buff, size_t n, Callback cb, Var reactor = Reactor::global()); void read(Var t, Var buff, Callback callback, Var reactor = Reactor::global()); } // namespace net } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/net/utils.hpp000066400000000000000000000020311315356162600241130ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_NET_UTILS_HPP #define MEASUREMENT_KIT_NET_UTILS_HPP #include namespace mk { namespace net { class Endpoint { public: std::string hostname; uint16_t port = 0; }; bool is_ipv4_addr(std::string s); bool is_ipv6_addr(std::string s); bool is_ip_addr(std::string s); ErrorOr parse_endpoint(std::string s, uint16_t def_port); std::string serialize_endpoint(Endpoint); ErrorOr endpoint_from_sockaddr_storage( sockaddr_storage *storage ) noexcept; Error make_sockaddr( std::string address, std::string port, sockaddr_storage *storage, socklen_t *len ) noexcept; Error make_sockaddr( std::string address, uint16_t port, sockaddr_storage *storage, socklen_t *len ) noexcept; } // namespace net } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/nettests/000077500000000000000000000000001315356162600233315ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/nettests/nettests.hpp000066400000000000000000000047121315356162600257170ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_NETTESTS_NETTESTS_HPP #define MEASUREMENT_KIT_NETTESTS_NETTESTS_HPP #include #include #include #include #include #include #include #include namespace mk { namespace nettests { class Runnable; class BaseTest { public: BaseTest &on_logger_eof(Delegate<>); BaseTest &on_log(Delegate); BaseTest &on_event(Delegate); BaseTest &on_progress(Delegate); BaseTest &set_verbosity(uint32_t); BaseTest &increase_verbosity(); BaseTest(); virtual ~BaseTest(); BaseTest &add_input(std::string); BaseTest &add_input_filepath(std::string); BaseTest &set_input_filepath(std::string); BaseTest &set_output_filepath(std::string); BaseTest &set_error_filepath(std::string); template ::value>::type> BaseTest &set_options(std::string key, T value) { return set_options(key, lexical_cast(value)); } BaseTest &set_options(std::string key, std::string value); BaseTest &on_entry(Delegate); BaseTest &on_begin(Delegate<>); BaseTest &on_end(Delegate<> cb); BaseTest &on_destroy(Delegate<> cb); void run(); void start(Callback<> func); Var runnable; Settings settings; }; #define MK_DECLARE_TEST(_name_) \ class _name_ : public BaseTest { \ public: \ _name_(); \ } MK_DECLARE_TEST(DashTest); MK_DECLARE_TEST(DnsInjectionTest); MK_DECLARE_TEST(HttpHeaderFieldManipulationTest); MK_DECLARE_TEST(HttpInvalidRequestLineTest); MK_DECLARE_TEST(MeekFrontedRequestsTest); MK_DECLARE_TEST(MultiNdtTest); MK_DECLARE_TEST(NdtTest); MK_DECLARE_TEST(TcpConnectTest); MK_DECLARE_TEST(WebConnectivityTest); } // namespace nettests } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/neubot/000077500000000000000000000000001315356162600227545ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/neubot/dash.hpp000066400000000000000000000015451315356162600244110ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_NEUBOT_DASH_HPP #define MEASUREMENT_KIT_NEUBOT_DASH_HPP #include namespace mk { namespace neubot { namespace dash { void run( std::string measurement_server_hostname, std::string auth_token, std::string real_address, Var entry, Settings settings, Var reactor, Var logger, Callback callback ); void negotiate( Var entry, Settings settings, Var reactor, Var logger, Callback callback ); } // namespace dash } // namespace neubot } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/ooni/000077500000000000000000000000001315356162600224245ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/ooni/bouncer.hpp000066400000000000000000000027701315356162600246000ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_OONI_BOUNCER_HPP #define MEASUREMENT_KIT_OONI_BOUNCER_HPP #include #include namespace mk { namespace ooni { class BouncerReply { public: nlohmann::json response; static ErrorOr> create(std::string, Var); ErrorOr get_collector(); ErrorOr get_collector_alternate(std::string type); ErrorOr get_name(); ErrorOr get_test_helper(std::string name); ErrorOr get_test_helper_alternate(std::string name, std::string type); ErrorOr get_version(); private: nlohmann::json get_base(); }; namespace bouncer { void post_net_tests(std::string base_bouncer_url, std::string test_name, std::string test_version, std::list helpers, Callback> cb, Settings settings, Var reactor, Var logger); #define MK_OONI_PRODUCTION_BOUNCER_URL "https://bouncer.ooni.io" #define MK_OONI_TESTING_BOUNCER_URL "https://bouncer.test.ooni.io" std::string production_bouncer_url(); std::string testing_bouncer_url(); } // namespace bouncer } // namespace ooni } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/ooni/collector_client.hpp000066400000000000000000000060071315356162600264640ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_OONI_BACKEND_CLIENT_HPP #define MEASUREMENT_KIT_OONI_BACKEND_CLIENT_HPP #include #include namespace mk { namespace ooni { namespace collector { /* To submit a file report, use one of the following collectors. By default the library uses the `production` collector. */ #define MK_OONI_PRODUCTION_COLLECTOR_URL "https://b.collector.ooni.io" #define MK_OONI_TESTING_COLLECTOR_URL "https://b.collector.test.ooni.io:4441" std::string production_collector_url(); std::string testing_collector_url(); void submit_report(std::string filepath, std::string collector_base_url, Callback callback, Settings conf = {}, Var = Reactor::global(), Var = Logger::global()); void submit_report(std::string filepath, std::string collector_base_url, std::string collector_front_domain, Callback callback, Settings conf = {}, Var = Reactor::global(), Var = Logger::global()); /* The following APIs are used to implement `submit_report()` and could also be the basic bricks to open report at the beginning, update during the test progress, and close when test ends: */ void connect(Settings, Callback>, Var = Reactor::global(), Var = Logger::global()); void create_report(Var, report::Entry, Callback, Settings = {}, Var = Reactor::global(), Var = Logger::global()); void connect_and_create_report(report::Entry, Callback, Settings = {}, Var = Reactor::global(), Var = Logger::global()); void update_report(Var, std::string report_id, report::Entry, Callback, Settings = {}, Var = Reactor::global(), Var = Logger::global()); void connect_and_update_report(std::string report_id, report::Entry, Callback, Settings = {}, Var = Reactor::global(), Var = Logger::global()); void close_report(Var, std::string report_id, Callback, Settings = {}, Var = Reactor::global(), Var = Logger::global()); void connect_and_close_report(std::string report_id, Callback, Settings = {}, Var = Reactor::global(), Var = Logger::global()); } // namespace collector } // namespace mk } // namespace ooni #endif measurement-kit-0.7.1/include/measurement_kit/ooni/error.hpp000066400000000000000000000062261315356162600242740ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_OONI_ERROR_HPP #define MEASUREMENT_KIT_OONI_ERROR_HPP #include namespace mk { namespace ooni { MK_DEFINE_ERR(MK_ERR_OONI(0), CannotReadAnyInputFileError, "cannot_read_any_input_file") MK_DEFINE_ERR(MK_ERR_OONI(1), MissingRequiredInputFileError, "missing_required_input_file") MK_DEFINE_ERR(MK_ERR_OONI(2), MissingCollectorBaseUrlError, "missing_collector_base_url") MK_DEFINE_ERR(MK_ERR_OONI(3), CannotOpenReportError, "cannot_open_report") MK_DEFINE_ERR(MK_ERR_OONI(4), MissingMandatoryKeyError, "missing_mandatory_key") MK_DEFINE_ERR(MK_ERR_OONI(5), InvalidMandatoryValueError, "invalid_mandatory_value") MK_DEFINE_ERR(MK_ERR_OONI(6), MissingRequiredHostError, "missing_required_host") MK_DEFINE_ERR(MK_ERR_OONI(7), MissingRequiredUrlError, "missing_required_url") MK_DEFINE_ERR(MK_ERR_OONI(8), GeoipDatabaseOpenError, "cannot_open_geoip_database") MK_DEFINE_ERR(MK_ERR_OONI(9), GeoipCountryCodeLookupError, "cannot_find_country_code") MK_DEFINE_ERR(MK_ERR_OONI(10), GeoipCountryNameLookupError, "cannot_find_country_name") MK_DEFINE_ERR(MK_ERR_OONI(11), GeoipCityLookupError, "cannot_find_city") MK_DEFINE_ERR(MK_ERR_OONI(12), GeoipAsnLookupError, "cannot_find_asn") MK_DEFINE_ERR(MK_ERR_OONI(13), CannotGetResourcesVersionError, "cannot_get_resources_version") MK_DEFINE_ERR(MK_ERR_OONI(14), CannotGetResourcesManifestError, "cannot_get_resources_manifest") MK_DEFINE_ERR(MK_ERR_OONI(15), CannotGetResourceError, "cannot_get_resource") MK_DEFINE_ERR(MK_ERR_OONI(16), ResourceIntegrityError, "resource_checksum_failed") MK_DEFINE_ERR(MK_ERR_OONI(17), BouncerCollectorNotFoundError, "bouncer_missing_collector") MK_DEFINE_ERR(MK_ERR_OONI(18), BouncerTestHelperNotFoundError, "bouncer_missing_test_helper") MK_DEFINE_ERR(MK_ERR_OONI(19), BouncerInvalidRequestError, "bouncer_invalid_request") MK_DEFINE_ERR(MK_ERR_OONI(20), BouncerGenericError, "bouncer_generic_error") MK_DEFINE_ERR(MK_ERR_OONI(21), BouncerValueNotFoundError, "bouncer_value_not_found") MK_DEFINE_ERR(MK_ERR_OONI(22), HttpRequestError, "http_request_error") MK_DEFINE_ERR(MK_ERR_OONI(23), RegexSearchError, "regex_search_error") MK_DEFINE_ERR(MK_ERR_OONI(24), RegistryWrongUsernamePasswordError, "registry_wrong_username_password") MK_DEFINE_ERR(MK_ERR_OONI(25), RegistryMissingUsernamePasswordError, "registry_missing_username_password") MK_DEFINE_ERR(MK_ERR_OONI(26), MissingAuthenticationTokenError, "missing_authentication_token") MK_DEFINE_ERR(MK_ERR_OONI(27), MissingRequiredValueError, "missing_required_value") MK_DEFINE_ERR(MK_ERR_OONI(28), RegistryInvalidRequestError, "registry_invalid_request") MK_DEFINE_ERR(MK_ERR_OONI(29), RegistryEmptyClientIdError, "registry_empty_client_id") } // namespace mk } // namespace ooni #endif measurement-kit-0.7.1/include/measurement_kit/ooni/nettests.hpp000066400000000000000000000031631315356162600250110ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_OONI_NETTESTS_HPP #define MEASUREMENT_KIT_OONI_NETTESTS_HPP #include namespace mk { namespace ooni { void dns_injection(std::string, Settings, Callback>, Var = Reactor::global(), Var = Logger::global()); void http_invalid_request_line(Settings, Callback>, Var = Reactor::global(), Var = Logger::global()); void tcp_connect(std::string, Settings, Callback>, Var = Reactor::global(), Var = Logger::global()); void web_connectivity(std::string input, Settings, Callback>, Var = Reactor::global(), Var = Logger::global()); void meek_fronted_requests(std::string input, Settings, Callback>, Var = Reactor::global(), Var = Logger::global()); void http_header_field_manipulation(std::string input, Settings, Callback>, Var = Reactor::global(), Var = Logger::global()); } // namespace ooni } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/ooni/orchestrate.hpp000066400000000000000000000062211315356162600254610ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_OONI_ORCHESTRATE_HPP #define MEASUREMENT_KIT_OONI_ORCHESTRATE_HPP // Documentation: doc/api/ooni/orchestrate.md #include namespace mk { namespace ooni { namespace orchestrate { /* * URLs */ #define MK_OONI_PRODUCTION_PROTEUS_REGISTRY_URL \ "https://a.registry.proteus.ooni.io" #define MK_OONI_TESTING_PROTEUS_REGISTRY_URL \ "https://registry.proteus.test.ooni.io" #define MK_OONI_PRODUCTION_PROTEUS_EVENTS_URL "https://a.events.proteus.ooni.io" #define MK_OONI_TESTING_PROTEUS_EVENTS_URL "https://events.proteus.test.ooni.io" std::string production_registry_url(); std::string testing_registry_url(); std::string production_events_url(); std::string testing_events_url(); /* * Registry database */ class Auth { public: std::string auth_token; std::string expiry_time; bool logged_in = false; std::string username; std::string password; static std::string make_password(); Error load(const std::string &filepath) noexcept; Error loads(const std::string &data) noexcept; Error dump(const std::string &filepath) noexcept; std::string dumps() noexcept; bool is_valid(Var) const noexcept; }; class ClientMetadata { public: Var logger = Logger::global(); Settings settings = {}; std::string available_bandwidth; std::string device_token; std::string events_url = production_events_url(); std::string language; std::string network_type; std::string geoip_country_path; std::string geoip_asn_path; std::string platform; std::string probe_asn; std::string probe_cc; std::string probe_family; std::string registry_url = production_registry_url(); std::string software_name = "measurement_kit"; std::string software_version = MK_VERSION; std::vector supported_tests; nlohmann::json as_json() const; }; class Task; /* Forward declaration */ class Client : public ClientMetadata { public: void register_probe( std::string &&, Callback &&callback) const; void find_location( Callback &&callback) const; void update(Auth &&, Callback &&callback) const; void list_tasks( Auth &&, Callback &&> &&callback) const; }; /* * Events database */ class TaskData { public: std::string events_url = production_events_url(); std::string task_id; }; class Task : public TaskData { public: void get(Auth &&, Callback &&callback) const; void accept(Auth &&, Callback &&callback) const; void reject(Auth &&, Callback &&callback) const; void done(Auth &&, Callback &&callback) const; }; } // namespace orchestrate } // namespace ooni } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/ooni/resources.hpp000066400000000000000000000032071315356162600251510ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_OONI_RESOURCES_HPP #define MEASUREMENT_KIT_OONI_RESOURCES_HPP #include #include namespace mk { namespace ooni { namespace resources { void get_latest_release(Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); void get_manifest_as_json(std::string version, Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); void get_resources_for_country(std::string latest, nlohmann::json manifest, std::string country, Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); void get_resources(std::string latest, std::string country, Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); } // namespace resources } // namespace mk } // namespace ooni #endif measurement-kit-0.7.1/include/measurement_kit/ooni/templates.hpp000066400000000000000000000023271315356162600251370ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_OONI_TEMPLATES_HPP #define MEASUREMENT_KIT_OONI_TEMPLATES_HPP #include #include namespace mk { namespace ooni { namespace templates { void dns_query(Var entry, dns::QueryType, dns::QueryClass, std::string query_name, std::string nameserver, Callback>, Settings = {}, Var = Reactor::global(), Var = Logger::global()); void http_request(Var entry, Settings settings, http::Headers headers, std::string body, Callback> cb, Var reactor = Reactor::global(), Var logger = Logger::global()); void tcp_connect(Settings options, Callback> cb, Var reactor = Reactor::global(), Var logger = Logger::global()); } // namespace templates } // namespace mk } // namespace ooni #endif measurement-kit-0.7.1/include/measurement_kit/ooni/utils.hpp000066400000000000000000000014631315356162600243010ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_OONI_UTILS_HPP #define MEASUREMENT_KIT_OONI_UTILS_HPP #include namespace mk { namespace ooni { void ip_lookup(Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); void resolver_lookup(Callback callback, Settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); report::Entry represent_string(const std::string &s); } // namespace ooni } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/portable/000077500000000000000000000000001315356162600232705ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/portable/arpa/000077500000000000000000000000001315356162600242135ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/portable/arpa/inet.h000066400000000000000000000002511315356162600253210ustar00rootroot00000000000000/* * Public domain. */ #ifndef MEASUREMENT_KIT_PORTABLE_ARPA_INET_H #define MEASUREMENT_KIT_PORTABLE_ARPA_INET_H #ifndef _WIN32 #include #endif #endif measurement-kit-0.7.1/include/measurement_kit/portable/netdb.h000066400000000000000000000002351315356162600245350ustar00rootroot00000000000000/* * Public domain. */ #ifndef MEASUREMENT_KIT_PORTABLE_NETDB_H #define MEASUREMENT_KIT_PORTABLE_NETDB_H #ifndef _WIN32 #include #endif #endif measurement-kit-0.7.1/include/measurement_kit/portable/netinet/000077500000000000000000000000001315356162600247365ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/portable/netinet/in.h000066400000000000000000000002541315356162600255160ustar00rootroot00000000000000/* * Public domain. */ #ifndef MEASUREMENT_KIT_PORTABLE_NETINET_IN_H #define MEASUREMENT_KIT_PORTABLE_NETINET_IN_H #ifndef _WIN32 #include #endif #endif measurement-kit-0.7.1/include/measurement_kit/portable/netinet/tcp.h000066400000000000000000000002571315356162600257010ustar00rootroot00000000000000/* * Public domain. */ #ifndef MEASUREMENT_KIT_PORTABLE_NETINET_TCP_H #define MEASUREMENT_KIT_PORTABLE_NETINET_TCP_H #ifndef _WIN32 #include #endif #endif measurement-kit-0.7.1/include/measurement_kit/portable/stdlib.h000066400000000000000000000011221315356162600247160ustar00rootroot00000000000000/* * Public domain. */ #ifndef MEASUREMENT_KIT_PORTABLE_STDLIB_H #define MEASUREMENT_KIT_PORTABLE_STDLIB_H #include #ifdef __cplusplus extern "C" { #endif /* strtonum() function is not defined under many C libraries but is defined e.g. by OpenBSD. Therefore we have our own wrapper that will call the sys strtonum() if available and otherwise use a replacement. */ long long mkp_strtonum(const char *numstr, long long minval, long long maxval, const char **errstrp); #ifdef __cplusplus } #endif #endif measurement-kit-0.7.1/include/measurement_kit/portable/strings.h000066400000000000000000000002431315356162600251310ustar00rootroot00000000000000/* * Public domain. */ #ifndef MEASUREMENT_KIT_PORTABLE_STRINGS_H #define MEASUREMENT_KIT_PORTABLE_STRINGS_H #ifndef _WIN32 #include #endif #endif measurement-kit-0.7.1/include/measurement_kit/portable/sys/000077500000000000000000000000001315356162600241065ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/portable/sys/socket.h000066400000000000000000000002541315356162600255500ustar00rootroot00000000000000/* * Public domain. */ #ifndef MEASUREMENT_KIT_PORTABLE_SYS_SOCKET_H #define MEASUREMENT_KIT_PORTABLE_SYS_SOCKET_H #ifndef _WIN32 #include #endif #endif measurement-kit-0.7.1/include/measurement_kit/portable/sys/time.h000066400000000000000000000002461315356162600252170ustar00rootroot00000000000000/* * Public domain. */ #ifndef MEASUREMENT_KIT_PORTABLE_SYS_TIME_H #define MEASUREMENT_KIT_PORTABLE_SYS_TIME_H #ifndef _WIN32 #include #endif #endif measurement-kit-0.7.1/include/measurement_kit/portable/sys/types.h000066400000000000000000000002511315356162600254210ustar00rootroot00000000000000/* * Public domain. */ #ifndef MEASUREMENT_KIT_PORTABLE_SYS_TYPES_H #define MEASUREMENT_KIT_PORTABLE_SYS_TYPES_H #ifndef _WIN32 #include #endif #endif measurement-kit-0.7.1/include/measurement_kit/portable/time.h000066400000000000000000000002041315356162600243730ustar00rootroot00000000000000/* * Public domain. */ #ifndef MEASUREMENT_KIT_PORTABLE_TIME_H #define MEASUREMENT_KIT_PORTABLE_TIME_H #include #endif measurement-kit-0.7.1/include/measurement_kit/report/000077500000000000000000000000001315356162600227735ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/report/base_reporter.hpp000066400000000000000000000027361315356162600263500ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_REPORT_BASE_REPORTER_HPP #define MEASUREMENT_KIT_REPORT_BASE_REPORTER_HPP #include #include namespace mk { namespace report { class Report; class BaseReporter : public NonCopyable, public NonMovable { public: static Var make(); virtual ~BaseReporter(); // TODO: refactor moving these inline functions inside of the .cpp file virtual Continuation open(Report &) { return do_open_([=](Callback cb) { cb(NoError()); }); } virtual Continuation write_entry(Entry e) { return do_write_entry_(e, [=](Callback cb) { cb(NoError()); }); } virtual Continuation close() { return do_close_([=](Callback cb) { cb(NoError()); }); } virtual std::string get_report_id() { return ""; /* This is basically "invalid report id" */ } protected: BaseReporter() {} Continuation do_open_(Continuation cc); Continuation do_write_entry_(Entry, Continuation cc); Continuation do_close_(Continuation cc); private: bool openned_ = false; bool closed_ = false; std::string prev_entry_; }; } // namespace report } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/report/entry.hpp000066400000000000000000000052141315356162600246470ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_REPORT_ENTRY_HPP #define MEASUREMENT_KIT_REPORT_ENTRY_HPP #include #include // vendored nlohmann::json namespace mk { namespace report { // A report entry. class Entry : public nlohmann::json { public: Entry() : nlohmann::json() {} template Entry(T t) : nlohmann::json(t) {} /* * I'd like to also declare these two constructors but apparently * there are cases where having all constructors defined create * some ambiguity and I don't know how to avoid that. * * Leaving this comment here so maybe someone can teach me. */ //template Entry(T &t) : nlohmann::json(t) {} //template Entry(T &&t) : nlohmann::json(t) {} Entry(std::initializer_list nl) : nlohmann::json(nl) {} Entry(Entry &) = default; Entry(const Entry &) = default; Entry(Entry &&) = default; static Entry array(); static Entry object(); template Entry &operator=(T t) { nlohmann::json::operator=(t); return *this; } Entry &operator=(std::initializer_list t); Entry &operator=(Entry &) = default; Entry &operator=(Entry &&) = default; template operator ErrorOr() { try { return nlohmann::json::operator T(); } catch (const std::domain_error &) { return JsonDomainError(); } } // Implementation of dict template Entry &operator[](const K &key) { try { return static_cast(nlohmann::json::operator[](key)); } catch (const std::domain_error &) { throw JsonDomainError(); } } static Entry parse(const std::string &s); // Implementation of list void push_back(Entry); template void push_back(T t) { try { nlohmann::json::push_back(t); } catch (const std::domain_error &) { throw JsonDomainError(); } } void push_back(std::initializer_list j); std::string dump(const int indent = -1) const; bool operator==(std::nullptr_t right) const noexcept; bool operator!=(std::nullptr_t right) const noexcept; protected: private: // NO ATTRIBUTES HERE BY DESIGN. DO NOT ADD ATTRIBUTES HERE BECAUSE // DOING THAT CREATES THE RISK OF OBJECT SLICING. }; } // namespace report } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/report/error.hpp000066400000000000000000000020731315356162600246370ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_REPORT_ERROR_HPP #define MEASUREMENT_KIT_REPORT_ERROR_HPP #include namespace mk { namespace report { MK_DEFINE_ERR(MK_ERR_REPORT(0), ReportAlreadyOpenError, "report_already_open") MK_DEFINE_ERR(MK_ERR_REPORT(1), ReportNotOpenError, "report_not_open") MK_DEFINE_ERR(MK_ERR_REPORT(2), ReportAlreadyClosedError, "report_already_closed") MK_DEFINE_ERR(MK_ERR_REPORT(3), ReportEofError, "report_eof_error") MK_DEFINE_ERR(MK_ERR_REPORT(4), ReportIoError, "report_io_error") MK_DEFINE_ERR(MK_ERR_REPORT(5), ReportLogicalError, "report_formatting_error") MK_DEFINE_ERR(MK_ERR_REPORT(6), DuplicateEntrySubmitError, "duplicate_entry_submitted") MK_DEFINE_ERR(MK_ERR_REPORT(7), MissingReportIdError, "missing_report_id") MK_DEFINE_ERR(MK_ERR_REPORT(8), MultipleReportIdsError, "multiple_inconsistent_report_ids") } // namespace report } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/report/file_reporter.hpp000066400000000000000000000014401315356162600263440ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_REPORT_FILE_REPORTER_HPP #define MEASUREMENT_KIT_REPORT_FILE_REPORTER_HPP #include namespace mk { namespace report { class FileReporter : public BaseReporter { public: static Var make(std::string filename); Continuation open(Report &report) override; Continuation write_entry(Entry entry) override; Continuation close() override; ~FileReporter() override {} private: FileReporter() {} std::string filename; std::ofstream file; }; } // namespace report } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/report/ooni_reporter.hpp000066400000000000000000000017761315356162600264050ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_OONI_OONI_REPORTER_HPP #define MEASUREMENT_KIT_OONI_OONI_REPORTER_HPP #include namespace mk { namespace report { class OoniReporter : public BaseReporter { public: static Var make(Settings, Var, Var); Continuation open(Report &report) override; Continuation write_entry(Entry entry) override; Continuation close() override; ~OoniReporter() override {} std::string get_report_id() override; private: OoniReporter(Settings, Var, Var); Var reactor = Reactor::global(); Var logger = Logger::global(); Settings settings; // Our private copy of the ooni_test settings std::string report_id; }; } // namespace report } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/report/report.hpp000066400000000000000000000024351315356162600250230ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_REPORT_REPORT_HPP #define MEASUREMENT_KIT_REPORT_REPORT_HPP #include #include #include namespace mk { namespace report { class BaseReporter; // Forward decl. class Report { public: const std::string software_name = "measurement_kit"; const std::string software_version = MEASUREMENT_KIT_VERSION; const std::string data_format_version = "0.2.0"; std::string test_name; std::string test_version; std::string probe_ip; std::string probe_asn; std::string probe_cc; tm test_start_time; Settings options; std::string report_id; /* Set after open(), if possible */ Report(); void add_reporter(Var reporter); void fill_entry(Entry &entry) const; Entry get_dummy_entry() const; void open(Callback callback); void write_entry(Entry entry, Callback callback, Var logger); void close(Callback callback); private: std::vector> reporters_; }; } // namespace report } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/traceroute/000077500000000000000000000000001315356162600236355ustar00rootroot00000000000000measurement-kit-0.7.1/include/measurement_kit/traceroute/android.hpp000066400000000000000000000133031315356162600257660ustar00rootroot00000000000000/*- * Part of measurement-kit . * Measurement-kit is free software. See AUTHORS and LICENSE for more * information on the copying conditions. * ========================================================================= * Based on Portolan code contributed by its authors. * See . * * Portions Copyright (c) 2015, Adriano Faggiani, Enrico Gregori, * Luciano Lenzini, Valerio Luconi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef MEASUREMENT_KIT_TRACEROUTE_ANDROID_HPP #define MEASUREMENT_KIT_TRACEROUTE_ANDROID_HPP /// Android implementation of traceroute interface // This is meant to run on Android but can run on all Linux systems #ifdef __linux__ #include struct sock_extended_err; struct sockaddr_in6; struct sockaddr_in; struct sockaddr_storage; namespace mk { class Error; namespace traceroute { /// Traceroute prober for Android class AndroidProber : public NonCopyable, public NonMovable, public ProberInterface { public: /// Constructor /// \param use_ipv4 Whether to use IPv4 /// \param port The port to bind /// \param evbase Event base to use (optional) AndroidProber( bool use_ipv4, int port, Var reactor = Reactor::global(), Var logger = Logger::global()); /// Destructor ~AndroidProber() { cleanup(); } void send_probe(std::string addr, int port, int ttl, std::string payload, double timeout) override; void on_result(Callback cb) override { result_cb_ = cb; } void on_timeout(Callback<> cb) override { timeout_cb_ = cb; } void on_error(Callback cb) override { error_cb_ = cb; } private: int sockfd_ = -1; ///< socket descr bool probe_pending_ = false; ///< probe is pending timespec start_time_{0, 0}; ///< start time bool use_ipv4_ = true; ///< using IPv4? Var reactor; ///< The reactor int port_ = 0; ///< socket port Var logger = Logger::global();///< logger Delegate result_cb_; ///< on result callback Delegate<> timeout_cb_; ///< on timeout callback Delegate error_cb_; ///< on error callback /// Call this when you don't receive a response within timeout void on_timeout() { probe_pending_ = false; } /// Initialize socket void init(); /// Call this as soon as the socket is readable to get /// the result ICMP error received by the socket and to /// calculate *precisely* the RTT. ProbeResult on_socket_readable(); /// Returns the source address of the error message. /// \param s IPv4 socket address /// \return source address of the error message static std::string get_source_addr(const sockaddr_in *s); /// Returns the source address of the error message. /// \param s IPv6 socket address /// \return source address of the error message static std::string get_source_addr(const sockaddr_in6 *s); /// Returns the source address of the error message. /// \param use_ipv4 whether we are using IPv4 /// \param ss Pointer to sockaddr_storage struct /// \return source address of the error message static std::string get_source_addr(bool use_ipv4, const sockaddr_storage *ss); /// Returns the source address of the error message. /// \param use_ipv4 whether we are using IPv4 /// \param err socket error structure /// \return source address of the error message static std::string get_source_addr(bool use_ipv4, sock_extended_err *err); /// Returns the Round Trip Time value in milliseconds /// \param end ICMP reply arrival time /// \param start UDP probe send time /// \return RTT value in milliseconds static double calculate_rtt(timespec end, timespec start); /// Returns the Time to Live of the error message /// \param data CMSG_DATA(cmsg) /// \return ttl of the error message static int get_ttl(void *data) { return *((int *)data); } /// Callback invoked when the socket is readable /// \param so Socket descriptor /// \param event Event that occurred void event_callback(Error err, short event); /// Idempotent cleanup function void cleanup(); }; } // namespace traceroute } // namespace mk #endif #endif measurement-kit-0.7.1/include/measurement_kit/traceroute/error.hpp000066400000000000000000000024761315356162600255100ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef MEASUREMENT_KIT_TRACEROUTE_ERROR_HPP #define MEASUREMENT_KIT_TRACEROUTE_ERROR_HPP #include namespace mk { namespace traceroute { MK_DEFINE_ERR(MK_ERR_TRACEROUTE(0), SocketCreateError, "cannot_create_socket") MK_DEFINE_ERR(MK_ERR_TRACEROUTE(1), SetsockoptError, "cannot_set_socket_options") MK_DEFINE_ERR(MK_ERR_TRACEROUTE(2), ProbeAlreadyPendingError, "response_already_pending") MK_DEFINE_ERR(MK_ERR_TRACEROUTE(3), PayloadTooLongError, "payload_too_large") MK_DEFINE_ERR(MK_ERR_TRACEROUTE(4), StorageInitError, "cannot_initialize_socket_address") MK_DEFINE_ERR(MK_ERR_TRACEROUTE(5), BindError, "cannot_bind_socket") MK_DEFINE_ERR(MK_ERR_TRACEROUTE(6), EventNewError, "event_new_error") MK_DEFINE_ERR(MK_ERR_TRACEROUTE(7), SendtoError, "cannot_send_packet") MK_DEFINE_ERR(MK_ERR_TRACEROUTE(8), NoProbePendingError, "no_probe_is_pending") MK_DEFINE_ERR(MK_ERR_TRACEROUTE(9), ClockGettimeError, "cannot_get_current_time") MK_DEFINE_ERR(MK_ERR_TRACEROUTE(10), EventAddError, "event_add_error") MK_DEFINE_ERR(MK_ERR_TRACEROUTE(11), SocketAlreadyClosedError, "socket_already_closed") } // namespace net } // namespace mk #endif measurement-kit-0.7.1/include/measurement_kit/traceroute/interface.hpp000066400000000000000000000126001315356162600263050ustar00rootroot00000000000000/*- * Part of measurement-kit . * Measurement-kit is free software. See AUTHORS and LICENSE for more * information on the copying conditions. * ========================================================================= * Based on Portolan code contributed by its authors. * See . * * Portions Copyright (c) 2015, Adriano Faggiani, Enrico Gregori, * Luciano Lenzini, Valerio Luconi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef MEASUREMENT_KIT_TRACEROUTE_INTERFACE_HPP #define MEASUREMENT_KIT_TRACEROUTE_INTERFACE_HPP /// Interface of traceroute module // Disable for non Linux until we figure out how to build on iOS #ifdef __linux__ #include namespace mk { namespace traceroute { /// Meaning of a probe result enum class ProbeResultMeaning { OTHER = 0, ///< Another meaning NO_ROUTE_TO_HOST = 1, ///< No route to host ADDRESS_UNREACH = 2, ///< E.g., link down PROTO_NOT_IMPL = 3, ///< UDP not implemented PORT_IS_CLOSED = 4, ///< Port is closed TTL_EXCEEDED = 5, ///< TTL is too small ADMIN_FILTER = 6, ///< E.g., firewall rule GOT_REPLY_PACKET = 7, ///< We got a real reply packet }; /// Result of a traceroute probe class ProbeResult { public: std::string interface_ip; ///< Host that replied int ttl = 0; ///< Response TTL double rtt = 0.0; ///< Round trip time bool is_ipv4 = true; ///< Are we using IPv4? unsigned char icmp_type = 255; ///< Raw ICMP/ICMPv6 type unsigned char icmp_code = 255; ///< Raw ICMP/ICMPv6 code ssize_t recv_bytes = 0; ///< Bytes recv'd bool valid_reply = false; ///< Whether reply is valid std::string reply; ///< Reply packet data /// Maps ICMP/ICMPv6 type and code to a meaning ProbeResultMeaning get_meaning(); }; /// Interface of a prober class ProberInterface { public: /// Default constructor ProberInterface() {} /// Send a traceroute probe /// In case of error this function emits error-event /// \param addr Destination address /// \param port Destination port /// \param ttl Time to live /// \param payload packet payload /// \param timeout Timeout for this probe virtual void send_probe(std::string addr, int port, int ttl, std::string payload, double timeout) = 0; /// Set callback called when result is available virtual void on_result(Callback cb) = 0; /// Set callback called on timeout virtual void on_timeout(Callback<> cb) = 0; /// Set callback called when there is an error virtual void on_error(Callback cb) = 0; /// Default copy constructor ProberInterface(ProberInterface &) = default; /// Default assignment operator ProberInterface &operator=(ProberInterface &) = default; /// Default move constructor ProberInterface(ProberInterface &&) = default; /// Default move assignment operator ProberInterface &operator=(ProberInterface &&) = default; /// Default destructor virtual ~ProberInterface(); }; /// Proxy for a prober implementation template class Prober : public ProberInterface { public: /// Constructor /// \param use_ipv4 Whether to use IPv4 /// \param port The port to bind /// \param evbase Event base to use (optional) /// \throws Exception on error Prober(bool use_ipv4, int port, Var reactor = Reactor::global()) { impl_.reset(new Impl(use_ipv4, port, reactor)); } void send_probe(std::string addr, int port, int ttl, std::string payload, double timeout) override { impl_->send_probe(addr, port, ttl, payload, timeout); } void on_result(Callback cb) override { impl_->on_result(cb); } void on_timeout(Callback<> cb) override { impl_->on_timeout(cb); } void on_error(Callback cb) override { impl_->on_error(cb); } private: std::unique_ptr impl_; }; } // namespace traceroute } // namespace mk #endif #endif measurement-kit-0.7.1/include/private/000077500000000000000000000000001315356162600177365ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/common/000077500000000000000000000000001315356162600212265ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/common/async_runner.hpp000066400000000000000000000120671315356162600244530ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_COMMON_ASYNC_RUNNER_HPP #define PRIVATE_COMMON_ASYNC_RUNNER_HPP #include #include #include #include #include #include #include #include #include namespace mk { class AsyncRunner : public HasGlobalFactory, public NonCopyable, public NonMovable { public: // Adapted from src/libmeasurement_kit/nettests/runner.cpp template void start(std::string &&name, Var logger, Task &&task, Callback &&cb) { assert(active_ >= 0); start_background_thread(logger); active_ += 1; logger->debug("%s: scheduling", name.c_str()); // Give background thread exclusive ownership of arguments reactor_->call_soon([ task = std::move(task), cb = std::move(cb), name = std::move(name), logger, this ]() { logger->debug("%s: starting", name.c_str()); // Make sure the lambda's closure keeps the task alive task([task, cb, name, logger, this](Error &&error) { logger->debug("%s: finished", name.c_str()); // WARNING: this closure keeps task alive but it MAY be invoked // by objects that MAY die after task is destroyed and that also // MAY do some work after the closure returns. To avoid issues // with use-after-free defer calling the final `cb`, and ensure // the closure keeps the task alive until that point in time. // // Notes: // // 1. if all objects avoid passing `this` to closures, we // can probably avoid doing this safety step // // 2. this last callback is mutable so it can be matched // by funtions that take a mutable error as argument reactor_->call_soon([task, cb, name, logger, this, error]() mutable { logger->debug("%s: callback", name.c_str()); active_ -= 1; logger->debug("runner: #active: %lld", (long long)active_); cb(std::move(error)); }); }); }); } // Semi-hidden method for now only used internally. The reason why it is // not advertised is that it does not provide the guarantees of the above // version of `start`, and it must be used with code that does not pass // the `this` of objects to any callback. template void start_(std::string &&name, Var logger, Task &&task) { start_background_thread(logger); assert(active_ >= 0); active_ += 1; logger->debug("%s: scheduling", name.c_str()); reactor_->call_soon([ task = std::move(task), name = std::move(name), logger, this ]() mutable { logger->debug("%s: starting", name.c_str()); task([name, logger, this](Callback<> &&cb) mutable { logger->debug("%s: finished", name.c_str()); active_ -= 1; logger->debug("runner: #active: %lld", (long long)active_); logger->debug("%s: callback", name.c_str()); cb(); }); }); } void stop() { if (running_) { // WARNING: Make sure we stop the runner before we stop the // thread otherwise we will most likely segfault. reactor_->stop(); thread_.join(); running_ = false; } } long long active() { return active_; } bool running() { return running_; } ~AsyncRunner() { stop(); } Var reactor() { return reactor_; } private: std::atomic active_{0}; Var reactor_ = Reactor::make(); std::atomic running_{false}; std::thread thread_; void start_background_thread(Var logger) { if (!running_) { std::promise promise; std::future future = promise.get_future(); // WARNING: the destructor MUST wait for the thread because we // are passing `this` to the thread's function. logger->debug("runner: starting reactor in background..."); thread_ = std::thread([&promise, this, logger]() { reactor_->run_with_initial_event([&promise, logger]() { logger->debug("runner: background reactor running..."); promise.set_value(); }); }); future.wait(); running_ = true; } } }; } // namespace mk #endif measurement-kit-0.7.1/include/private/common/encoding.hpp000066400000000000000000000006561315356162600235340ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_COMMON_ENCODING_HPP #define PRIVATE_COMMON_ENCODING_HPP #include namespace mk { Error is_valid_utf8_string(const std::string &s); std::string base64_encode(std::string s); } // namespace mk #endif measurement-kit-0.7.1/include/private/common/encoding_base64_impl.hpp000066400000000000000000000046201315356162600257140ustar00rootroot00000000000000/*- * Part of measurement-kit . * Measurement-kit is free software. See AUTHORS and LICENSE for more * information on the copying conditions. * ============================================================================= * base64.cpp and base64.h * * Portions Copyright (C) 2004-2008 René Nyffenegger * * This source code is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this source code must not be misrepresented; you must not * claim that you wrote the original source code. If you use this source code * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original source code. * * 3. This notice may not be removed or altered from any source distribution. * * René Nyffenegger rene.nyffenegger@adp-gmbh.ch */ #ifndef PRIVATE_COMMON_ENCODING_BASE64_IMPL_HPP #define PRIVATE_COMMON_ENCODING_BASE64_IMPL_HPP #include #include namespace mk { static std::string base64_encode_impl(const uint8_t *base, size_t len) { static const std::string b64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; std::string res; uint8_t in[3]; uint8_t out[4]; int state = 0; auto copy = [&]() { out[0] = (in[0] & 0xfc) >> 2; out[1] = ((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4); out[2] = ((in[1] & 0x0f) << 2) + ((in[2] & 0xc0) >> 6); out[3] = in[2] & 0x3f; for (int idx = 0; idx < 4; ++idx) { res += (idx <= state) ? b64_table[out[idx]] : '='; } }; while (len-- > 0) { in[state++] = *(base++); if (state == 3) { copy(); state = 0; } } if (state != 0) { for (int idx = state; idx < 3; ++idx) { in[idx] = '\0'; } copy(); } return res; } } // namespace mk #endif measurement-kit-0.7.1/include/private/common/every.hpp000066400000000000000000000016711315356162600230760ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_COMMON_EVERY_HPP #define PRIVATE_COMMON_EVERY_HPP #include #include namespace mk { template void every(double delay, Var reactor, Callback callback, StopPredicate stop_predicate, Callable callable) { reactor->call_soon([=]() { if (delay <= 0.0) { callback(ValueError()); return; } if (stop_predicate()) { callback(NoError()); return; } callable(); reactor->call_later(delay, [=]() { every(delay, reactor, callback, stop_predicate, callable); }); }); } } // namespace mk #endif measurement-kit-0.7.1/include/private/common/fapply.hpp000066400000000000000000000041031315356162600232300ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. // ============================================================= // Based on #ifndef PRIVATE_COMMON_FAPPLY_HPP #define PRIVATE_COMMON_FAPPLY_HPP #include #include namespace mk { /* * fapply() */ template constexpr auto fapply_(F &&f, std::tuple &&t, std::index_sequence) { return f(std::move(std::get(t))...); } // start compile time recursion to ensure the compiler generates code such // that `f` is called with all the arguments inside `t` template constexpr auto fapply(F &&f, std::tuple &&t) { return fapply_(std::move(f), std::move(t), std::index_sequence_for{}); } // convert arbitrary arguments into a tuple template constexpr auto fapply(F &&f, A &&... a) { return fapply(std::move(f), std::make_tuple(std::forward(a)...)); } /* * fapply_with_callback() */ template constexpr void fapply_with_callback_(F &&f, CB &&cb, std::tuple &&t, std::index_sequence) { f(std::move(std::get(t))..., std::move(cb)); } // start compile time recursion to ensure the compiler generates code such // that `f` is called with all the arguments inside `t` template constexpr void fapply_with_callback(F &&f, CB &&cb, std::tuple &&t) { fapply_with_callback_(std::move(f), std::move(cb), std::move(t), std::index_sequence_for{}); } // convert arbitrary arguments into a tuple template constexpr void fapply_with_callback(F &&f, CB &&cb, A &&... a) { fapply_with_callback(std::move(f), std::move(cb), std::make_tuple(std::forward(a)...)); } } // namespace mk #endif measurement-kit-0.7.1/include/private/common/fcar.hpp000066400000000000000000000010341315356162600226500ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. // ============================================================= // Based on #ifndef PRIVATE_COMMON_FCAR_HPP #define PRIVATE_COMMON_FCAR_HPP #include namespace mk { template constexpr T fcar(const std::tuple &t) { return std::get<0>(t); } } // namespace mk #endif measurement-kit-0.7.1/include/private/common/fcdr.hpp000066400000000000000000000015451315356162600226620ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. // ============================================================= // Based on #ifndef PRIVATE_COMMON_FCDR_HPP #define PRIVATE_COMMON_FCDR_HPP #include #include namespace mk { template constexpr auto fcdr_impl_(std::tuple &&t, std::index_sequence) { // Note: using `+1` so we skip the first element of the original tuple return std::make_tuple(std::move(std::get(t))...); } template constexpr auto fcdr(std::tuple &&t) { return fcdr_impl_(std::move(t), std::make_index_sequence{}); } } // namespace mk #endif measurement-kit-0.7.1/include/private/common/fcompose.hpp000066400000000000000000000051501315356162600235530ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_COMMON_FCOMPOSE_HPP #define PRIVATE_COMMON_FCOMPOSE_HPP #include "private/common/fapply.hpp" #include "private/common/fcar.hpp" #include "private/common/fcdr.hpp" #include "private/common/freverse.hpp" namespace mk { // pathologic corner case template constexpr auto fcompose_(const P &, F &&f, std::tuple &&, std::index_sequence<0>) { return f; } // base case template constexpr auto fcompose_(const P &p, F &&f, std::tuple &&g, std::index_sequence<1>) { return p(f, fcar(g)); } // generic case template = 2)>::type> constexpr auto fcompose_(const P &p, F &&f, std::tuple &&g, std::index_sequence) { return fcompose_(p, p(f, fcar(g)), fcdr(std::move(g)), std::index_sequence{}); } // Set policy `p`, convert `g...` into a tuple and start compile time recursion template constexpr auto fcompose(P &&p, F &&f, G &&... g) { return fcompose_(p, f, std::make_tuple(std::forward(g)...), std::index_sequence{}); } class fcompose_policy_sync { public: template constexpr auto operator()(F &&f, G &&g) const { return [ f = std::move(f), g = std::move(g) ](auto &&... f_in) mutable { return fapply(g, fapply(f, std::move(f_in)...)); }; } }; class fcompose_policy_async { public: template constexpr auto operator()(F &&f, G &&g) const { return [ f = std::move(f), g = std::move(g) ](auto &&... f_in) mutable { auto f_tuple = std::make_tuple(std::move(f_in)...); auto f_rev = freverse(std::move(f_tuple)); auto g_cb = fcar(f_rev); auto args = freverse(std::move(fcdr(std::move(f_rev)))); auto f_cb = [ g = std::move(g), g_cb = std::move(g_cb) ](auto &&... f_out) mutable { fapply_with_callback(std::move(g), std::move(g_cb), std::move(f_out)...); }; fapply_with_callback(std::move(f), std::move(f_cb), std::move(args)); }; } }; } // namespace mk #endif measurement-kit-0.7.1/include/private/common/fmap.hpp000066400000000000000000000012531315356162600226630ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. // ============================================================= // Based on #ifndef PRIVATE_COMMON_FMAP_HPP #define PRIVATE_COMMON_FMAP_HPP #include #include #include namespace mk { template std::vector fmap(std::vector i, std::function f) { std::vector o; std::transform(i.begin(), i.end(), std::back_inserter(o), f); return std::move(o); } } // namespace mk #endif measurement-kit-0.7.1/include/private/common/freverse.hpp000066400000000000000000000014441315356162600235630ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. // ============================================================= // Based on #ifndef PRIVATE_COMMON_FREVERSE_HPP #define PRIVATE_COMMON_FREVERSE_HPP #include #include namespace mk { template constexpr auto freverse_(std::tuple &&t, std::index_sequence) { return std::make_tuple(std::move(std::get(t))...); } template constexpr auto freverse(std::tuple &&t) { return freverse_(std::move(t), std::make_index_sequence{}); } } // namespace mk #endif measurement-kit-0.7.1/include/private/common/json.hpp000066400000000000000000000031031315356162600227050ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_COMMON_JSON_HPP #define PRIVATE_COMMON_JSON_HPP #include "private/common/sandbox.hpp" #include #include namespace mk { template Error json_process(nlohmann::json &json, Callable &&fun) { Error err = NoError(); try { fun(json); } catch (const std::out_of_range &) { err = JsonKeyError(); } catch (const std::domain_error &) { err = JsonDomainError(); } return err; } template Error json_process_and_filter_errors(nlohmann::json &json, Callable &&fun) { return sandbox_for_errors([&]() { auto err = json_process(json, std::move(fun)); if (err) { throw err; } }); } template Error json_parse_and_process(Stringlike str, Callable &&fun) { nlohmann::json json; try { json = nlohmann::json::parse(str); } catch (const std::invalid_argument &) { return JsonParseError(); } return json_process(json, std::move(fun)); } template Error json_parse_process_and_filter_errors(Stringlike str, Callable &&fun) { return sandbox_for_errors([&]() { auto err = json_parse_and_process(str, std::move(fun)); if (err) { throw err; } }); } } // namespace mk #endif measurement-kit-0.7.1/include/private/common/mock.hpp000066400000000000000000000013771315356162600227000ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_COMMON_MOCK_HPP #define PRIVATE_COMMON_MOCK_HPP /* Simplifies life when you use templates for mocking APIs because allows you to write the following: template void foobar() { event_base *p = event_base_new(); } Which is arguably faster than writing the following: template void foobar() { ... */ #define MK_MOCK(name_) MK_MOCK_AS(name_, name_) // Similar to MK_MOCK but with alias #define MK_MOCK_AS(name_, alias_) decltype(name_) alias_ = name_ #endif measurement-kit-0.7.1/include/private/common/parallel.hpp000066400000000000000000000010271315356162600235330ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_COMMON_PARALLEL_HPP #define PRIVATE_COMMON_PARALLEL_HPP #include #include namespace mk { void parallel(std::vector> input, Callback cb, size_t parallelism = 0 /* means equal to input.size() */); } // namespace mk #endif measurement-kit-0.7.1/include/private/common/range.hpp000066400000000000000000000011311315356162600230270ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. // ============================================================= // Based on #ifndef PRIVATE_COMMON_RANGE_HPP #define PRIVATE_COMMON_RANGE_HPP #include #include namespace mk { template std::vector range(size_t count) { std::vector vector(count); std::iota(vector.begin(), vector.end(), 0); return vector; } } // namespace mk #endif measurement-kit-0.7.1/include/private/common/sandbox.hpp000066400000000000000000000014251315356162600233770ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_COMMON_SANDBOX_HPP #define PRIVATE_COMMON_SANDBOX_HPP #include #include namespace mk { template Error sandbox_for_errors(Callable fun) { Error error = NoError(); try { fun(); } catch (const Error &exc) { error = exc; } return error; } template Maybe sandbox_for_exceptions(Callable fun) { try { fun(); } catch (std::exception &exc) { return std::move(exc); } return {}; } } // namespace mk #endif measurement-kit-0.7.1/include/private/common/utils.hpp000066400000000000000000000015571315356162600231070ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_KIT_COMMON_UTILS_HPP #define PRIVATE_KIT_COMMON_UTILS_HPP #include struct timeval; namespace mk { std::string random_within_charset(std::string charset, size_t length); std::string random_printable(size_t length); std::string random_str(size_t length); std::string random_str_uppercase(size_t length); std::string random_choice(std::vector inputs); std::string randomly_capitalize(std::string input); void dump_settings(Settings &s, std::string prefix, Var logger); double percentile(std::vector v, double percent); inline double median(std::vector v) { return percentile(v, 0.5); } } // namespace mk #endif measurement-kit-0.7.1/include/private/common/utils_impl.hpp000066400000000000000000000055631315356162600241310ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_COMMON_UTILS_IMPL_HPP #define PRIVATE_COMMON_UTILS_IMPL_HPP #include "private/common/mock.hpp" #include "private/common/mock.hpp" #include "../common/utils.hpp" #include #include namespace mk { /* * There are many ways in C++ to slurp the whole content of a file into a * C++ string. The following is my favourite. Compared to other methods, * not only this seems fastest, but also it provides greater control over * errors that can occur. Thus mocking is simpler. * * See . */ template ErrorOr> slurpv_impl(std::string p) { FILE *filep = std_fopen(p.c_str(), "rb"); if (filep == nullptr) { return FileIoError(); } if (std_fseek_1(filep, 0, SEEK_END) != 0) { std_fclose(filep); return FileIoError(); } // Note: ftello() might be better for reading very large files but // honestly I do think we should use some kind of mmap for them. long pos = std_ftell(filep); if (pos < 0) { std_fclose(filep); return FileIoError(); } std::vector result; // Note: cast to unsigned safe because we excluded negative case above result.resize((unsigned long)pos, 0); if (std_fseek_2(filep, 0, SEEK_SET) != 0) { std_fclose(filep); return FileIoError(); } size_t nread = std_fread(result.data(), 1, result.size(), filep); // Note: cast to unsigned safe because we excluded negative case above if ((unsigned long)pos != nread) { (void)std_fclose(filep); return FileIoError(); } // Note: afaik fclose() should not fail when we're just reading if (std_fclose(filep) != 0) { return FileIoError(); } return result; } template Error overwrite_file_impl(std::string path, std::string content) { FILE *filep = std_fopen(path.c_str(), "wb"); if (filep == nullptr) { return FileIoError(); } size_t count = std_fwrite(content.data(), 1, content.size(), filep); if (count != content.size()) { (void)std_fclose(filep); return FileIoError(); } if (std_fclose(filep) != 0) { return FileIoError(); } return NoError(); } } // namespace mk #endif measurement-kit-0.7.1/include/private/common/worker.hpp000066400000000000000000000024401315356162600232500ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_COMMON_WORKER_HPP #define PRIVATE_COMMON_WORKER_HPP #include #include #include #include #include #include namespace mk { class Worker : public HasGlobalFactory, public NonCopyable, public NonMovable { public: void run_in_background_thread(Callback<> &&func); size_t parallelism(); void set_parallelism(size_t); short concurrency(); private: /* * Variables allocated indirectly using `Var` because they need to * survive this class lifetime when background threads use them. */ Var>> queue_ = Var>>::make(); Var mutex_ = Var::make(); Var active_ = Var::make(); /* * Not allocated using `Var`, because it is only accessed by * this object and background threads do not see it. */ size_t parallelism_ = 3; }; } // namespace mk #endif measurement-kit-0.7.1/include/private/dns/000077500000000000000000000000001315356162600205225ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/dns/getaddrinfo_async.hpp000066400000000000000000000111201315356162600247110ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_DNS_GETADDRINFO_ASYNC_HPP #define PRIVATE_DNS_GETADDRINFO_ASYNC_HPP #include namespace mk { namespace dns { #define GETADDRINFO_ASYNC_MAP_ERROR \ XX(0, NoError) \ XX(EAI_AGAIN, TemporaryFailureError) \ XX(EAI_BADFLAGS, InvalidFlagsValueError) \ XX(EAI_FAIL, NonRecoverableFailureError) \ XX(EAI_FAMILY, NotSupportedAIFamilyError) \ XX(EAI_MEMORY, MemoryAllocationFailureError) \ XX(EAI_NONAME, HostOrServiceNotProvidedOrNotKnownError) \ XX(EAI_OVERFLOW, ArgumentBufferOverflowError) \ XX(EAI_SERVICE, NotSupportedServnameError) \ XX(EAI_SOCKTYPE, NotSupportedAISocktypeError) inline Error getaddrinfo_async_map_error(int error) { switch (error) { #define XX(code_, class_name_) \ case code_: \ return class_name_(); GETADDRINFO_ASYNC_MAP_ERROR #undef XX #ifdef EAI_BADHINTS // Not always available case EAI_BADHINTS: return InvalidHintsValueError(); #endif #ifdef EAI_PROTOCOL // Not always available case EAI_PROTOCOL: return UnknownResolvedProtocolError(); #endif default: break; } return ResolverError(); } template std::vector getaddrinfo_async_parse_response(const std::string &name, addrinfo *rp) { std::vector answers; for (addrinfo *p = rp; p != nullptr; p = p->ai_next) { Answer answer; answer.name = name; answer.qclass = "IN"; void *aptr = nullptr; if (p->ai_family == AF_INET) { answer.type = MK_DNS_TYPE_A; aptr = &((sockaddr_in *)p->ai_addr)->sin_addr; } else if (p->ai_family == AF_INET6) { answer.type = MK_DNS_TYPE_AAAA; aptr = &((sockaddr_in6 *)p->ai_addr)->sin6_addr; } else { throw GenericError(); /* Avoid g++ warning */ } if (p->ai_canonname != nullptr) { answer.hostname = p->ai_canonname; } char abuf[128]; if (inet_ntop(p->ai_family, aptr, abuf, sizeof(abuf)) == nullptr) { throw InetNtopFailureError(); } if (p->ai_family == AF_INET) { answer.ipv4 = abuf; } else if (p->ai_family == AF_INET6) { answer.ipv6 = abuf; } else { /* Case excluded above */; } answers.push_back(answer); } return answers; } template void getaddrinfo_async(std::string name, addrinfo hints, Var reactor, Var logger, Var worker, Callback> cb) { /* * Move everything down such that there is always just one function in * one specific thread having ownership of the state */ worker->run_in_background_thread([ name = std::move(name), hints = std::move(hints), reactor = std::move(reactor), logger = std::move(logger), cb = std::move(cb) ]() { addrinfo *rp = nullptr; Error error = getaddrinfo_async_map_error( getaddrinfo(name.c_str(), nullptr, &hints, &rp)); logger->debug("getaddrinfo('%s') => %s", name.c_str(), error.as_ooni_error().c_str()); std::vector answers; if (!error && rp != nullptr) { try { answers = getaddrinfo_async_parse_response(name, rp); } catch (const Error &err) { error = std::move(err); } } if (rp != nullptr) { freeaddrinfo(rp); } /* * Pass through call soon such that the callback executes in the * thread in which we're running our async I/O loop. */ reactor->call_soon([ cb = std::move(cb), error = std::move(error), answers = std::move(answers) ]() { cb(error, answers); }); }); } } // namespace dns } // namespace mk #endif measurement-kit-0.7.1/include/private/dns/ping.hpp000066400000000000000000000022121315356162600221650ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_DNS_PING_HPP #define PRIVATE_DNS_PING_HPP #include "private/common/every.hpp" #include namespace mk { namespace dns { template void ping_nameserver(QueryClass dns_class, QueryType dns_type, std::string name, double interval, Maybe run_for, Settings settings, Var reactor, Var logger, ResultsCollector collector, Callback callback) { if (run_for) { *run_for += time_now(); /* From relative to absolute timing */ } mk::every( interval, reactor, callback, [=]() { return run_for && time_now() > *run_for; }, [=]() { query(dns_class, dns_type, name, [=](Error err, Var msg) { collector(err, msg); }, settings, reactor, logger); }); } } // namespace dns } // namespace mk #endif measurement-kit-0.7.1/include/private/dns/system_resolver.hpp000066400000000000000000000045051315356162600245040ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_DNS_SYSTEM_RESOLVER_HPP #define PRIVATE_DNS_SYSTEM_RESOLVER_HPP #include "private/common/mock.hpp" #include "private/common/worker.hpp" #include "private/common/mock.hpp" #include "private/common/worker.hpp" #include #include "../dns/getaddrinfo_async.hpp" namespace mk { namespace dns { template void system_resolver(QueryClass dns_class, QueryType dns_type, std::string name, Var reactor, Var logger, Callback> cb) { Query query; addrinfo hints = {}; /* * Note: here we pass empty flags. It used to be AI_ALL | AI_V4MAPPED but * Android did not like it and, honestly, I do not think having back v4 * mapped addresses would be super useful to us (or in general) given that * when we want to connect we usually connect trying to resolve AAAA and * A at the same time. Keeping the feature conditionally may lead to * odd behaviors in corner cases and I'd like to avoid future headaches. */ hints.ai_socktype = SOCK_STREAM; if (dns_class != MK_DNS_CLASS_IN) { reactor->call_soon([=]() { cb(UnsupportedClassError(), nullptr); }); return; } if (dns_type == MK_DNS_TYPE_A) { hints.ai_family = AF_INET; } else if (dns_type == MK_DNS_TYPE_AAAA) { hints.ai_family = AF_INET6; } else if (dns_type == MK_DNS_TYPE_CNAME) { hints.ai_family = AF_UNSPEC; hints.ai_flags |= AI_CANONNAME; } else { reactor->call_soon([=]() { cb(UnsupportedTypeError(), nullptr); }); return; } query.type = dns_type; query.qclass = dns_class; query.name = name; Var message{new Message}; message->queries.push_back(query); getaddrinfo_async( name, hints, reactor, logger, Worker::global(), [ message = std::move(message), cb = std::move(cb) ](Error error, std::vector answers) { message->answers = std::move(answers); cb(error, message); }); } } // namespace dns } // namespace mk #endif measurement-kit-0.7.1/include/private/ext/000077500000000000000000000000001315356162600205365ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/ext/catch.hpp000066400000000000000000014707571315356162600223560ustar00rootroot00000000000000/* * Catch v1.10.0 * Generated: 2017-08-26 15:16:46.676990 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED #define TWOBLUECUBES_CATCH_HPP_INCLUDED #ifdef __clang__ # pragma clang system_header #elif defined __GNUC__ # pragma GCC system_header #endif // #included from: internal/catch_suppress_warnings.h #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro # pragma warning(push) # pragma warning(disable: 161 1682) # else // __ICC # pragma clang diagnostic ignored "-Wglobal-constructors" # pragma clang diagnostic ignored "-Wvariadic-macros" # pragma clang diagnostic ignored "-Wc99-extensions" # pragma clang diagnostic ignored "-Wunused-variable" # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wpadded" # pragma clang diagnostic ignored "-Wc++98-compat" # pragma clang diagnostic ignored "-Wc++98-compat-pedantic" # pragma clang diagnostic ignored "-Wswitch-enum" # pragma clang diagnostic ignored "-Wcovered-switch-default" # endif #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wvariadic-macros" # pragma GCC diagnostic ignored "-Wunused-variable" # pragma GCC diagnostic ignored "-Wparentheses" # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpadded" #endif #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) # define CATCH_IMPL #endif #ifdef CATCH_IMPL # ifndef CLARA_CONFIG_MAIN # define CLARA_CONFIG_MAIN_NOT_DEFINED # define CLARA_CONFIG_MAIN # endif #endif // #included from: internal/catch_notimplemented_exception.h #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED // #included from: catch_common.h #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED // #included from: catch_compiler_capabilities.h #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED // Detect a number of compiler features - mostly C++11/14 conformance - by compiler // The following features are defined: // // CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? // CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? // CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? // CATCH_CONFIG_CPP11_OVERRIDE : is override supported? // CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) // CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported? // CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported? // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? // **************** // Note to maintainers: if new toggles are added please document them // in configuration.md, too // **************** // In general each macro has a _NO_ form // (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. // Many features, at point of detection, define an _INTERNAL_ macro, so they // can be combined, en-mass, with the _NO_ forms later. // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 #ifdef __cplusplus # if __cplusplus >= 201103L # define CATCH_CPP11_OR_GREATER # endif # if __cplusplus >= 201402L # define CATCH_CPP14_OR_GREATER # endif #endif #ifdef __clang__ # if __has_feature(cxx_nullptr) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # endif # if __has_feature(cxx_noexcept) # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT # endif # if defined(CATCH_CPP11_OR_GREATER) # define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ _Pragma( "clang diagnostic push" ) \ _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) # define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ _Pragma( "clang diagnostic pop" ) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ _Pragma( "clang diagnostic push" ) \ _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ _Pragma( "clang diagnostic pop" ) # endif #endif // __clang__ //////////////////////////////////////////////////////////////////////////////// // We know some environments not to support full POSIX signals #if defined(__CYGWIN__) || defined(__QNX__) # if !defined(CATCH_CONFIG_POSIX_SIGNALS) # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS # endif #endif #ifdef __OS400__ # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS # define CATCH_CONFIG_COLOUR_NONE #endif //////////////////////////////////////////////////////////////////////////////// // Cygwin #ifdef __CYGWIN__ // Required for some versions of Cygwin to declare gettimeofday // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin # define _BSD_SOURCE #endif // __CYGWIN__ //////////////////////////////////////////////////////////////////////////////// // Borland #ifdef __BORLANDC__ #endif // __BORLANDC__ //////////////////////////////////////////////////////////////////////////////// // EDG #ifdef __EDG_VERSION__ #endif // __EDG_VERSION__ //////////////////////////////////////////////////////////////////////////////// // Digital Mars #ifdef __DMC__ #endif // __DMC__ //////////////////////////////////////////////////////////////////////////////// // GCC #ifdef __GNUC__ # if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # endif // - otherwise more recent versions define __cplusplus >= 201103L // and will get picked up below #endif // __GNUC__ //////////////////////////////////////////////////////////////////////////////// // Visual C++ #ifdef _MSC_VER #define CATCH_INTERNAL_CONFIG_WINDOWS_SEH #if (_MSC_VER >= 1600) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR #endif #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS #define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE #define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS #endif #endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// // Use variadic macros if the compiler supports them #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ ( defined __GNUC__ && __GNUC__ >= 3 ) || \ ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS #endif // Use __COUNTER__ if the compiler supports it #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ ( defined __clang__ && __clang_major__ >= 3 ) #define CATCH_INTERNAL_CONFIG_COUNTER #endif //////////////////////////////////////////////////////////////////////////////// // C++ language feature support // catch all support for C++11 #if defined(CATCH_CPP11_OR_GREATER) # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # endif # ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT # endif # ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS # define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS # endif # ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM # define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM # endif # ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE # define CATCH_INTERNAL_CONFIG_CPP11_TUPLE # endif # ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS # endif # if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG # endif # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE # endif # if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR # endif # if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) # define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE # endif # if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) # define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS # endif #endif // __cplusplus >= 201103L // Now set the actual defines based on the above + anything the user has configured #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_NULLPTR #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_NOEXCEPT #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_GENERATED_METHODS #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_IS_ENUM #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_TUPLE #endif #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) # define CATCH_CONFIG_VARIADIC_MACROS #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_LONG_LONG #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_OVERRIDE #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_UNIQUE_PTR #endif // Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for // analytics) because, at time of writing, __COUNTER__ is not properly handled by it. // This does not affect compilation #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__) # define CATCH_CONFIG_COUNTER #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_SHUFFLE #endif # if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_TYPE_TRAITS # endif #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) # define CATCH_CONFIG_WINDOWS_SEH #endif // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. #if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) # define CATCH_CONFIG_POSIX_SIGNALS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS #endif // noexcept support: #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) # define CATCH_NOEXCEPT noexcept # define CATCH_NOEXCEPT_IS(x) noexcept(x) #else # define CATCH_NOEXCEPT throw() # define CATCH_NOEXCEPT_IS(x) #endif // nullptr support #ifdef CATCH_CONFIG_CPP11_NULLPTR # define CATCH_NULL nullptr #else # define CATCH_NULL NULL #endif // override support #ifdef CATCH_CONFIG_CPP11_OVERRIDE # define CATCH_OVERRIDE override #else # define CATCH_OVERRIDE #endif // unique_ptr support #ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR # define CATCH_AUTO_PTR( T ) std::unique_ptr #else # define CATCH_AUTO_PTR( T ) std::auto_ptr #endif #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) #ifdef CATCH_CONFIG_COUNTER # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) #else # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) #endif #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) #include #include namespace Catch { struct IConfig; struct CaseSensitive { enum Choice { Yes, No }; }; class NonCopyable { #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS NonCopyable( NonCopyable const& ) = delete; NonCopyable( NonCopyable && ) = delete; NonCopyable& operator = ( NonCopyable const& ) = delete; NonCopyable& operator = ( NonCopyable && ) = delete; #else NonCopyable( NonCopyable const& info ); NonCopyable& operator = ( NonCopyable const& ); #endif protected: NonCopyable() {} virtual ~NonCopyable(); }; class SafeBool { public: typedef void (SafeBool::*type)() const; static type makeSafe( bool value ) { return value ? &SafeBool::trueValue : 0; } private: void trueValue() const {} }; template void deleteAll( ContainerT& container ) { typename ContainerT::const_iterator it = container.begin(); typename ContainerT::const_iterator itEnd = container.end(); for(; it != itEnd; ++it ) delete *it; } template void deleteAllValues( AssociativeContainerT& container ) { typename AssociativeContainerT::const_iterator it = container.begin(); typename AssociativeContainerT::const_iterator itEnd = container.end(); for(; it != itEnd; ++it ) delete it->second; } bool startsWith( std::string const& s, std::string const& prefix ); bool startsWith( std::string const& s, char prefix ); bool endsWith( std::string const& s, std::string const& suffix ); bool endsWith( std::string const& s, char suffix ); bool contains( std::string const& s, std::string const& infix ); void toLowerInPlace( std::string& s ); std::string toLower( std::string const& s ); std::string trim( std::string const& str ); bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); struct pluralise { pluralise( std::size_t count, std::string const& label ); friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); std::size_t m_count; std::string m_label; }; struct SourceLineInfo { SourceLineInfo(); SourceLineInfo( char const* _file, std::size_t _line ); # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS SourceLineInfo(SourceLineInfo const& other) = default; SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo const& ) = default; SourceLineInfo& operator = ( SourceLineInfo && ) = default; # endif bool empty() const; bool operator == ( SourceLineInfo const& other ) const; bool operator < ( SourceLineInfo const& other ) const; char const* file; std::size_t line; }; std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); // This is just here to avoid compiler warnings with macro constants and boolean literals inline bool isTrue( bool value ){ return value; } inline bool alwaysTrue() { return true; } inline bool alwaysFalse() { return false; } void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); void seedRng( IConfig const& config ); unsigned int rngSeed(); // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as // >> stuff +StreamEndStop struct StreamEndStop { std::string operator+() { return std::string(); } }; template T const& operator + ( T const& value, StreamEndStop ) { return value; } } #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); namespace Catch { class NotImplementedException : public std::exception { public: NotImplementedException( SourceLineInfo const& lineInfo ); virtual ~NotImplementedException() CATCH_NOEXCEPT {} virtual const char* what() const CATCH_NOEXCEPT; private: std::string m_what; SourceLineInfo m_lineInfo; }; } // end namespace Catch /////////////////////////////////////////////////////////////////////////////// #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) // #included from: internal/catch_context.h #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED // #included from: catch_interfaces_generators.h #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED #include namespace Catch { struct IGeneratorInfo { virtual ~IGeneratorInfo(); virtual bool moveNext() = 0; virtual std::size_t getCurrentIndex() const = 0; }; struct IGeneratorsForTest { virtual ~IGeneratorsForTest(); virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; virtual bool moveNext() = 0; }; IGeneratorsForTest* createGeneratorsForTest(); } // end namespace Catch // #included from: catch_ptr.hpp #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif namespace Catch { // An intrusive reference counting smart pointer. // T must implement addRef() and release() methods // typically implementing the IShared interface template class Ptr { public: Ptr() : m_p( CATCH_NULL ){} Ptr( T* p ) : m_p( p ){ if( m_p ) m_p->addRef(); } Ptr( Ptr const& other ) : m_p( other.m_p ){ if( m_p ) m_p->addRef(); } ~Ptr(){ if( m_p ) m_p->release(); } void reset() { if( m_p ) m_p->release(); m_p = CATCH_NULL; } Ptr& operator = ( T* p ){ Ptr temp( p ); swap( temp ); return *this; } Ptr& operator = ( Ptr const& other ){ Ptr temp( other ); swap( temp ); return *this; } void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } T* get() const{ return m_p; } T& operator*() const { return *m_p; } T* operator->() const { return m_p; } bool operator !() const { return m_p == CATCH_NULL; } operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } private: T* m_p; }; struct IShared : NonCopyable { virtual ~IShared(); virtual void addRef() const = 0; virtual void release() const = 0; }; template struct SharedImpl : T { SharedImpl() : m_rc( 0 ){} virtual void addRef() const { ++m_rc; } virtual void release() const { if( --m_rc == 0 ) delete this; } mutable unsigned int m_rc; }; } // end namespace Catch #ifdef __clang__ #pragma clang diagnostic pop #endif namespace Catch { class TestCase; class Stream; struct IResultCapture; struct IRunner; struct IGeneratorsForTest; struct IConfig; struct IContext { virtual ~IContext(); virtual IResultCapture* getResultCapture() = 0; virtual IRunner* getRunner() = 0; virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; virtual bool advanceGeneratorsForCurrentTest() = 0; virtual Ptr getConfig() const = 0; }; struct IMutableContext : IContext { virtual ~IMutableContext(); virtual void setResultCapture( IResultCapture* resultCapture ) = 0; virtual void setRunner( IRunner* runner ) = 0; virtual void setConfig( Ptr const& config ) = 0; }; IContext& getCurrentContext(); IMutableContext& getCurrentMutableContext(); void cleanUpContext(); Stream createStream( std::string const& streamName ); } // #included from: internal/catch_test_registry.hpp #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED // #included from: catch_interfaces_testcase.h #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED #include namespace Catch { class TestSpec; struct ITestCase : IShared { virtual void invoke () const = 0; protected: virtual ~ITestCase(); }; class TestCase; struct IConfig; struct ITestCaseRegistry { virtual ~ITestCaseRegistry(); virtual std::vector const& getAllTests() const = 0; virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); std::vector const& getAllTestCasesSorted( IConfig const& config ); } namespace Catch { template class MethodTestCase : public SharedImpl { public: MethodTestCase( void (C::*method)() ) : m_method( method ) {} virtual void invoke() const { C obj; (obj.*m_method)(); } private: virtual ~MethodTestCase() {} void (C::*m_method)(); }; typedef void(*TestFunction)(); struct NameAndDesc { NameAndDesc( const char* _name = "", const char* _description= "" ) : name( _name ), description( _description ) {} const char* name; const char* description; }; void registerTestCase ( ITestCase* testCase, char const* className, NameAndDesc const& nameAndDesc, SourceLineInfo const& lineInfo ); struct AutoReg { AutoReg ( TestFunction function, SourceLineInfo const& lineInfo, NameAndDesc const& nameAndDesc ); template AutoReg ( void (C::*method)(), char const* className, NameAndDesc const& nameAndDesc, SourceLineInfo const& lineInfo ) { registerTestCase ( new MethodTestCase( method ), className, nameAndDesc, lineInfo ); } ~AutoReg(); private: AutoReg( AutoReg const& ); void operator= ( AutoReg const& ); }; void registerTestCaseFunction ( TestFunction function, SourceLineInfo const& lineInfo, NameAndDesc const& nameAndDesc ); } // end namespace Catch #ifdef CATCH_CONFIG_VARIADIC_MACROS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ static void TestName(); \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } /* NOLINT */ \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ static void TestName() #define INTERNAL_CATCH_TESTCASE( ... ) \ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } /* NOLINT */ \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ \ struct TestName : ClassName{ \ void test(); \ }; \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); /* NOLINT */ \ } \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ void TestName::test() #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); /* NOLINT */ \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS #else /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ static void TestName(); \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); } /* NOLINT */ \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ static void TestName() #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } /* NOLINT */ \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ \ struct TestCaseName : ClassName{ \ void test(); \ }; \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); /* NOLINT */ \ } \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ void TestCaseName::test() #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); /* NOLINT */ \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS #endif // #included from: internal/catch_capture.hpp #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED // #included from: catch_result_builder.h #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED // #included from: catch_result_type.h #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED namespace Catch { // ResultWas::OfType enum struct ResultWas { enum OfType { Unknown = -1, Ok = 0, Info = 1, Warning = 2, FailureBit = 0x10, ExpressionFailed = FailureBit | 1, ExplicitFailure = FailureBit | 2, Exception = 0x100 | FailureBit, ThrewException = Exception | 1, DidntThrowException = Exception | 2, FatalErrorCondition = 0x200 | FailureBit }; }; inline bool isOk( ResultWas::OfType resultType ) { return ( resultType & ResultWas::FailureBit ) == 0; } inline bool isJustInfo( int flags ) { return flags == ResultWas::Info; } // ResultDisposition::Flags enum struct ResultDisposition { enum Flags { Normal = 0x01, ContinueOnFailure = 0x02, // Failures fail test, but execution continues FalseTest = 0x04, // Prefix expression with ! SuppressFail = 0x08 // Failures are reported but do not fail the test }; }; inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { return static_cast( static_cast( lhs ) | static_cast( rhs ) ); } inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } } // end namespace Catch // #included from: catch_assertionresult.h #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED #include namespace Catch { struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; struct DecomposedExpression { virtual ~DecomposedExpression() {} virtual bool isBinaryExpression() const { return false; } virtual void reconstructExpression( std::string& dest ) const = 0; // Only simple binary comparisons can be decomposed. // If more complex check is required then wrap sub-expressions in parentheses. template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& ); private: DecomposedExpression& operator = (DecomposedExpression const&); }; struct AssertionInfo { AssertionInfo(); AssertionInfo( char const * _macroName, SourceLineInfo const& _lineInfo, char const * _capturedExpression, ResultDisposition::Flags _resultDisposition, char const * _secondArg = ""); char const * macroName; SourceLineInfo lineInfo; char const * capturedExpression; ResultDisposition::Flags resultDisposition; char const * secondArg; }; struct AssertionResultData { AssertionResultData() : decomposedExpression( CATCH_NULL ) , resultType( ResultWas::Unknown ) , negated( false ) , parenthesized( false ) {} void negate( bool parenthesize ) { negated = !negated; parenthesized = parenthesize; if( resultType == ResultWas::Ok ) resultType = ResultWas::ExpressionFailed; else if( resultType == ResultWas::ExpressionFailed ) resultType = ResultWas::Ok; } std::string const& reconstructExpression() const { if( decomposedExpression != CATCH_NULL ) { decomposedExpression->reconstructExpression( reconstructedExpression ); if( parenthesized ) { reconstructedExpression.insert( 0, 1, '(' ); reconstructedExpression.append( 1, ')' ); } if( negated ) { reconstructedExpression.insert( 0, 1, '!' ); } decomposedExpression = CATCH_NULL; } return reconstructedExpression; } mutable DecomposedExpression const* decomposedExpression; mutable std::string reconstructedExpression; std::string message; ResultWas::OfType resultType; bool negated; bool parenthesized; }; class AssertionResult { public: AssertionResult(); AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); ~AssertionResult(); # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS AssertionResult( AssertionResult const& ) = default; AssertionResult( AssertionResult && ) = default; AssertionResult& operator = ( AssertionResult const& ) = default; AssertionResult& operator = ( AssertionResult && ) = default; # endif bool isOk() const; bool succeeded() const; ResultWas::OfType getResultType() const; bool hasExpression() const; bool hasMessage() const; std::string getExpression() const; std::string getExpressionInMacro() const; bool hasExpandedExpression() const; std::string getExpandedExpression() const; std::string getMessage() const; SourceLineInfo getSourceInfo() const; std::string getTestMacroName() const; void discardDecomposedExpression() const; void expandDecomposedExpression() const; protected: AssertionInfo m_info; AssertionResultData m_resultData; }; } // end namespace Catch // #included from: catch_matchers.hpp #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED namespace Catch { namespace Matchers { namespace Impl { template struct MatchAllOf; template struct MatchAnyOf; template struct MatchNotOf; class MatcherUntypedBase { public: std::string toString() const { if( m_cachedToString.empty() ) m_cachedToString = describe(); return m_cachedToString; } protected: virtual ~MatcherUntypedBase(); virtual std::string describe() const = 0; mutable std::string m_cachedToString; private: MatcherUntypedBase& operator = ( MatcherUntypedBase const& ); }; template struct MatcherMethod { virtual bool match( ObjectT const& arg ) const = 0; }; template struct MatcherMethod { virtual bool match( PtrT* arg ) const = 0; }; template struct MatcherBase : MatcherUntypedBase, MatcherMethod { MatchAllOf operator && ( MatcherBase const& other ) const; MatchAnyOf operator || ( MatcherBase const& other ) const; MatchNotOf operator ! () const; }; template struct MatchAllOf : MatcherBase { virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { for( std::size_t i = 0; i < m_matchers.size(); ++i ) { if (!m_matchers[i]->match(arg)) return false; } return true; } virtual std::string describe() const CATCH_OVERRIDE { std::string description; description.reserve( 4 + m_matchers.size()*32 ); description += "( "; for( std::size_t i = 0; i < m_matchers.size(); ++i ) { if( i != 0 ) description += " and "; description += m_matchers[i]->toString(); } description += " )"; return description; } MatchAllOf& operator && ( MatcherBase const& other ) { m_matchers.push_back( &other ); return *this; } std::vector const*> m_matchers; }; template struct MatchAnyOf : MatcherBase { virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { for( std::size_t i = 0; i < m_matchers.size(); ++i ) { if (m_matchers[i]->match(arg)) return true; } return false; } virtual std::string describe() const CATCH_OVERRIDE { std::string description; description.reserve( 4 + m_matchers.size()*32 ); description += "( "; for( std::size_t i = 0; i < m_matchers.size(); ++i ) { if( i != 0 ) description += " or "; description += m_matchers[i]->toString(); } description += " )"; return description; } MatchAnyOf& operator || ( MatcherBase const& other ) { m_matchers.push_back( &other ); return *this; } std::vector const*> m_matchers; }; template struct MatchNotOf : MatcherBase { MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { return !m_underlyingMatcher.match( arg ); } virtual std::string describe() const CATCH_OVERRIDE { return "not " + m_underlyingMatcher.toString(); } MatcherBase const& m_underlyingMatcher; }; template MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const { return MatchAllOf() && *this && other; } template MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const { return MatchAnyOf() || *this || other; } template MatchNotOf MatcherBase::operator ! () const { return MatchNotOf( *this ); } } // namespace Impl // The following functions create the actual matcher objects. // This allows the types to be inferred // - deprecated: prefer ||, && and ! template Impl::MatchNotOf Not( Impl::MatcherBase const& underlyingMatcher ) { return Impl::MatchNotOf( underlyingMatcher ); } template Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { return Impl::MatchAllOf() && m1 && m2; } template Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { return Impl::MatchAllOf() && m1 && m2 && m3; } template Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { return Impl::MatchAnyOf() || m1 || m2; } template Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { return Impl::MatchAnyOf() || m1 || m2 || m3; } } // namespace Matchers using namespace Matchers; using Matchers::Impl::MatcherBase; } // namespace Catch namespace Catch { struct TestFailureException{}; template class ExpressionLhs; struct CopyableStream { CopyableStream() {} CopyableStream( CopyableStream const& other ) { oss << other.oss.str(); } CopyableStream& operator=( CopyableStream const& other ) { oss.str(std::string()); oss << other.oss.str(); return *this; } std::ostringstream oss; }; class ResultBuilder : public DecomposedExpression { public: ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, ResultDisposition::Flags resultDisposition, char const* secondArg = "" ); ~ResultBuilder(); template ExpressionLhs operator <= ( T const& operand ); ExpressionLhs operator <= ( bool value ); template ResultBuilder& operator << ( T const& value ) { stream().oss << value; return *this; } ResultBuilder& setResultType( ResultWas::OfType result ); ResultBuilder& setResultType( bool result ); void endExpression( DecomposedExpression const& expr ); virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE; AssertionResult build() const; AssertionResult build( DecomposedExpression const& expr ) const; void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); void captureResult( ResultWas::OfType resultType ); void captureExpression(); void captureExpectedException( std::string const& expectedMessage ); void captureExpectedException( Matchers::Impl::MatcherBase const& matcher ); void handleResult( AssertionResult const& result ); void react(); bool shouldDebugBreak() const; bool allowThrows() const; template void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ); void setExceptionGuard(); void unsetExceptionGuard(); private: AssertionInfo m_assertionInfo; AssertionResultData m_data; CopyableStream &stream() { if(!m_usedStream) { m_usedStream = true; m_stream().oss.str(""); } return m_stream(); } static CopyableStream &m_stream() { static CopyableStream s; return s; } bool m_shouldDebugBreak; bool m_shouldThrow; bool m_guardException; bool m_usedStream; }; } // namespace Catch // Include after due to circular dependency: // #included from: catch_expression_lhs.hpp #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED // #included from: catch_evaluate.hpp #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4389) // '==' : signed/unsigned mismatch #pragma warning(disable:4018) // more "signed/unsigned mismatch" #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) #endif #include namespace Catch { namespace Internal { enum Operator { IsEqualTo, IsNotEqualTo, IsLessThan, IsGreaterThan, IsLessThanOrEqualTo, IsGreaterThanOrEqualTo }; template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; template T& removeConst(T const &t) { return const_cast(t); } #ifdef CATCH_CONFIG_CPP11_NULLPTR inline std::nullptr_t removeConst(std::nullptr_t) { return nullptr; } #endif // So the compare overloads can be operator agnostic we convey the operator as a template // enum, which is used to specialise an Evaluator for doing the comparison. template struct Evaluator{}; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs) { return bool(removeConst(lhs) == removeConst(rhs) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool(removeConst(lhs) != removeConst(rhs) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool(removeConst(lhs) < removeConst(rhs) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool(removeConst(lhs) > removeConst(rhs) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool(removeConst(lhs) >= removeConst(rhs) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool(removeConst(lhs) <= removeConst(rhs) ); } }; // Special case for comparing a pointer to an int (deduced for p==0) template struct Evaluator { static bool evaluate( int lhs, T* rhs) { return reinterpret_cast( lhs ) == rhs; } }; template struct Evaluator { static bool evaluate( T* lhs, int rhs) { return lhs == reinterpret_cast( rhs ); } }; template struct Evaluator { static bool evaluate( int lhs, T* rhs) { return reinterpret_cast( lhs ) != rhs; } }; template struct Evaluator { static bool evaluate( T* lhs, int rhs) { return lhs != reinterpret_cast( rhs ); } }; template struct Evaluator { static bool evaluate( long lhs, T* rhs) { return reinterpret_cast( lhs ) == rhs; } }; template struct Evaluator { static bool evaluate( T* lhs, long rhs) { return lhs == reinterpret_cast( rhs ); } }; template struct Evaluator { static bool evaluate( long lhs, T* rhs) { return reinterpret_cast( lhs ) != rhs; } }; template struct Evaluator { static bool evaluate( T* lhs, long rhs) { return lhs != reinterpret_cast( rhs ); } }; } // end of namespace Internal } // end of namespace Catch #ifdef _MSC_VER #pragma warning(pop) #endif // #included from: catch_tostring.h #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED #include #include #include #include #include #ifdef __OBJC__ // #included from: catch_objc_arc.hpp #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED #import #ifdef __has_feature #define CATCH_ARC_ENABLED __has_feature(objc_arc) #else #define CATCH_ARC_ENABLED 0 #endif void arcSafeRelease( NSObject* obj ); id performOptionalSelector( id obj, SEL sel ); #if !CATCH_ARC_ENABLED inline void arcSafeRelease( NSObject* obj ) { [obj release]; } inline id performOptionalSelector( id obj, SEL sel ) { if( [obj respondsToSelector: sel] ) return [obj performSelector: sel]; return nil; } #define CATCH_UNSAFE_UNRETAINED #define CATCH_ARC_STRONG #else inline void arcSafeRelease( NSObject* ){} inline id performOptionalSelector( id obj, SEL sel ) { #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" #endif if( [obj respondsToSelector: sel] ) return [obj performSelector: sel]; #ifdef __clang__ #pragma clang diagnostic pop #endif return nil; } #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained #define CATCH_ARC_STRONG __strong #endif #endif #ifdef CATCH_CONFIG_CPP11_TUPLE #include #endif #ifdef CATCH_CONFIG_CPP11_IS_ENUM #include #endif namespace Catch { // Why we're here. template std::string toString( T const& value ); // Built in overloads std::string toString( std::string const& value ); std::string toString( std::wstring const& value ); std::string toString( const char* const value ); std::string toString( char* const value ); std::string toString( const wchar_t* const value ); std::string toString( wchar_t* const value ); std::string toString( int value ); std::string toString( unsigned long value ); std::string toString( unsigned int value ); std::string toString( const double value ); std::string toString( const float value ); std::string toString( bool value ); std::string toString( char value ); std::string toString( signed char value ); std::string toString( unsigned char value ); #ifdef CATCH_CONFIG_CPP11_LONG_LONG std::string toString( long long value ); std::string toString( unsigned long long value ); #endif #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ); #endif #ifdef __OBJC__ std::string toString( NSString const * const& nsstring ); std::string toString( NSString * CATCH_ARC_STRONG & nsstring ); std::string toString( NSObject* const& nsObject ); #endif namespace Detail { extern const std::string unprintableString; #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK) struct BorgType { template BorgType( T const& ); }; struct TrueType { char sizer[1]; }; struct FalseType { char sizer[2]; }; TrueType& testStreamable( std::ostream& ); FalseType testStreamable( FalseType ); FalseType operator<<( std::ostream const&, BorgType const& ); template struct IsStreamInsertable { static std::ostream &s; static T const&t; enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; }; #else template class IsStreamInsertable { template static auto test(int) -> decltype( std::declval() << std::declval(), std::true_type() ); template static auto test(...) -> std::false_type; public: static const bool value = decltype(test(0))::value; }; #endif #if defined(CATCH_CONFIG_CPP11_IS_ENUM) template::value > struct EnumStringMaker { static std::string convert( T const& ) { return unprintableString; } }; template struct EnumStringMaker { static std::string convert( T const& v ) { return ::Catch::toString( static_cast::type>(v) ); } }; #endif template struct StringMakerBase { #if defined(CATCH_CONFIG_CPP11_IS_ENUM) template static std::string convert( T const& v ) { return EnumStringMaker::convert( v ); } #else template static std::string convert( T const& ) { return unprintableString; } #endif }; template<> struct StringMakerBase { template static std::string convert( T const& _value ) { std::ostringstream oss; oss << _value; return oss.str(); } }; std::string rawMemoryToString( const void *object, std::size_t size ); template std::string rawMemoryToString( const T& object ) { return rawMemoryToString( &object, sizeof(object) ); } } // end namespace Detail template struct StringMaker : Detail::StringMakerBase::value> {}; template struct StringMaker { template static std::string convert( U* p ) { if( !p ) return "NULL"; else return Detail::rawMemoryToString( p ); } }; template struct StringMaker { static std::string convert( R C::* p ) { if( !p ) return "NULL"; else return Detail::rawMemoryToString( p ); } }; namespace Detail { template std::string rangeToString( InputIterator first, InputIterator last ); } //template //struct StringMaker > { // static std::string convert( std::vector const& v ) { // return Detail::rangeToString( v.begin(), v.end() ); // } //}; template std::string toString( std::vector const& v ) { return Detail::rangeToString( v.begin(), v.end() ); } #ifdef CATCH_CONFIG_CPP11_TUPLE // toString for tuples namespace TupleDetail { template< typename Tuple, std::size_t N = 0, bool = (N < std::tuple_size::value) > struct ElementPrinter { static void print( const Tuple& tuple, std::ostream& os ) { os << ( N ? ", " : " " ) << Catch::toString(std::get(tuple)); ElementPrinter::print(tuple,os); } }; template< typename Tuple, std::size_t N > struct ElementPrinter { static void print( const Tuple&, std::ostream& ) {} }; } template struct StringMaker> { static std::string convert( const std::tuple& tuple ) { std::ostringstream os; os << '{'; TupleDetail::ElementPrinter>::print( tuple, os ); os << " }"; return os.str(); } }; #endif // CATCH_CONFIG_CPP11_TUPLE namespace Detail { template std::string makeString( T const& value ) { return StringMaker::convert( value ); } } // end namespace Detail /// \brief converts any type to a string /// /// The default template forwards on to ostringstream - except when an /// ostringstream overload does not exist - in which case it attempts to detect /// that and writes {?}. /// Overload (not specialise) this template for custom typs that you don't want /// to provide an ostream overload for. template std::string toString( T const& value ) { return StringMaker::convert( value ); } namespace Detail { template std::string rangeToString( InputIterator first, InputIterator last ) { std::ostringstream oss; oss << "{ "; if( first != last ) { oss << Catch::toString( *first ); for( ++first ; first != last ; ++first ) oss << ", " << Catch::toString( *first ); } oss << " }"; return oss.str(); } } } // end namespace Catch namespace Catch { template class BinaryExpression; template class MatchExpression; // Wraps the LHS of an expression and overloads comparison operators // for also capturing those and RHS (if any) template class ExpressionLhs : public DecomposedExpression { public: ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {} ExpressionLhs& operator = ( const ExpressionLhs& ); template BinaryExpression operator == ( RhsT const& rhs ) { return captureExpression( rhs ); } template BinaryExpression operator != ( RhsT const& rhs ) { return captureExpression( rhs ); } template BinaryExpression operator < ( RhsT const& rhs ) { return captureExpression( rhs ); } template BinaryExpression operator > ( RhsT const& rhs ) { return captureExpression( rhs ); } template BinaryExpression operator <= ( RhsT const& rhs ) { return captureExpression( rhs ); } template BinaryExpression operator >= ( RhsT const& rhs ) { return captureExpression( rhs ); } BinaryExpression operator == ( bool rhs ) { return captureExpression( rhs ); } BinaryExpression operator != ( bool rhs ) { return captureExpression( rhs ); } void endExpression() { m_truthy = m_lhs ? true : false; m_rb .setResultType( m_truthy ) .endExpression( *this ); } virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { dest = Catch::toString( m_lhs ); } private: template BinaryExpression captureExpression( RhsT& rhs ) const { return BinaryExpression( m_rb, m_lhs, rhs ); } template BinaryExpression captureExpression( bool rhs ) const { return BinaryExpression( m_rb, m_lhs, rhs ); } private: ResultBuilder& m_rb; T m_lhs; bool m_truthy; }; template class BinaryExpression : public DecomposedExpression { public: BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs ) : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {} BinaryExpression& operator = ( BinaryExpression& ); void endExpression() const { m_rb .setResultType( Internal::Evaluator::evaluate( m_lhs, m_rhs ) ) .endExpression( *this ); } virtual bool isBinaryExpression() const CATCH_OVERRIDE { return true; } virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { std::string lhs = Catch::toString( m_lhs ); std::string rhs = Catch::toString( m_rhs ); char delim = lhs.size() + rhs.size() < 40 && lhs.find('\n') == std::string::npos && rhs.find('\n') == std::string::npos ? ' ' : '\n'; dest.reserve( 7 + lhs.size() + rhs.size() ); // 2 for spaces around operator // 2 for operator // 2 for parentheses (conditionally added later) // 1 for negation (conditionally added later) dest = lhs; dest += delim; dest += Internal::OperatorTraits::getName(); dest += delim; dest += rhs; } private: ResultBuilder& m_rb; LhsT m_lhs; RhsT m_rhs; }; template class MatchExpression : public DecomposedExpression { public: MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString ) : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {} virtual bool isBinaryExpression() const CATCH_OVERRIDE { return true; } virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { std::string matcherAsString = m_matcher.toString(); dest = Catch::toString( m_arg ); dest += ' '; if( matcherAsString == Detail::unprintableString ) dest += m_matcherString; else dest += matcherAsString; } private: ArgT m_arg; MatcherT m_matcher; char const* m_matcherString; }; } // end namespace Catch namespace Catch { template ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { return ExpressionLhs( *this, operand ); } inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { return ExpressionLhs( *this, value ); } template void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ) { MatchExpression expr( arg, matcher, matcherString ); setResultType( matcher.match( arg ) ); endExpression( expr ); } } // namespace Catch // #included from: catch_message.h #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED #include namespace Catch { struct MessageInfo { MessageInfo( std::string const& _macroName, SourceLineInfo const& _lineInfo, ResultWas::OfType _type ); std::string macroName; SourceLineInfo lineInfo; ResultWas::OfType type; std::string message; unsigned int sequence; bool operator == ( MessageInfo const& other ) const { return sequence == other.sequence; } bool operator < ( MessageInfo const& other ) const { return sequence < other.sequence; } private: static unsigned int globalCount; }; struct MessageBuilder { MessageBuilder( std::string const& macroName, SourceLineInfo const& lineInfo, ResultWas::OfType type ) : m_info( macroName, lineInfo, type ) {} template MessageBuilder& operator << ( T const& value ) { m_stream << value; return *this; } MessageInfo m_info; std::ostringstream m_stream; }; class ScopedMessage { public: ScopedMessage( MessageBuilder const& builder ); ScopedMessage( ScopedMessage const& other ); ~ScopedMessage(); MessageInfo m_info; }; } // end namespace Catch // #included from: catch_interfaces_capture.h #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED #include namespace Catch { class TestCase; class AssertionResult; struct AssertionInfo; struct SectionInfo; struct SectionEndInfo; struct MessageInfo; class ScopedMessageBuilder; struct Counts; struct IResultCapture { virtual ~IResultCapture(); virtual void assertionEnded( AssertionResult const& result ) = 0; virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) = 0; virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0; virtual std::string getCurrentTestName() const = 0; virtual const AssertionResult* getLastResult() const = 0; virtual void exceptionEarlyReported() = 0; virtual void handleFatalErrorCondition( std::string const& message ) = 0; virtual bool lastAssertionPassed() = 0; virtual void assertionPassed() = 0; virtual void assertionRun() = 0; }; IResultCapture& getResultCapture(); } // #included from: catch_debugger.h #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED // #included from: catch_platform.h #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) # define CATCH_PLATFORM_MAC #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) # define CATCH_PLATFORM_IPHONE #elif defined(linux) || defined(__linux) || defined(__linux__) # define CATCH_PLATFORM_LINUX #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) # define CATCH_PLATFORM_WINDOWS # if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) # define CATCH_DEFINES_NOMINMAX # endif # if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) # define CATCH_DEFINES_WIN32_LEAN_AND_MEAN # endif #endif #include namespace Catch{ bool isDebuggerActive(); void writeToDebugConsole( std::string const& text ); } #ifdef CATCH_PLATFORM_MAC // The following code snippet based on: // http://cocoawithlove.com/2008/03/break-into-debugger.html #if defined(__ppc64__) || defined(__ppc__) #define CATCH_TRAP() \ __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ : : : "memory","r0","r3","r4" ) /* NOLINT */ #else #define CATCH_TRAP() __asm__("int $3\n" : : /* NOLINT */ ) #endif #elif defined(CATCH_PLATFORM_LINUX) // If we can use inline assembler, do it because this allows us to break // directly at the location of the failing check instead of breaking inside // raise() called from it, i.e. one stack frame below. #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */ #else // Fall back to the generic way. #include #define CATCH_TRAP() raise(SIGTRAP) #endif #elif defined(_MSC_VER) #define CATCH_TRAP() __debugbreak() #elif defined(__MINGW32__) extern "C" __declspec(dllimport) void __stdcall DebugBreak(); #define CATCH_TRAP() DebugBreak() #endif #ifdef CATCH_TRAP #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } #else #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); #endif // #included from: catch_interfaces_runner.h #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED namespace Catch { class TestCase; struct IRunner { virtual ~IRunner(); virtual bool aborting() const = 0; }; } #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) # define CATCH_INTERNAL_STRINGIFY(expr) #expr #else # define CATCH_INTERNAL_STRINGIFY(expr) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" #endif #if defined(CATCH_CONFIG_FAST_COMPILE) /////////////////////////////////////////////////////////////////////////////// // We can speedup compilation significantly by breaking into debugger lower in // the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER // macro in each assertion #define INTERNAL_CATCH_REACT( resultBuilder ) \ resultBuilder.react(); /////////////////////////////////////////////////////////////////////////////// // Another way to speed-up compilation is to omit local try-catch for REQUIRE* // macros. // This can potentially cause false negative, if the test code catches // the exception before it propagates back up to the runner. #define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \ __catchResult.setExceptionGuard(); \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ ( __catchResult <= expr ).endExpression(); \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ __catchResult.unsetExceptionGuard(); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. #define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ __catchResult.setExceptionGuard(); \ __catchResult.captureMatch( arg, matcher, CATCH_INTERNAL_STRINGIFY(matcher) ); \ __catchResult.unsetExceptionGuard(); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) #else /////////////////////////////////////////////////////////////////////////////// // In the event of a failure works out if the debugger needs to be invoked // and/or an exception thrown and takes appropriate action. // This needs to be done as a macro so the debugger will stop in the user // source code rather than in Catch library code #define INTERNAL_CATCH_REACT( resultBuilder ) \ if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ resultBuilder.react(); #endif /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \ try { \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ ( __catchResult <= expr ).endExpression(); \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ } \ catch( ... ) { \ __catchResult.useActiveException( resultDisposition ); \ } \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \ INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ if( Catch::getResultCapture().lastAssertionPassed() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \ INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ if( !Catch::getResultCapture().lastAssertionPassed() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \ try { \ static_cast(expr); \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ __catchResult.useActiveException( resultDisposition ); \ } \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition, CATCH_INTERNAL_STRINGIFY(matcher) ); \ if( __catchResult.allowThrows() ) \ try { \ static_cast(expr); \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ __catchResult.captureExpectedException( matcher ); \ } \ else \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ if( __catchResult.allowThrows() ) \ try { \ static_cast(expr); \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ catch( exceptionType ) { \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ __catchResult.useActiveException( resultDisposition ); \ } \ else \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// #ifdef CATCH_CONFIG_VARIADIC_MACROS #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ __catchResult.captureResult( messageType ); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) #else #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, log ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ __catchResult << log + ::Catch::StreamEndStop(); \ __catchResult.captureResult( messageType ); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) #endif /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_INFO( macroName, log ) \ Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ try { \ __catchResult.captureMatch( arg, matcher, CATCH_INTERNAL_STRINGIFY(matcher) ); \ } catch( ... ) { \ __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ } \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) // #included from: internal/catch_section.h #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED // #included from: catch_section_info.h #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED // #included from: catch_totals.hpp #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED #include namespace Catch { struct Counts { Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} Counts operator - ( Counts const& other ) const { Counts diff; diff.passed = passed - other.passed; diff.failed = failed - other.failed; diff.failedButOk = failedButOk - other.failedButOk; return diff; } Counts& operator += ( Counts const& other ) { passed += other.passed; failed += other.failed; failedButOk += other.failedButOk; return *this; } std::size_t total() const { return passed + failed + failedButOk; } bool allPassed() const { return failed == 0 && failedButOk == 0; } bool allOk() const { return failed == 0; } std::size_t passed; std::size_t failed; std::size_t failedButOk; }; struct Totals { Totals operator - ( Totals const& other ) const { Totals diff; diff.assertions = assertions - other.assertions; diff.testCases = testCases - other.testCases; return diff; } Totals delta( Totals const& prevTotals ) const { Totals diff = *this - prevTotals; if( diff.assertions.failed > 0 ) ++diff.testCases.failed; else if( diff.assertions.failedButOk > 0 ) ++diff.testCases.failedButOk; else ++diff.testCases.passed; return diff; } Totals& operator += ( Totals const& other ) { assertions += other.assertions; testCases += other.testCases; return *this; } Counts assertions; Counts testCases; }; } #include namespace Catch { struct SectionInfo { SectionInfo ( SourceLineInfo const& _lineInfo, std::string const& _name, std::string const& _description = std::string() ); std::string name; std::string description; SourceLineInfo lineInfo; }; struct SectionEndInfo { SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) {} SectionInfo sectionInfo; Counts prevAssertions; double durationInSeconds; }; } // end namespace Catch // #included from: catch_timer.h #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED #ifdef _MSC_VER namespace Catch { typedef unsigned long long UInt64; } #else #include namespace Catch { typedef uint64_t UInt64; } #endif namespace Catch { class Timer { public: Timer() : m_ticks( 0 ) {} void start(); unsigned int getElapsedMicroseconds() const; unsigned int getElapsedMilliseconds() const; double getElapsedSeconds() const; private: UInt64 m_ticks; }; } // namespace Catch #include namespace Catch { class Section : NonCopyable { public: Section( SectionInfo const& info ); ~Section(); // This indicates whether the section should be executed or not operator bool() const; private: SectionInfo m_info; std::string m_name; Counts m_assertions; bool m_sectionIncluded; Timer m_timer; }; } // end namespace Catch #ifdef CATCH_CONFIG_VARIADIC_MACROS #define INTERNAL_CATCH_SECTION( ... ) \ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) #else #define INTERNAL_CATCH_SECTION( name, desc ) \ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) #endif // #included from: internal/catch_generators.hpp #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED #include #include #include namespace Catch { template struct IGenerator { virtual ~IGenerator() {} virtual T getValue( std::size_t index ) const = 0; virtual std::size_t size () const = 0; }; template class BetweenGenerator : public IGenerator { public: BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} virtual T getValue( std::size_t index ) const { return m_from+static_cast( index ); } virtual std::size_t size() const { return static_cast( 1+m_to-m_from ); } private: T m_from; T m_to; }; template class ValuesGenerator : public IGenerator { public: ValuesGenerator(){} void add( T value ) { m_values.push_back( value ); } virtual T getValue( std::size_t index ) const { return m_values[index]; } virtual std::size_t size() const { return m_values.size(); } private: std::vector m_values; }; template class CompositeGenerator { public: CompositeGenerator() : m_totalSize( 0 ) {} // *** Move semantics, similar to auto_ptr *** CompositeGenerator( CompositeGenerator& other ) : m_fileInfo( other.m_fileInfo ), m_totalSize( 0 ) { move( other ); } CompositeGenerator& setFileInfo( const char* fileInfo ) { m_fileInfo = fileInfo; return *this; } ~CompositeGenerator() { deleteAll( m_composed ); } operator T () const { size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); typename std::vector*>::const_iterator it = m_composed.begin(); typename std::vector*>::const_iterator itEnd = m_composed.end(); for( size_t index = 0; it != itEnd; ++it ) { const IGenerator* generator = *it; if( overallIndex >= index && overallIndex < index + generator->size() ) { return generator->getValue( overallIndex-index ); } index += generator->size(); } CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so } void add( const IGenerator* generator ) { m_totalSize += generator->size(); m_composed.push_back( generator ); } CompositeGenerator& then( CompositeGenerator& other ) { move( other ); return *this; } CompositeGenerator& then( T value ) { ValuesGenerator* valuesGen = new ValuesGenerator(); valuesGen->add( value ); add( valuesGen ); return *this; } private: void move( CompositeGenerator& other ) { m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() ); m_totalSize += other.m_totalSize; other.m_composed.clear(); } std::vector*> m_composed; std::string m_fileInfo; size_t m_totalSize; }; namespace Generators { template CompositeGenerator between( T from, T to ) { CompositeGenerator generators; generators.add( new BetweenGenerator( from, to ) ); return generators; } template CompositeGenerator values( T val1, T val2 ) { CompositeGenerator generators; ValuesGenerator* valuesGen = new ValuesGenerator(); valuesGen->add( val1 ); valuesGen->add( val2 ); generators.add( valuesGen ); return generators; } template CompositeGenerator values( T val1, T val2, T val3 ){ CompositeGenerator generators; ValuesGenerator* valuesGen = new ValuesGenerator(); valuesGen->add( val1 ); valuesGen->add( val2 ); valuesGen->add( val3 ); generators.add( valuesGen ); return generators; } template CompositeGenerator values( T val1, T val2, T val3, T val4 ) { CompositeGenerator generators; ValuesGenerator* valuesGen = new ValuesGenerator(); valuesGen->add( val1 ); valuesGen->add( val2 ); valuesGen->add( val3 ); valuesGen->add( val4 ); generators.add( valuesGen ); return generators; } } // end namespace Generators using namespace Generators; } // end namespace Catch #define INTERNAL_CATCH_LINESTR2( line ) #line #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) // #included from: internal/catch_interfaces_exception.h #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED #include #include // #included from: catch_interfaces_registry_hub.h #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED #include namespace Catch { class TestCase; struct ITestCaseRegistry; struct IExceptionTranslatorRegistry; struct IExceptionTranslator; struct IReporterRegistry; struct IReporterFactory; struct ITagAliasRegistry; struct IRegistryHub { virtual ~IRegistryHub(); virtual IReporterRegistry const& getReporterRegistry() const = 0; virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; }; struct IMutableRegistryHub { virtual ~IMutableRegistryHub(); virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; virtual void registerListener( Ptr const& factory ) = 0; virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; }; IRegistryHub& getRegistryHub(); IMutableRegistryHub& getMutableRegistryHub(); void cleanUp(); std::string translateActiveException(); } namespace Catch { typedef std::string(*exceptionTranslateFunction)(); struct IExceptionTranslator; typedef std::vector ExceptionTranslators; struct IExceptionTranslator { virtual ~IExceptionTranslator(); virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; }; struct IExceptionTranslatorRegistry { virtual ~IExceptionTranslatorRegistry(); virtual std::string translateActiveException() const = 0; }; class ExceptionTranslatorRegistrar { template class ExceptionTranslator : public IExceptionTranslator { public: ExceptionTranslator( std::string(*translateFunction)( T& ) ) : m_translateFunction( translateFunction ) {} virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { try { if( it == itEnd ) throw; else return (*it)->translate( it+1, itEnd ); } catch( T& ex ) { return m_translateFunction( ex ); } } protected: std::string(*m_translateFunction)( T& ); }; public: template ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { getMutableRegistryHub().registerTranslator ( new ExceptionTranslator( translateFunction ) ); } }; } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ static std::string translatorName( signature ); \ namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ static std::string translatorName( signature ) #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) // #included from: internal/catch_approx.hpp #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED #include #include #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) #include #endif namespace Catch { namespace Detail { class Approx { public: explicit Approx ( double value ) : m_epsilon( std::numeric_limits::epsilon()*100 ), m_margin( 0.0 ), m_scale( 1.0 ), m_value( value ) {} static Approx custom() { return Approx( 0 ); } #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) template ::value>::type> Approx operator()( T value ) { Approx approx( static_cast(value) ); approx.epsilon( m_epsilon ); approx.margin( m_margin ); approx.scale( m_scale ); return approx; } template ::value>::type> explicit Approx( T value ): Approx(static_cast(value)) {} template ::value>::type> friend bool operator == ( const T& lhs, Approx const& rhs ) { // Thanks to Richard Harris for his help refining this formula auto lhs_v = double(lhs); bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); if (relativeOK) { return true; } return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin; } template ::value>::type> friend bool operator == ( Approx const& lhs, const T& rhs ) { return operator==( rhs, lhs ); } template ::value>::type> friend bool operator != ( T lhs, Approx const& rhs ) { return !operator==( lhs, rhs ); } template ::value>::type> friend bool operator != ( Approx const& lhs, T rhs ) { return !operator==( rhs, lhs ); } template ::value>::type> friend bool operator <= ( T lhs, Approx const& rhs ) { return double(lhs) < rhs.m_value || lhs == rhs; } template ::value>::type> friend bool operator <= ( Approx const& lhs, T rhs ) { return lhs.m_value < double(rhs) || lhs == rhs; } template ::value>::type> friend bool operator >= ( T lhs, Approx const& rhs ) { return double(lhs) > rhs.m_value || lhs == rhs; } template ::value>::type> friend bool operator >= ( Approx const& lhs, T rhs ) { return lhs.m_value > double(rhs) || lhs == rhs; } template ::value>::type> Approx& epsilon( T newEpsilon ) { m_epsilon = double(newEpsilon); return *this; } template ::value>::type> Approx& margin( T newMargin ) { m_margin = double(newMargin); return *this; } template ::value>::type> Approx& scale( T newScale ) { m_scale = double(newScale); return *this; } #else Approx operator()( double value ) { Approx approx( value ); approx.epsilon( m_epsilon ); approx.margin( m_margin ); approx.scale( m_scale ); return approx; } friend bool operator == ( double lhs, Approx const& rhs ) { // Thanks to Richard Harris for his help refining this formula bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) ); if (relativeOK) { return true; } return std::fabs(lhs - rhs.m_value) < rhs.m_margin; } friend bool operator == ( Approx const& lhs, double rhs ) { return operator==( rhs, lhs ); } friend bool operator != ( double lhs, Approx const& rhs ) { return !operator==( lhs, rhs ); } friend bool operator != ( Approx const& lhs, double rhs ) { return !operator==( rhs, lhs ); } friend bool operator <= ( double lhs, Approx const& rhs ) { return lhs < rhs.m_value || lhs == rhs; } friend bool operator <= ( Approx const& lhs, double rhs ) { return lhs.m_value < rhs || lhs == rhs; } friend bool operator >= ( double lhs, Approx const& rhs ) { return lhs > rhs.m_value || lhs == rhs; } friend bool operator >= ( Approx const& lhs, double rhs ) { return lhs.m_value > rhs || lhs == rhs; } Approx& epsilon( double newEpsilon ) { m_epsilon = newEpsilon; return *this; } Approx& margin( double newMargin ) { m_margin = newMargin; return *this; } Approx& scale( double newScale ) { m_scale = newScale; return *this; } #endif std::string toString() const { std::ostringstream oss; oss << "Approx( " << Catch::toString( m_value ) << " )"; return oss.str(); } private: double m_epsilon; double m_margin; double m_scale; double m_value; }; } template<> inline std::string toString( Detail::Approx const& value ) { return value.toString(); } } // end namespace Catch // #included from: internal/catch_matchers_string.h #define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED namespace Catch { namespace Matchers { namespace StdString { struct CasedString { CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); std::string adjustString( std::string const& str ) const; std::string caseSensitivitySuffix() const; CaseSensitive::Choice m_caseSensitivity; std::string m_str; }; struct StringMatcherBase : MatcherBase { StringMatcherBase( std::string const& operation, CasedString const& comparator ); virtual std::string describe() const CATCH_OVERRIDE; CasedString m_comparator; std::string m_operation; }; struct EqualsMatcher : StringMatcherBase { EqualsMatcher( CasedString const& comparator ); virtual bool match( std::string const& source ) const CATCH_OVERRIDE; }; struct ContainsMatcher : StringMatcherBase { ContainsMatcher( CasedString const& comparator ); virtual bool match( std::string const& source ) const CATCH_OVERRIDE; }; struct StartsWithMatcher : StringMatcherBase { StartsWithMatcher( CasedString const& comparator ); virtual bool match( std::string const& source ) const CATCH_OVERRIDE; }; struct EndsWithMatcher : StringMatcherBase { EndsWithMatcher( CasedString const& comparator ); virtual bool match( std::string const& source ) const CATCH_OVERRIDE; }; } // namespace StdString // The following functions create the actual matcher objects. // This allows the types to be inferred StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); } // namespace Matchers } // namespace Catch // #included from: internal/catch_matchers_vector.h #define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED namespace Catch { namespace Matchers { namespace Vector { template struct ContainsElementMatcher : MatcherBase, T> { ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} bool match(std::vector const &v) const CATCH_OVERRIDE { return std::find(v.begin(), v.end(), m_comparator) != v.end(); } virtual std::string describe() const CATCH_OVERRIDE { return "Contains: " + Catch::toString( m_comparator ); } T const& m_comparator; }; template struct ContainsMatcher : MatcherBase, std::vector > { ContainsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} bool match(std::vector const &v) const CATCH_OVERRIDE { // !TBD: see note in EqualsMatcher if (m_comparator.size() > v.size()) return false; for (size_t i = 0; i < m_comparator.size(); ++i) if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end()) return false; return true; } virtual std::string describe() const CATCH_OVERRIDE { return "Contains: " + Catch::toString( m_comparator ); } std::vector const& m_comparator; }; template struct EqualsMatcher : MatcherBase, std::vector > { EqualsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} bool match(std::vector const &v) const CATCH_OVERRIDE { // !TBD: This currently works if all elements can be compared using != // - a more general approach would be via a compare template that defaults // to using !=. but could be specialised for, e.g. std::vector etc // - then just call that directly if (m_comparator.size() != v.size()) return false; for (size_t i = 0; i < v.size(); ++i) if (m_comparator[i] != v[i]) return false; return true; } virtual std::string describe() const CATCH_OVERRIDE { return "Equals: " + Catch::toString( m_comparator ); } std::vector const& m_comparator; }; } // namespace Vector // The following functions create the actual matcher objects. // This allows the types to be inferred template Vector::ContainsMatcher Contains( std::vector const& comparator ) { return Vector::ContainsMatcher( comparator ); } template Vector::ContainsElementMatcher VectorContains( T const& comparator ) { return Vector::ContainsElementMatcher( comparator ); } template Vector::EqualsMatcher Equals( std::vector const& comparator ) { return Vector::EqualsMatcher( comparator ); } } // namespace Matchers } // namespace Catch // #included from: internal/catch_interfaces_tag_alias_registry.h #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED // #included from: catch_tag_alias.h #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED #include namespace Catch { struct TagAlias { TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} std::string tag; SourceLineInfo lineInfo; }; struct RegistrarForTagAliases { RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); }; } // end namespace Catch #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } // #included from: catch_option.hpp #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED namespace Catch { // An optional type template class Option { public: Option() : nullableValue( CATCH_NULL ) {} Option( T const& _value ) : nullableValue( new( storage ) T( _value ) ) {} Option( Option const& _other ) : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) {} ~Option() { reset(); } Option& operator= ( Option const& _other ) { if( &_other != this ) { reset(); if( _other ) nullableValue = new( storage ) T( *_other ); } return *this; } Option& operator = ( T const& _value ) { reset(); nullableValue = new( storage ) T( _value ); return *this; } void reset() { if( nullableValue ) nullableValue->~T(); nullableValue = CATCH_NULL; } T& operator*() { return *nullableValue; } T const& operator*() const { return *nullableValue; } T* operator->() { return nullableValue; } const T* operator->() const { return nullableValue; } T valueOr( T const& defaultValue ) const { return nullableValue ? *nullableValue : defaultValue; } bool some() const { return nullableValue != CATCH_NULL; } bool none() const { return nullableValue == CATCH_NULL; } bool operator !() const { return nullableValue == CATCH_NULL; } operator SafeBool::type() const { return SafeBool::makeSafe( some() ); } private: T *nullableValue; union { char storage[sizeof(T)]; // These are here to force alignment for the storage long double dummy1; void (*dummy2)(); long double dummy3; #ifdef CATCH_CONFIG_CPP11_LONG_LONG long long dummy4; #endif }; }; } // end namespace Catch namespace Catch { struct ITagAliasRegistry { virtual ~ITagAliasRegistry(); virtual Option find( std::string const& alias ) const = 0; virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; static ITagAliasRegistry const& get(); }; } // end namespace Catch // These files are included here so the single_include script doesn't put them // in the conditionally compiled sections // #included from: internal/catch_test_case_info.h #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED #include #include #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif namespace Catch { struct ITestCase; struct TestCaseInfo { enum SpecialProperties{ None = 0, IsHidden = 1 << 1, ShouldFail = 1 << 2, MayFail = 1 << 3, Throws = 1 << 4, NonPortable = 1 << 5 }; TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, std::set const& _tags, SourceLineInfo const& _lineInfo ); TestCaseInfo( TestCaseInfo const& other ); friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); bool isHidden() const; bool throws() const; bool okToFail() const; bool expectedToFail() const; std::string name; std::string className; std::string description; std::set tags; std::set lcaseTags; std::string tagsAsString; SourceLineInfo lineInfo; SpecialProperties properties; }; class TestCase : public TestCaseInfo { public: TestCase( ITestCase* testCase, TestCaseInfo const& info ); TestCase( TestCase const& other ); TestCase withName( std::string const& _newName ) const; void invoke() const; TestCaseInfo const& getTestCaseInfo() const; void swap( TestCase& other ); bool operator == ( TestCase const& other ) const; bool operator < ( TestCase const& other ) const; TestCase& operator = ( TestCase const& other ); private: Ptr test; }; TestCase makeTestCase( ITestCase* testCase, std::string const& className, std::string const& name, std::string const& description, SourceLineInfo const& lineInfo ); } #ifdef __clang__ #pragma clang diagnostic pop #endif #ifdef __OBJC__ // #included from: internal/catch_objc.hpp #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED #import #include // NB. Any general catch headers included here must be included // in catch.hpp first to make sure they are included by the single // header for non obj-usage /////////////////////////////////////////////////////////////////////////////// // This protocol is really only here for (self) documenting purposes, since // all its methods are optional. @protocol OcFixture @optional -(void) setUp; -(void) tearDown; @end namespace Catch { class OcMethod : public SharedImpl { public: OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} virtual void invoke() const { id obj = [[m_cls alloc] init]; performOptionalSelector( obj, @selector(setUp) ); performOptionalSelector( obj, m_sel ); performOptionalSelector( obj, @selector(tearDown) ); arcSafeRelease( obj ); } private: virtual ~OcMethod() {} Class m_cls; SEL m_sel; }; namespace Detail{ inline std::string getAnnotation( Class cls, std::string const& annotationName, std::string const& testCaseName ) { NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; SEL sel = NSSelectorFromString( selStr ); arcSafeRelease( selStr ); id value = performOptionalSelector( cls, sel ); if( value ) return [(NSString*)value UTF8String]; return ""; } } inline size_t registerTestMethods() { size_t noTestMethods = 0; int noClasses = objc_getClassList( CATCH_NULL, 0 ); Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); objc_getClassList( classes, noClasses ); for( int c = 0; c < noClasses; c++ ) { Class cls = classes[c]; { u_int count; Method* methods = class_copyMethodList( cls, &count ); for( u_int m = 0; m < count ; m++ ) { SEL selector = method_getName(methods[m]); std::string methodName = sel_getName(selector); if( startsWith( methodName, "Catch_TestCase_" ) ) { std::string testCaseName = methodName.substr( 15 ); std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); const char* className = class_getName( cls ); getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); noTestMethods++; } } free(methods); } } return noTestMethods; } namespace Matchers { namespace Impl { namespace NSStringMatchers { struct StringHolder : MatcherBase{ StringHolder( NSString* substr ) : m_substr( [substr copy] ){} StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} StringHolder() { arcSafeRelease( m_substr ); } virtual bool match( NSString* arg ) const CATCH_OVERRIDE { return false; } NSString* m_substr; }; struct Equals : StringHolder { Equals( NSString* substr ) : StringHolder( substr ){} virtual bool match( NSString* str ) const CATCH_OVERRIDE { return (str != nil || m_substr == nil ) && [str isEqualToString:m_substr]; } virtual std::string describe() const CATCH_OVERRIDE { return "equals string: " + Catch::toString( m_substr ); } }; struct Contains : StringHolder { Contains( NSString* substr ) : StringHolder( substr ){} virtual bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location != NSNotFound; } virtual std::string describe() const CATCH_OVERRIDE { return "contains string: " + Catch::toString( m_substr ); } }; struct StartsWith : StringHolder { StartsWith( NSString* substr ) : StringHolder( substr ){} virtual bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == 0; } virtual std::string describe() const CATCH_OVERRIDE { return "starts with: " + Catch::toString( m_substr ); } }; struct EndsWith : StringHolder { EndsWith( NSString* substr ) : StringHolder( substr ){} virtual bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == [str length] - [m_substr length]; } virtual std::string describe() const CATCH_OVERRIDE { return "ends with: " + Catch::toString( m_substr ); } }; } // namespace NSStringMatchers } // namespace Impl inline Impl::NSStringMatchers::Equals Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } inline Impl::NSStringMatchers::Contains Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } inline Impl::NSStringMatchers::StartsWith StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } inline Impl::NSStringMatchers::EndsWith EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } } // namespace Matchers using namespace Matchers; } // namespace Catch /////////////////////////////////////////////////////////////////////////////// #define OC_TEST_CASE( name, desc )\ +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ {\ return @ name; \ }\ +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ { \ return @ desc; \ } \ -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) #endif #ifdef CATCH_IMPL // !TBD: Move the leak detector code into a separate header #ifdef CATCH_CONFIG_WINDOWS_CRTDBG #include class LeakDetector { public: LeakDetector() { int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); flag |= _CRTDBG_LEAK_CHECK_DF; flag |= _CRTDBG_ALLOC_MEM_DF; _CrtSetDbgFlag(flag); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); // Change this to leaking allocation's number to break there _CrtSetBreakAlloc(-1); } }; #else class LeakDetector {}; #endif LeakDetector leakDetector; // #included from: internal/catch_impl.hpp #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED // Collect all the implementation files together here // These are the equivalent of what would usually be cpp files #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wweak-vtables" #endif // #included from: ../catch_session.hpp #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED // #included from: internal/catch_commandline.hpp #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED // #included from: catch_config.hpp #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED // #included from: catch_test_spec_parser.hpp #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif // #included from: catch_test_spec.hpp #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif // #included from: catch_wildcard_pattern.hpp #define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED #include namespace Catch { class WildcardPattern { enum WildcardPosition { NoWildcard = 0, WildcardAtStart = 1, WildcardAtEnd = 2, WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd }; public: WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) : m_caseSensitivity( caseSensitivity ), m_wildcard( NoWildcard ), m_pattern( adjustCase( pattern ) ) { if( startsWith( m_pattern, '*' ) ) { m_pattern = m_pattern.substr( 1 ); m_wildcard = WildcardAtStart; } if( endsWith( m_pattern, '*' ) ) { m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); } } virtual ~WildcardPattern(); virtual bool matches( std::string const& str ) const { switch( m_wildcard ) { case NoWildcard: return m_pattern == adjustCase( str ); case WildcardAtStart: return endsWith( adjustCase( str ), m_pattern ); case WildcardAtEnd: return startsWith( adjustCase( str ), m_pattern ); case WildcardAtBothEnds: return contains( adjustCase( str ), m_pattern ); } #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code" #endif throw std::logic_error( "Unknown enum" ); #ifdef __clang__ #pragma clang diagnostic pop #endif } private: std::string adjustCase( std::string const& str ) const { return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; } CaseSensitive::Choice m_caseSensitivity; WildcardPosition m_wildcard; std::string m_pattern; }; } #include #include namespace Catch { class TestSpec { struct Pattern : SharedImpl<> { virtual ~Pattern(); virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; class NamePattern : public Pattern { public: NamePattern( std::string const& name ) : m_wildcardPattern( toLower( name ), CaseSensitive::No ) {} virtual ~NamePattern(); virtual bool matches( TestCaseInfo const& testCase ) const { return m_wildcardPattern.matches( toLower( testCase.name ) ); } private: WildcardPattern m_wildcardPattern; }; class TagPattern : public Pattern { public: TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} virtual ~TagPattern(); virtual bool matches( TestCaseInfo const& testCase ) const { return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); } private: std::string m_tag; }; class ExcludedPattern : public Pattern { public: ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} virtual ~ExcludedPattern(); virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } private: Ptr m_underlyingPattern; }; struct Filter { std::vector > m_patterns; bool matches( TestCaseInfo const& testCase ) const { // All patterns in a filter must match for the filter to be a match for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) { if( !(*it)->matches( testCase ) ) return false; } return true; } }; public: bool hasFilters() const { return !m_filters.empty(); } bool matches( TestCaseInfo const& testCase ) const { // A TestSpec matches if any filter matches for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) if( it->matches( testCase ) ) return true; return false; } private: std::vector m_filters; friend class TestSpecParser; }; } #ifdef __clang__ #pragma clang diagnostic pop #endif namespace Catch { class TestSpecParser { enum Mode{ None, Name, QuotedName, Tag, EscapedName }; Mode m_mode; bool m_exclusion; std::size_t m_start, m_pos; std::string m_arg; std::vector m_escapeChars; TestSpec::Filter m_currentFilter; TestSpec m_testSpec; ITagAliasRegistry const* m_tagAliases; public: TestSpecParser( ITagAliasRegistry const& tagAliases ) :m_mode(None), m_exclusion(false), m_start(0), m_pos(0), m_tagAliases( &tagAliases ) {} TestSpecParser& parse( std::string const& arg ) { m_mode = None; m_exclusion = false; m_start = std::string::npos; m_arg = m_tagAliases->expandAliases( arg ); m_escapeChars.clear(); for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) visitChar( m_arg[m_pos] ); if( m_mode == Name ) addPattern(); return *this; } TestSpec testSpec() { addFilter(); return m_testSpec; } private: void visitChar( char c ) { if( m_mode == None ) { switch( c ) { case ' ': return; case '~': m_exclusion = true; return; case '[': return startNewMode( Tag, ++m_pos ); case '"': return startNewMode( QuotedName, ++m_pos ); case '\\': return escape(); default: startNewMode( Name, m_pos ); break; } } if( m_mode == Name ) { if( c == ',' ) { addPattern(); addFilter(); } else if( c == '[' ) { if( subString() == "exclude:" ) m_exclusion = true; else addPattern(); startNewMode( Tag, ++m_pos ); } else if( c == '\\' ) escape(); } else if( m_mode == EscapedName ) m_mode = Name; else if( m_mode == QuotedName && c == '"' ) addPattern(); else if( m_mode == Tag && c == ']' ) addPattern(); } void startNewMode( Mode mode, std::size_t start ) { m_mode = mode; m_start = start; } void escape() { if( m_mode == None ) m_start = m_pos; m_mode = EscapedName; m_escapeChars.push_back( m_pos ); } std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } template void addPattern() { std::string token = subString(); for( size_t i = 0; i < m_escapeChars.size(); ++i ) token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); m_escapeChars.clear(); if( startsWith( token, "exclude:" ) ) { m_exclusion = true; token = token.substr( 8 ); } if( !token.empty() ) { Ptr pattern = new T( token ); if( m_exclusion ) pattern = new TestSpec::ExcludedPattern( pattern ); m_currentFilter.m_patterns.push_back( pattern ); } m_exclusion = false; m_mode = None; } void addFilter() { if( !m_currentFilter.m_patterns.empty() ) { m_testSpec.m_filters.push_back( m_currentFilter ); m_currentFilter = TestSpec::Filter(); } } }; inline TestSpec parseTestSpec( std::string const& arg ) { return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); } } // namespace Catch #ifdef __clang__ #pragma clang diagnostic pop #endif // #included from: catch_interfaces_config.h #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED #include #include #include namespace Catch { struct Verbosity { enum Level { NoOutput = 0, Quiet, Normal }; }; struct WarnAbout { enum What { Nothing = 0x00, NoAssertions = 0x01 }; }; struct ShowDurations { enum OrNot { DefaultForReporter, Always, Never }; }; struct RunTests { enum InWhatOrder { InDeclarationOrder, InLexicographicalOrder, InRandomOrder }; }; struct UseColour { enum YesOrNo { Auto, Yes, No }; }; struct WaitForKeypress { enum When { Never, BeforeStart = 1, BeforeExit = 2, BeforeStartAndExit = BeforeStart | BeforeExit }; }; class TestSpec; struct IConfig : IShared { virtual ~IConfig(); virtual bool allowThrows() const = 0; virtual std::ostream& stream() const = 0; virtual std::string name() const = 0; virtual bool includeSuccessfulResults() const = 0; virtual bool shouldDebugBreak() const = 0; virtual bool warnAboutMissingAssertions() const = 0; virtual int abortAfter() const = 0; virtual bool showInvisibles() const = 0; virtual ShowDurations::OrNot showDurations() const = 0; virtual TestSpec const& testSpec() const = 0; virtual RunTests::InWhatOrder runOrder() const = 0; virtual unsigned int rngSeed() const = 0; virtual UseColour::YesOrNo useColour() const = 0; virtual std::vector const& getSectionsToRun() const = 0; }; } // #included from: catch_stream.h #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED // #included from: catch_streambuf.h #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED #include namespace Catch { class StreamBufBase : public std::streambuf { public: virtual ~StreamBufBase() CATCH_NOEXCEPT; }; } #include #include #include #include namespace Catch { std::ostream& cout(); std::ostream& cerr(); std::ostream& clog(); struct IStream { virtual ~IStream() CATCH_NOEXCEPT; virtual std::ostream& stream() const = 0; }; class FileStream : public IStream { mutable std::ofstream m_ofs; public: FileStream( std::string const& filename ); virtual ~FileStream() CATCH_NOEXCEPT; public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; }; class CoutStream : public IStream { mutable std::ostream m_os; public: CoutStream(); virtual ~CoutStream() CATCH_NOEXCEPT; public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; }; class DebugOutStream : public IStream { CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; mutable std::ostream m_os; public: DebugOutStream(); virtual ~DebugOutStream() CATCH_NOEXCEPT; public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; }; } #include #include #include #include #ifndef CATCH_CONFIG_CONSOLE_WIDTH #define CATCH_CONFIG_CONSOLE_WIDTH 80 #endif namespace Catch { struct ConfigData { ConfigData() : listTests( false ), listTags( false ), listReporters( false ), listTestNamesOnly( false ), listExtraInfo( false ), showSuccessfulTests( false ), shouldDebugBreak( false ), noThrow( false ), showHelp( false ), showInvisibles( false ), filenamesAsTags( false ), libIdentify( false ), abortAfter( -1 ), rngSeed( 0 ), verbosity( Verbosity::Normal ), warnings( WarnAbout::Nothing ), showDurations( ShowDurations::DefaultForReporter ), runOrder( RunTests::InDeclarationOrder ), useColour( UseColour::Auto ), waitForKeypress( WaitForKeypress::Never ) {} bool listTests; bool listTags; bool listReporters; bool listTestNamesOnly; bool listExtraInfo; bool showSuccessfulTests; bool shouldDebugBreak; bool noThrow; bool showHelp; bool showInvisibles; bool filenamesAsTags; bool libIdentify; int abortAfter; unsigned int rngSeed; Verbosity::Level verbosity; WarnAbout::What warnings; ShowDurations::OrNot showDurations; RunTests::InWhatOrder runOrder; UseColour::YesOrNo useColour; WaitForKeypress::When waitForKeypress; std::string outputFilename; std::string name; std::string processName; std::vector reporterNames; std::vector testsOrTags; std::vector sectionsToRun; }; class Config : public SharedImpl { private: Config( Config const& other ); Config& operator = ( Config const& other ); virtual void dummy(); public: Config() {} Config( ConfigData const& data ) : m_data( data ), m_stream( openStream() ) { if( !data.testsOrTags.empty() ) { TestSpecParser parser( ITagAliasRegistry::get() ); for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) parser.parse( data.testsOrTags[i] ); m_testSpec = parser.testSpec(); } } virtual ~Config() {} std::string const& getFilename() const { return m_data.outputFilename ; } bool listTests() const { return m_data.listTests; } bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } bool listTags() const { return m_data.listTags; } bool listReporters() const { return m_data.listReporters; } bool listExtraInfo() const { return m_data.listExtraInfo; } std::string getProcessName() const { return m_data.processName; } std::vector const& getReporterNames() const { return m_data.reporterNames; } std::vector const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; } virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; } bool showHelp() const { return m_data.showHelp; } // IConfig interface virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; } virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); } virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; } virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; } virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; } virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; } virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; } virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; } virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; } virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; } virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; } virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; } private: IStream const* openStream() { if( m_data.outputFilename.empty() ) return new CoutStream(); else if( m_data.outputFilename[0] == '%' ) { if( m_data.outputFilename == "%debug" ) return new DebugOutStream(); else throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); } else return new FileStream( m_data.outputFilename ); } ConfigData m_data; CATCH_AUTO_PTR( IStream const ) m_stream; TestSpec m_testSpec; }; } // end namespace Catch // #included from: catch_clara.h #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED // Use Catch's value for console width (store Clara's off to the side, if present) #ifdef CLARA_CONFIG_CONSOLE_WIDTH #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH #undef CLARA_CONFIG_CONSOLE_WIDTH #endif #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH // Declare Clara inside the Catch namespace #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { // #included from: ../external/clara.h // Version 0.0.2.4 // Only use header guard if we are not using an outer namespace #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) #ifndef STITCH_CLARA_OPEN_NAMESPACE #define TWOBLUECUBES_CLARA_H_INCLUDED #define STITCH_CLARA_OPEN_NAMESPACE #define STITCH_CLARA_CLOSE_NAMESPACE #else #define STITCH_CLARA_CLOSE_NAMESPACE } #endif #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE // ----------- #included from tbc_text_format.h ----------- // Only use header guard if we are not using an outer namespace #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE #define TBC_TEXT_FORMAT_H_INCLUDED #endif #include #include #include #include #include // Use optional outer namespace #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { #endif namespace Tbc { #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; #else const unsigned int consoleWidth = 80; #endif struct TextAttributes { TextAttributes() : initialIndent( std::string::npos ), indent( 0 ), width( consoleWidth-1 ), tabChar( '\t' ) {} TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } std::size_t initialIndent; // indent of first line, or npos std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos std::size_t width; // maximum width of text, including indent. Longer text will wrap char tabChar; // If this char is seen the indent is changed to current pos }; class Text { public: Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) : attr( _attr ) { std::string wrappableChars = " [({.,/|\\-"; std::size_t indent = _attr.initialIndent != std::string::npos ? _attr.initialIndent : _attr.indent; std::string remainder = _str; while( !remainder.empty() ) { if( lines.size() >= 1000 ) { lines.push_back( "... message truncated due to excessive size" ); return; } std::size_t tabPos = std::string::npos; std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); std::size_t pos = remainder.find_first_of( '\n' ); if( pos <= width ) { width = pos; } pos = remainder.find_last_of( _attr.tabChar, width ); if( pos != std::string::npos ) { tabPos = pos; if( remainder[width] == '\n' ) width--; remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); } if( width == remainder.size() ) { spliceLine( indent, remainder, width ); } else if( remainder[width] == '\n' ) { spliceLine( indent, remainder, width ); if( width <= 1 || remainder.size() != 1 ) remainder = remainder.substr( 1 ); indent = _attr.indent; } else { pos = remainder.find_last_of( wrappableChars, width ); if( pos != std::string::npos && pos > 0 ) { spliceLine( indent, remainder, pos ); if( remainder[0] == ' ' ) remainder = remainder.substr( 1 ); } else { spliceLine( indent, remainder, width-1 ); lines.back() += "-"; } if( lines.size() == 1 ) indent = _attr.indent; if( tabPos != std::string::npos ) indent += tabPos; } } } void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); _remainder = _remainder.substr( _pos ); } typedef std::vector::const_iterator const_iterator; const_iterator begin() const { return lines.begin(); } const_iterator end() const { return lines.end(); } std::string const& last() const { return lines.back(); } std::size_t size() const { return lines.size(); } std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } std::string toString() const { std::ostringstream oss; oss << *this; return oss.str(); } friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); it != itEnd; ++it ) { if( it != _text.begin() ) _stream << "\n"; _stream << *it; } return _stream; } private: std::string str; TextAttributes attr; std::vector lines; }; } // end namespace Tbc #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE } // end outer namespace #endif #endif // TBC_TEXT_FORMAT_H_INCLUDED // ----------- end of #include from tbc_text_format.h ----------- // ........... back in clara.h #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE // ----------- #included from clara_compilers.h ----------- #ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED #define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED // Detect a number of compiler features - mostly C++11/14 conformance - by compiler // The following features are defined: // // CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? // CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? // CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods // CLARA_CONFIG_CPP11_OVERRIDE : is override supported? // CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) // CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? // CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? // In general each macro has a _NO_ form // (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. // Many features, at point of detection, define an _INTERNAL_ macro, so they // can be combined, en-mass, with the _NO_ forms later. // All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 #ifdef __clang__ #if __has_feature(cxx_nullptr) #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR #endif #if __has_feature(cxx_noexcept) #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT #endif #endif // __clang__ //////////////////////////////////////////////////////////////////////////////// // GCC #ifdef __GNUC__ #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR #endif // - otherwise more recent versions define __cplusplus >= 201103L // and will get picked up below #endif // __GNUC__ //////////////////////////////////////////////////////////////////////////////// // Visual C++ #ifdef _MSC_VER #if (_MSC_VER >= 1600) #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR #endif #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS #endif #endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// // C++ language feature support // catch all support for C++11 #if defined(__cplusplus) && __cplusplus >= 201103L #define CLARA_CPP11_OR_GREATER #if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR #endif #ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT #endif #ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS #endif #if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) #define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE #endif #if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR #endif #endif // __cplusplus >= 201103L // Now set the actual defines based on the above + anything the user has configured #if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) #define CLARA_CONFIG_CPP11_NULLPTR #endif #if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) #define CLARA_CONFIG_CPP11_NOEXCEPT #endif #if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) #define CLARA_CONFIG_CPP11_GENERATED_METHODS #endif #if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) #define CLARA_CONFIG_CPP11_OVERRIDE #endif #if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) #define CLARA_CONFIG_CPP11_UNIQUE_PTR #endif // noexcept support: #if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) #define CLARA_NOEXCEPT noexcept # define CLARA_NOEXCEPT_IS(x) noexcept(x) #else #define CLARA_NOEXCEPT throw() # define CLARA_NOEXCEPT_IS(x) #endif // nullptr support #ifdef CLARA_CONFIG_CPP11_NULLPTR #define CLARA_NULL nullptr #else #define CLARA_NULL NULL #endif // override support #ifdef CLARA_CONFIG_CPP11_OVERRIDE #define CLARA_OVERRIDE override #else #define CLARA_OVERRIDE #endif // unique_ptr support #ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR # define CLARA_AUTO_PTR( T ) std::unique_ptr #else # define CLARA_AUTO_PTR( T ) std::auto_ptr #endif #endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED // ----------- end of #include from clara_compilers.h ----------- // ........... back in clara.h #include #include #include #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) #define CLARA_PLATFORM_WINDOWS #endif // Use optional outer namespace #ifdef STITCH_CLARA_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE #endif namespace Clara { struct UnpositionalTag {}; extern UnpositionalTag _; #ifdef CLARA_CONFIG_MAIN UnpositionalTag _; #endif namespace Detail { #ifdef CLARA_CONSOLE_WIDTH const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; #else const unsigned int consoleWidth = 80; #endif using namespace Tbc; inline bool startsWith( std::string const& str, std::string const& prefix ) { return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; } template struct RemoveConstRef{ typedef T type; }; template struct RemoveConstRef{ typedef T type; }; template struct RemoveConstRef{ typedef T type; }; template struct RemoveConstRef{ typedef T type; }; template struct IsBool { static const bool value = false; }; template<> struct IsBool { static const bool value = true; }; template void convertInto( std::string const& _source, T& _dest ) { std::stringstream ss; ss << _source; ss >> _dest; if( ss.fail() ) throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); } inline void convertInto( std::string const& _source, std::string& _dest ) { _dest = _source; } char toLowerCh(char c) { return static_cast( std::tolower( c ) ); } inline void convertInto( std::string const& _source, bool& _dest ) { std::string sourceLC = _source; std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh ); if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) _dest = true; else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) _dest = false; else throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); } template struct IArgFunction { virtual ~IArgFunction() {} #ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS IArgFunction() = default; IArgFunction( IArgFunction const& ) = default; #endif virtual void set( ConfigT& config, std::string const& value ) const = 0; virtual bool takesArg() const = 0; virtual IArgFunction* clone() const = 0; }; template class BoundArgFunction { public: BoundArgFunction() : functionObj( CLARA_NULL ) {} BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} BoundArgFunction& operator = ( BoundArgFunction const& other ) { IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; delete functionObj; functionObj = newFunctionObj; return *this; } ~BoundArgFunction() { delete functionObj; } void set( ConfigT& config, std::string const& value ) const { functionObj->set( config, value ); } bool takesArg() const { return functionObj->takesArg(); } bool isSet() const { return functionObj != CLARA_NULL; } private: IArgFunction* functionObj; }; template struct NullBinder : IArgFunction{ virtual void set( C&, std::string const& ) const {} virtual bool takesArg() const { return true; } virtual IArgFunction* clone() const { return new NullBinder( *this ); } }; template struct BoundDataMember : IArgFunction{ BoundDataMember( M C::* _member ) : member( _member ) {} virtual void set( C& p, std::string const& stringValue ) const { convertInto( stringValue, p.*member ); } virtual bool takesArg() const { return !IsBool::value; } virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } M C::* member; }; template struct BoundUnaryMethod : IArgFunction{ BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} virtual void set( C& p, std::string const& stringValue ) const { typename RemoveConstRef::type value; convertInto( stringValue, value ); (p.*member)( value ); } virtual bool takesArg() const { return !IsBool::value; } virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } void (C::*member)( M ); }; template struct BoundNullaryMethod : IArgFunction{ BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} virtual void set( C& p, std::string const& stringValue ) const { bool value; convertInto( stringValue, value ); if( value ) (p.*member)(); } virtual bool takesArg() const { return false; } virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } void (C::*member)(); }; template struct BoundUnaryFunction : IArgFunction{ BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} virtual void set( C& obj, std::string const& stringValue ) const { bool value; convertInto( stringValue, value ); if( value ) function( obj ); } virtual bool takesArg() const { return false; } virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } void (*function)( C& ); }; template struct BoundBinaryFunction : IArgFunction{ BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} virtual void set( C& obj, std::string const& stringValue ) const { typename RemoveConstRef::type value; convertInto( stringValue, value ); function( obj, value ); } virtual bool takesArg() const { return !IsBool::value; } virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } void (*function)( C&, T ); }; } // namespace Detail inline std::vector argsToVector( int argc, char const* const* const argv ) { std::vector args( static_cast( argc ) ); for( std::size_t i = 0; i < static_cast( argc ); ++i ) args[i] = argv[i]; return args; } class Parser { enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; Mode mode; std::size_t from; bool inQuotes; public: struct Token { enum Type { Positional, ShortOpt, LongOpt }; Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} Type type; std::string data; }; Parser() : mode( None ), from( 0 ), inQuotes( false ){} void parseIntoTokens( std::vector const& args, std::vector& tokens ) { const std::string doubleDash = "--"; for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) parseIntoTokens( args[i], tokens); } void parseIntoTokens( std::string const& arg, std::vector& tokens ) { for( std::size_t i = 0; i < arg.size(); ++i ) { char c = arg[i]; if( c == '"' ) inQuotes = !inQuotes; mode = handleMode( i, c, arg, tokens ); } mode = handleMode( arg.size(), '\0', arg, tokens ); } Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { switch( mode ) { case None: return handleNone( i, c ); case MaybeShortOpt: return handleMaybeShortOpt( i, c ); case ShortOpt: case LongOpt: case SlashOpt: return handleOpt( i, c, arg, tokens ); case Positional: return handlePositional( i, c, arg, tokens ); default: throw std::logic_error( "Unknown mode" ); } } Mode handleNone( std::size_t i, char c ) { if( inQuotes ) { from = i; return Positional; } switch( c ) { case '-': return MaybeShortOpt; #ifdef CLARA_PLATFORM_WINDOWS case '/': from = i+1; return SlashOpt; #endif default: from = i; return Positional; } } Mode handleMaybeShortOpt( std::size_t i, char c ) { switch( c ) { case '-': from = i+1; return LongOpt; default: from = i; return ShortOpt; } } Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) return mode; std::string optName = arg.substr( from, i-from ); if( mode == ShortOpt ) for( std::size_t j = 0; j < optName.size(); ++j ) tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); else if( mode == SlashOpt && optName.size() == 1 ) tokens.push_back( Token( Token::ShortOpt, optName ) ); else tokens.push_back( Token( Token::LongOpt, optName ) ); return None; } Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos ) return mode; std::string data = arg.substr( from, i-from ); tokens.push_back( Token( Token::Positional, data ) ); return None; } }; template struct CommonArgProperties { CommonArgProperties() {} CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} Detail::BoundArgFunction boundField; std::string description; std::string detail; std::string placeholder; // Only value if boundField takes an arg bool takesArg() const { return !placeholder.empty(); } void validate() const { if( !boundField.isSet() ) throw std::logic_error( "option not bound" ); } }; struct OptionArgProperties { std::vector shortNames; std::string longName; bool hasShortName( std::string const& shortName ) const { return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); } bool hasLongName( std::string const& _longName ) const { return _longName == longName; } }; struct PositionalArgProperties { PositionalArgProperties() : position( -1 ) {} int position; // -1 means non-positional (floating) bool isFixedPositional() const { return position != -1; } }; template class CommandLine { struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { Arg() {} Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} using CommonArgProperties::placeholder; // !TBD std::string dbgName() const { if( !longName.empty() ) return "--" + longName; if( !shortNames.empty() ) return "-" + shortNames[0]; return "positional args"; } std::string commands() const { std::ostringstream oss; bool first = true; std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); for(; it != itEnd; ++it ) { if( first ) first = false; else oss << ", "; oss << "-" << *it; } if( !longName.empty() ) { if( !first ) oss << ", "; oss << "--" << longName; } if( !placeholder.empty() ) oss << " <" << placeholder << ">"; return oss.str(); } }; typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; friend void addOptName( Arg& arg, std::string const& optName ) { if( optName.empty() ) return; if( Detail::startsWith( optName, "--" ) ) { if( !arg.longName.empty() ) throw std::logic_error( "Only one long opt may be specified. '" + arg.longName + "' already specified, now attempting to add '" + optName + "'" ); arg.longName = optName.substr( 2 ); } else if( Detail::startsWith( optName, "-" ) ) arg.shortNames.push_back( optName.substr( 1 ) ); else throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); } friend void setPositionalArg( Arg& arg, int position ) { arg.position = position; } class ArgBuilder { public: ArgBuilder( Arg* arg ) : m_arg( arg ) {} // Bind a non-boolean data member (requires placeholder string) template void bind( M C::* field, std::string const& placeholder ) { m_arg->boundField = new Detail::BoundDataMember( field ); m_arg->placeholder = placeholder; } // Bind a boolean data member (no placeholder required) template void bind( bool C::* field ) { m_arg->boundField = new Detail::BoundDataMember( field ); } // Bind a method taking a single, non-boolean argument (requires a placeholder string) template void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); m_arg->placeholder = placeholder; } // Bind a method taking a single, boolean argument (no placeholder string required) template void bind( void (C::* unaryMethod)( bool ) ) { m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); } // Bind a method that takes no arguments (will be called if opt is present) template void bind( void (C::* nullaryMethod)() ) { m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); } // Bind a free function taking a single argument - the object to operate on (no placeholder string required) template void bind( void (* unaryFunction)( C& ) ) { m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); } // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) template void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); m_arg->placeholder = placeholder; } ArgBuilder& describe( std::string const& description ) { m_arg->description = description; return *this; } ArgBuilder& detail( std::string const& detail ) { m_arg->detail = detail; return *this; } protected: Arg* m_arg; }; class OptBuilder : public ArgBuilder { public: OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} OptBuilder& operator[]( std::string const& optName ) { addOptName( *ArgBuilder::m_arg, optName ); return *this; } }; public: CommandLine() : m_boundProcessName( new Detail::NullBinder() ), m_highestSpecifiedArgPosition( 0 ), m_throwOnUnrecognisedTokens( false ) {} CommandLine( CommandLine const& other ) : m_boundProcessName( other.m_boundProcessName ), m_options ( other.m_options ), m_positionalArgs( other.m_positionalArgs ), m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) { if( other.m_floatingArg.get() ) m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); } CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { m_throwOnUnrecognisedTokens = shouldThrow; return *this; } OptBuilder operator[]( std::string const& optName ) { m_options.push_back( Arg() ); addOptName( m_options.back(), optName ); OptBuilder builder( &m_options.back() ); return builder; } ArgBuilder operator[]( int position ) { m_positionalArgs.insert( std::make_pair( position, Arg() ) ); if( position > m_highestSpecifiedArgPosition ) m_highestSpecifiedArgPosition = position; setPositionalArg( m_positionalArgs[position], position ); ArgBuilder builder( &m_positionalArgs[position] ); return builder; } // Invoke this with the _ instance ArgBuilder operator[]( UnpositionalTag ) { if( m_floatingArg.get() ) throw std::logic_error( "Only one unpositional argument can be added" ); m_floatingArg.reset( new Arg() ); ArgBuilder builder( m_floatingArg.get() ); return builder; } template void bindProcessName( M C::* field ) { m_boundProcessName = new Detail::BoundDataMember( field ); } template void bindProcessName( void (C::*_unaryMethod)( M ) ) { m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); } void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; std::size_t maxWidth = 0; for( it = itBegin; it != itEnd; ++it ) maxWidth = (std::max)( maxWidth, it->commands().size() ); for( it = itBegin; it != itEnd; ++it ) { Detail::Text usage( it->commands(), Detail::TextAttributes() .setWidth( maxWidth+indent ) .setIndent( indent ) ); Detail::Text desc( it->description, Detail::TextAttributes() .setWidth( width - maxWidth - 3 ) ); for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { std::string usageCol = i < usage.size() ? usage[i] : ""; os << usageCol; if( i < desc.size() && !desc[i].empty() ) os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) << desc[i]; os << "\n"; } } } std::string optUsage() const { std::ostringstream oss; optUsage( oss ); return oss.str(); } void argSynopsis( std::ostream& os ) const { for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { if( i > 1 ) os << " "; typename std::map::const_iterator it = m_positionalArgs.find( i ); if( it != m_positionalArgs.end() ) os << "<" << it->second.placeholder << ">"; else if( m_floatingArg.get() ) os << "<" << m_floatingArg->placeholder << ">"; else throw std::logic_error( "non consecutive positional arguments with no floating args" ); } // !TBD No indication of mandatory args if( m_floatingArg.get() ) { if( m_highestSpecifiedArgPosition > 1 ) os << " "; os << "[<" << m_floatingArg->placeholder << "> ...]"; } } std::string argSynopsis() const { std::ostringstream oss; argSynopsis( oss ); return oss.str(); } void usage( std::ostream& os, std::string const& procName ) const { validate(); os << "usage:\n " << procName << " "; argSynopsis( os ); if( !m_options.empty() ) { os << " [options]\n\nwhere options are: \n"; optUsage( os, 2 ); } os << "\n"; } std::string usage( std::string const& procName ) const { std::ostringstream oss; usage( oss, procName ); return oss.str(); } ConfigT parse( std::vector const& args ) const { ConfigT config; parseInto( args, config ); return config; } std::vector parseInto( std::vector const& args, ConfigT& config ) const { std::string processName = args.empty() ? std::string() : args[0]; std::size_t lastSlash = processName.find_last_of( "/\\" ); if( lastSlash != std::string::npos ) processName = processName.substr( lastSlash+1 ); m_boundProcessName.set( config, processName ); std::vector tokens; Parser parser; parser.parseIntoTokens( args, tokens ); return populate( tokens, config ); } std::vector populate( std::vector const& tokens, ConfigT& config ) const { validate(); std::vector unusedTokens = populateOptions( tokens, config ); unusedTokens = populateFixedArgs( unusedTokens, config ); unusedTokens = populateFloatingArgs( unusedTokens, config ); return unusedTokens; } std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { std::vector unusedTokens; std::vector errors; for( std::size_t i = 0; i < tokens.size(); ++i ) { Parser::Token const& token = tokens[i]; typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); for(; it != itEnd; ++it ) { Arg const& arg = *it; try { if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { if( arg.takesArg() ) { if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) errors.push_back( "Expected argument to option: " + token.data ); else arg.boundField.set( config, tokens[++i].data ); } else { arg.boundField.set( config, "true" ); } break; } } catch( std::exception& ex ) { errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); } } if( it == itEnd ) { if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) unusedTokens.push_back( token ); else if( errors.empty() && m_throwOnUnrecognisedTokens ) errors.push_back( "unrecognised option: " + token.data ); } } if( !errors.empty() ) { std::ostringstream oss; for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); it != itEnd; ++it ) { if( it != errors.begin() ) oss << "\n"; oss << *it; } throw std::runtime_error( oss.str() ); } return unusedTokens; } std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { std::vector unusedTokens; int position = 1; for( std::size_t i = 0; i < tokens.size(); ++i ) { Parser::Token const& token = tokens[i]; typename std::map::const_iterator it = m_positionalArgs.find( position ); if( it != m_positionalArgs.end() ) it->second.boundField.set( config, token.data ); else unusedTokens.push_back( token ); if( token.type == Parser::Token::Positional ) position++; } return unusedTokens; } std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { if( !m_floatingArg.get() ) return tokens; std::vector unusedTokens; for( std::size_t i = 0; i < tokens.size(); ++i ) { Parser::Token const& token = tokens[i]; if( token.type == Parser::Token::Positional ) m_floatingArg->boundField.set( config, token.data ); else unusedTokens.push_back( token ); } return unusedTokens; } void validate() const { if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) throw std::logic_error( "No options or arguments specified" ); for( typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); it != itEnd; ++it ) it->validate(); } private: Detail::BoundArgFunction m_boundProcessName; std::vector m_options; std::map m_positionalArgs; ArgAutoPtr m_floatingArg; int m_highestSpecifiedArgPosition; bool m_throwOnUnrecognisedTokens; }; } // end namespace Clara STITCH_CLARA_CLOSE_NAMESPACE #undef STITCH_CLARA_OPEN_NAMESPACE #undef STITCH_CLARA_CLOSE_NAMESPACE #endif // TWOBLUECUBES_CLARA_H_INCLUDED #undef STITCH_CLARA_OPEN_NAMESPACE // Restore Clara's value for console width, if present #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #endif #include #include namespace Catch { inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } inline void abortAfterX( ConfigData& config, int x ) { if( x < 1 ) throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); config.abortAfter = x; } inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); } inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } inline void addWarning( ConfigData& config, std::string const& _warning ) { if( _warning == "NoAssertions" ) config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); else throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' ); } inline void setOrder( ConfigData& config, std::string const& order ) { if( startsWith( "declared", order ) ) config.runOrder = RunTests::InDeclarationOrder; else if( startsWith( "lexical", order ) ) config.runOrder = RunTests::InLexicographicalOrder; else if( startsWith( "random", order ) ) config.runOrder = RunTests::InRandomOrder; else throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' ); } inline void setRngSeed( ConfigData& config, std::string const& seed ) { if( seed == "time" ) { config.rngSeed = static_cast( std::time(0) ); } else { std::stringstream ss; ss << seed; ss >> config.rngSeed; if( ss.fail() ) throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" ); } } inline void setVerbosity( ConfigData& config, int level ) { // !TBD: accept strings? config.verbosity = static_cast( level ); } inline void setShowDurations( ConfigData& config, bool _showDurations ) { config.showDurations = _showDurations ? ShowDurations::Always : ShowDurations::Never; } inline void setUseColour( ConfigData& config, std::string const& value ) { std::string mode = toLower( value ); if( mode == "yes" ) config.useColour = UseColour::Yes; else if( mode == "no" ) config.useColour = UseColour::No; else if( mode == "auto" ) config.useColour = UseColour::Auto; else throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); } inline void setWaitForKeypress( ConfigData& config, std::string const& keypress ) { std::string keypressLc = toLower( keypress ); if( keypressLc == "start" ) config.waitForKeypress = WaitForKeypress::BeforeStart; else if( keypressLc == "exit" ) config.waitForKeypress = WaitForKeypress::BeforeExit; else if( keypressLc == "both" ) config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; else throw std::runtime_error( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" ); }; inline void forceColour( ConfigData& config ) { config.useColour = UseColour::Yes; } inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { std::ifstream f( _filename.c_str() ); if( !f.is_open() ) throw std::domain_error( "Unable to load input file: " + _filename ); std::string line; while( std::getline( f, line ) ) { line = trim(line); if( !line.empty() && !startsWith( line, '#' ) ) { if( !startsWith( line, '"' ) ) line = '"' + line + '"'; addTestOrTags( config, line + ',' ); } } } inline Clara::CommandLine makeCommandLineParser() { using namespace Clara; CommandLine cli; cli.bindProcessName( &ConfigData::processName ); cli["-?"]["-h"]["--help"] .describe( "display usage information" ) .bind( &ConfigData::showHelp ); cli["-l"]["--list-tests"] .describe( "list all/matching test cases" ) .bind( &ConfigData::listTests ); cli["-t"]["--list-tags"] .describe( "list all/matching tags" ) .bind( &ConfigData::listTags ); cli["-s"]["--success"] .describe( "include successful tests in output" ) .bind( &ConfigData::showSuccessfulTests ); cli["-b"]["--break"] .describe( "break into debugger on failure" ) .bind( &ConfigData::shouldDebugBreak ); cli["-e"]["--nothrow"] .describe( "skip exception tests" ) .bind( &ConfigData::noThrow ); cli["-i"]["--invisibles"] .describe( "show invisibles (tabs, newlines)" ) .bind( &ConfigData::showInvisibles ); cli["-o"]["--out"] .describe( "output filename" ) .bind( &ConfigData::outputFilename, "filename" ); cli["-r"]["--reporter"] // .placeholder( "name[:filename]" ) .describe( "reporter to use (defaults to console)" ) .bind( &addReporterName, "name" ); cli["-n"]["--name"] .describe( "suite name" ) .bind( &ConfigData::name, "name" ); cli["-a"]["--abort"] .describe( "abort at first failure" ) .bind( &abortAfterFirst ); cli["-x"]["--abortx"] .describe( "abort after x failures" ) .bind( &abortAfterX, "no. failures" ); cli["-w"]["--warn"] .describe( "enable warnings" ) .bind( &addWarning, "warning name" ); // - needs updating if reinstated // cli.into( &setVerbosity ) // .describe( "level of verbosity (0=no output)" ) // .shortOpt( "v") // .longOpt( "verbosity" ) // .placeholder( "level" ); cli[_] .describe( "which test or tests to use" ) .bind( &addTestOrTags, "test name, pattern or tags" ); cli["-d"]["--durations"] .describe( "show test durations" ) .bind( &setShowDurations, "yes|no" ); cli["-f"]["--input-file"] .describe( "load test names to run from a file" ) .bind( &loadTestNamesFromFile, "filename" ); cli["-#"]["--filenames-as-tags"] .describe( "adds a tag for the filename" ) .bind( &ConfigData::filenamesAsTags ); cli["-c"]["--section"] .describe( "specify section to run" ) .bind( &addSectionToRun, "section name" ); // Less common commands which don't have a short form cli["--list-test-names-only"] .describe( "list all/matching test cases names only" ) .bind( &ConfigData::listTestNamesOnly ); cli["--list-extra-info"] .describe( "list all/matching test cases with more info" ) .bind( &ConfigData::listExtraInfo ); cli["--list-reporters"] .describe( "list all reporters" ) .bind( &ConfigData::listReporters ); cli["--order"] .describe( "test case order (defaults to decl)" ) .bind( &setOrder, "decl|lex|rand" ); cli["--rng-seed"] .describe( "set a specific seed for random numbers" ) .bind( &setRngSeed, "'time'|number" ); cli["--force-colour"] .describe( "force colourised output (deprecated)" ) .bind( &forceColour ); cli["--use-colour"] .describe( "should output be colourised" ) .bind( &setUseColour, "yes|no" ); cli["--use-colour"] .describe( "should output be colourised" ) .bind( &setUseColour, "yes|no" ); cli["--libidentify"] .describe( "report name and version according to libidentify standard" ) .bind( &ConfigData::libIdentify ); cli["--wait-for-keypress"] .describe( "waits for a keypress before exiting" ) .bind( &setWaitForKeypress, "start|exit|both" ); return cli; } } // end namespace Catch // #included from: internal/catch_list.hpp #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED // #included from: catch_text.h #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch // #included from: ../external/tbc_text_format.h // Only use header guard if we are not using an outer namespace #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED # endif # else # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED # endif #endif #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED #include #include #include // Use optional outer namespace #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { #endif namespace Tbc { #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; #else const unsigned int consoleWidth = 80; #endif struct TextAttributes { TextAttributes() : initialIndent( std::string::npos ), indent( 0 ), width( consoleWidth-1 ) {} TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } std::size_t initialIndent; // indent of first line, or npos std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos std::size_t width; // maximum width of text, including indent. Longer text will wrap }; class Text { public: Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) : attr( _attr ) { const std::string wrappableBeforeChars = "[({<\t"; const std::string wrappableAfterChars = "])}>-,./|\\"; const std::string wrappableInsteadOfChars = " \n\r"; std::string indent = _attr.initialIndent != std::string::npos ? std::string( _attr.initialIndent, ' ' ) : std::string( _attr.indent, ' ' ); typedef std::string::const_iterator iterator; iterator it = _str.begin(); const iterator strEnd = _str.end(); while( it != strEnd ) { if( lines.size() >= 1000 ) { lines.push_back( "... message truncated due to excessive size" ); return; } std::string suffix; std::size_t width = (std::min)( static_cast( strEnd-it ), _attr.width-static_cast( indent.size() ) ); iterator itEnd = it+width; iterator itNext = _str.end(); iterator itNewLine = std::find( it, itEnd, '\n' ); if( itNewLine != itEnd ) itEnd = itNewLine; if( itEnd != strEnd ) { bool foundWrapPoint = false; iterator findIt = itEnd; do { if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) { itEnd = findIt+1; itNext = findIt+1; foundWrapPoint = true; } else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) { itEnd = findIt; itNext = findIt; foundWrapPoint = true; } else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) { itNext = findIt+1; itEnd = findIt; foundWrapPoint = true; } if( findIt == it ) break; else --findIt; } while( !foundWrapPoint ); if( !foundWrapPoint ) { // No good wrap char, so we'll break mid word and add a hyphen --itEnd; itNext = itEnd; suffix = "-"; } else { while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos ) --itEnd; } } lines.push_back( indent + std::string( it, itEnd ) + suffix ); if( indent.size() != _attr.indent ) indent = std::string( _attr.indent, ' ' ); it = itNext; } } typedef std::vector::const_iterator const_iterator; const_iterator begin() const { return lines.begin(); } const_iterator end() const { return lines.end(); } std::string const& last() const { return lines.back(); } std::size_t size() const { return lines.size(); } std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } std::string toString() const { std::ostringstream oss; oss << *this; return oss.str(); } inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); it != itEnd; ++it ) { if( it != _text.begin() ) _stream << "\n"; _stream << *it; } return _stream; } private: std::string str; TextAttributes attr; std::vector lines; }; } // end namespace Tbc #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE } // end outer namespace #endif #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE namespace Catch { using Tbc::Text; using Tbc::TextAttributes; } // #included from: catch_console_colour.hpp #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED namespace Catch { struct Colour { enum Code { None = 0, White, Red, Green, Blue, Cyan, Yellow, Grey, Bright = 0x10, BrightRed = Bright | Red, BrightGreen = Bright | Green, LightGrey = Bright | Grey, BrightWhite = Bright | White, // By intention FileName = LightGrey, Warning = Yellow, ResultError = BrightRed, ResultSuccess = BrightGreen, ResultExpectedFailure = Warning, Error = BrightRed, Success = Green, OriginalExpression = Cyan, ReconstructedExpression = Yellow, SecondaryText = LightGrey, Headers = White }; // Use constructed object for RAII guard Colour( Code _colourCode ); Colour( Colour const& other ); ~Colour(); // Use static method for one-shot changes static void use( Code _colourCode ); private: bool m_moved; }; inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } } // end namespace Catch // #included from: catch_interfaces_reporter.h #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED #include #include #include namespace Catch { struct ReporterConfig { explicit ReporterConfig( Ptr const& _fullConfig ) : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} std::ostream& stream() const { return *m_stream; } Ptr fullConfig() const { return m_fullConfig; } private: std::ostream* m_stream; Ptr m_fullConfig; }; struct ReporterPreferences { ReporterPreferences() : shouldRedirectStdOut( false ) {} bool shouldRedirectStdOut; }; template struct LazyStat : Option { LazyStat() : used( false ) {} LazyStat& operator=( T const& _value ) { Option::operator=( _value ); used = false; return *this; } void reset() { Option::reset(); used = false; } bool used; }; struct TestRunInfo { TestRunInfo( std::string const& _name ) : name( _name ) {} std::string name; }; struct GroupInfo { GroupInfo( std::string const& _name, std::size_t _groupIndex, std::size_t _groupsCount ) : name( _name ), groupIndex( _groupIndex ), groupsCounts( _groupsCount ) {} std::string name; std::size_t groupIndex; std::size_t groupsCounts; }; struct AssertionStats { AssertionStats( AssertionResult const& _assertionResult, std::vector const& _infoMessages, Totals const& _totals ) : assertionResult( _assertionResult ), infoMessages( _infoMessages ), totals( _totals ) { if( assertionResult.hasMessage() ) { // Copy message into messages list. // !TBD This should have been done earlier, somewhere MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); builder << assertionResult.getMessage(); builder.m_info.message = builder.m_stream.str(); infoMessages.push_back( builder.m_info ); } } virtual ~AssertionStats(); # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS AssertionStats( AssertionStats const& ) = default; AssertionStats( AssertionStats && ) = default; AssertionStats& operator = ( AssertionStats const& ) = default; AssertionStats& operator = ( AssertionStats && ) = default; # endif AssertionResult assertionResult; std::vector infoMessages; Totals totals; }; struct SectionStats { SectionStats( SectionInfo const& _sectionInfo, Counts const& _assertions, double _durationInSeconds, bool _missingAssertions ) : sectionInfo( _sectionInfo ), assertions( _assertions ), durationInSeconds( _durationInSeconds ), missingAssertions( _missingAssertions ) {} virtual ~SectionStats(); # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS SectionStats( SectionStats const& ) = default; SectionStats( SectionStats && ) = default; SectionStats& operator = ( SectionStats const& ) = default; SectionStats& operator = ( SectionStats && ) = default; # endif SectionInfo sectionInfo; Counts assertions; double durationInSeconds; bool missingAssertions; }; struct TestCaseStats { TestCaseStats( TestCaseInfo const& _testInfo, Totals const& _totals, std::string const& _stdOut, std::string const& _stdErr, bool _aborting ) : testInfo( _testInfo ), totals( _totals ), stdOut( _stdOut ), stdErr( _stdErr ), aborting( _aborting ) {} virtual ~TestCaseStats(); # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS TestCaseStats( TestCaseStats const& ) = default; TestCaseStats( TestCaseStats && ) = default; TestCaseStats& operator = ( TestCaseStats const& ) = default; TestCaseStats& operator = ( TestCaseStats && ) = default; # endif TestCaseInfo testInfo; Totals totals; std::string stdOut; std::string stdErr; bool aborting; }; struct TestGroupStats { TestGroupStats( GroupInfo const& _groupInfo, Totals const& _totals, bool _aborting ) : groupInfo( _groupInfo ), totals( _totals ), aborting( _aborting ) {} TestGroupStats( GroupInfo const& _groupInfo ) : groupInfo( _groupInfo ), aborting( false ) {} virtual ~TestGroupStats(); # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS TestGroupStats( TestGroupStats const& ) = default; TestGroupStats( TestGroupStats && ) = default; TestGroupStats& operator = ( TestGroupStats const& ) = default; TestGroupStats& operator = ( TestGroupStats && ) = default; # endif GroupInfo groupInfo; Totals totals; bool aborting; }; struct TestRunStats { TestRunStats( TestRunInfo const& _runInfo, Totals const& _totals, bool _aborting ) : runInfo( _runInfo ), totals( _totals ), aborting( _aborting ) {} virtual ~TestRunStats(); # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS TestRunStats( TestRunStats const& _other ) : runInfo( _other.runInfo ), totals( _other.totals ), aborting( _other.aborting ) {} # else TestRunStats( TestRunStats const& ) = default; TestRunStats( TestRunStats && ) = default; TestRunStats& operator = ( TestRunStats const& ) = default; TestRunStats& operator = ( TestRunStats && ) = default; # endif TestRunInfo runInfo; Totals totals; bool aborting; }; class MultipleReporters; struct IStreamingReporter : IShared { virtual ~IStreamingReporter(); // Implementing class must also provide the following static method: // static std::string getDescription(); virtual ReporterPreferences getPreferences() const = 0; virtual void noMatchingTestCases( std::string const& spec ) = 0; virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; // The return value indicates if the messages buffer should be cleared: virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; virtual void sectionEnded( SectionStats const& sectionStats ) = 0; virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; virtual void skipTest( TestCaseInfo const& testInfo ) = 0; virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } }; struct IReporterFactory : IShared { virtual ~IReporterFactory(); virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; virtual std::string getDescription() const = 0; }; struct IReporterRegistry { typedef std::map > FactoryMap; typedef std::vector > Listeners; virtual ~IReporterRegistry(); virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; virtual Listeners const& getListeners() const = 0; }; Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); } #include #include namespace Catch { inline std::size_t listTests( Config const& config ) { TestSpec testSpec = config.testSpec(); if( config.testSpec().hasFilters() ) Catch::cout() << "Matching test cases:\n"; else { Catch::cout() << "All available test cases:\n"; testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); } std::size_t matchedTests = 0; TextAttributes nameAttr, descAttr, tagsAttr; nameAttr.setInitialIndent( 2 ).setIndent( 4 ); descAttr.setIndent( 4 ); tagsAttr.setIndent( 6 ); std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { matchedTests++; TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); Colour::Code colour = testCaseInfo.isHidden() ? Colour::SecondaryText : Colour::None; Colour colourGuard( colour ); Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; if( config.listExtraInfo() ) { Catch::cout() << " " << testCaseInfo.lineInfo << std::endl; std::string description = testCaseInfo.description; if( description.empty() ) description = "(NO DESCRIPTION)"; Catch::cout() << Text( description, descAttr ) << std::endl; } if( !testCaseInfo.tags.empty() ) Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; } if( !config.testSpec().hasFilters() ) Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl; else Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl; return matchedTests; } inline std::size_t listTestsNamesOnly( Config const& config ) { TestSpec testSpec = config.testSpec(); if( !config.testSpec().hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); std::size_t matchedTests = 0; std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { matchedTests++; TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); if( startsWith( testCaseInfo.name, '#' ) ) Catch::cout() << '"' << testCaseInfo.name << '"'; else Catch::cout() << testCaseInfo.name; if ( config.listExtraInfo() ) Catch::cout() << "\t@" << testCaseInfo.lineInfo; Catch::cout() << std::endl; } return matchedTests; } struct TagInfo { TagInfo() : count ( 0 ) {} void add( std::string const& spelling ) { ++count; spellings.insert( spelling ); } std::string all() const { std::string out; for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); it != itEnd; ++it ) out += "[" + *it + "]"; return out; } std::set spellings; std::size_t count; }; inline std::size_t listTags( Config const& config ) { TestSpec testSpec = config.testSpec(); if( config.testSpec().hasFilters() ) Catch::cout() << "Tags for matching test cases:\n"; else { Catch::cout() << "All available tags:\n"; testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); } std::map tagCounts; std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), tagItEnd = it->getTestCaseInfo().tags.end(); tagIt != tagItEnd; ++tagIt ) { std::string tagName = *tagIt; std::string lcaseTagName = toLower( tagName ); std::map::iterator countIt = tagCounts.find( lcaseTagName ); if( countIt == tagCounts.end() ) countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; countIt->second.add( tagName ); } } for( std::map::const_iterator countIt = tagCounts.begin(), countItEnd = tagCounts.end(); countIt != countItEnd; ++countIt ) { std::ostringstream oss; oss << " " << std::setw(2) << countIt->second.count << " "; Text wrapper( countIt->second.all(), TextAttributes() .setInitialIndent( 0 ) .setIndent( oss.str().size() ) .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); Catch::cout() << oss.str() << wrapper << '\n'; } Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; return tagCounts.size(); } inline std::size_t listReporters( Config const& /*config*/ ) { Catch::cout() << "Available reporters:\n"; IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; std::size_t maxNameLen = 0; for(it = itBegin; it != itEnd; ++it ) maxNameLen = (std::max)( maxNameLen, it->first.size() ); for(it = itBegin; it != itEnd; ++it ) { Text wrapper( it->second->getDescription(), TextAttributes() .setInitialIndent( 0 ) .setIndent( 7+maxNameLen ) .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); Catch::cout() << " " << it->first << ':' << std::string( maxNameLen - it->first.size() + 2, ' ' ) << wrapper << '\n'; } Catch::cout() << std::endl; return factories.size(); } inline Option list( Config const& config ) { Option listedCount; if( config.listTests() || ( config.listExtraInfo() && !config.listTestNamesOnly() ) ) listedCount = listedCount.valueOr(0) + listTests( config ); if( config.listTestNamesOnly() ) listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); if( config.listTags() ) listedCount = listedCount.valueOr(0) + listTags( config ); if( config.listReporters() ) listedCount = listedCount.valueOr(0) + listReporters( config ); return listedCount; } } // end namespace Catch // #included from: internal/catch_run_context.hpp #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED // #included from: catch_test_case_tracker.hpp #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED #include #include #include #include #include CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS namespace Catch { namespace TestCaseTracking { struct NameAndLocation { std::string name; SourceLineInfo location; NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) : name( _name ), location( _location ) {} }; struct ITracker : SharedImpl<> { virtual ~ITracker(); // static queries virtual NameAndLocation const& nameAndLocation() const = 0; // dynamic queries virtual bool isComplete() const = 0; // Successfully completed or failed virtual bool isSuccessfullyCompleted() const = 0; virtual bool isOpen() const = 0; // Started but not complete virtual bool hasChildren() const = 0; virtual ITracker& parent() = 0; // actions virtual void close() = 0; // Successfully complete virtual void fail() = 0; virtual void markAsNeedingAnotherRun() = 0; virtual void addChild( Ptr const& child ) = 0; virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0; virtual void openChild() = 0; // Debug/ checking virtual bool isSectionTracker() const = 0; virtual bool isIndexTracker() const = 0; }; class TrackerContext { enum RunState { NotStarted, Executing, CompletedCycle }; Ptr m_rootTracker; ITracker* m_currentTracker; RunState m_runState; public: static TrackerContext& instance() { static TrackerContext s_instance; return s_instance; } TrackerContext() : m_currentTracker( CATCH_NULL ), m_runState( NotStarted ) {} ITracker& startRun(); void endRun() { m_rootTracker.reset(); m_currentTracker = CATCH_NULL; m_runState = NotStarted; } void startCycle() { m_currentTracker = m_rootTracker.get(); m_runState = Executing; } void completeCycle() { m_runState = CompletedCycle; } bool completedCycle() const { return m_runState == CompletedCycle; } ITracker& currentTracker() { return *m_currentTracker; } void setCurrentTracker( ITracker* tracker ) { m_currentTracker = tracker; } }; class TrackerBase : public ITracker { protected: enum CycleState { NotStarted, Executing, ExecutingChildren, NeedsAnotherRun, CompletedSuccessfully, Failed }; class TrackerHasName { NameAndLocation m_nameAndLocation; public: TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} bool operator ()( Ptr const& tracker ) { return tracker->nameAndLocation().name == m_nameAndLocation.name && tracker->nameAndLocation().location == m_nameAndLocation.location; } }; typedef std::vector > Children; NameAndLocation m_nameAndLocation; TrackerContext& m_ctx; ITracker* m_parent; Children m_children; CycleState m_runState; public: TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) : m_nameAndLocation( nameAndLocation ), m_ctx( ctx ), m_parent( parent ), m_runState( NotStarted ) {} virtual ~TrackerBase(); virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE { return m_nameAndLocation; } virtual bool isComplete() const CATCH_OVERRIDE { return m_runState == CompletedSuccessfully || m_runState == Failed; } virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { return m_runState == CompletedSuccessfully; } virtual bool isOpen() const CATCH_OVERRIDE { return m_runState != NotStarted && !isComplete(); } virtual bool hasChildren() const CATCH_OVERRIDE { return !m_children.empty(); } virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { m_children.push_back( child ); } virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE { Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); return( it != m_children.end() ) ? it->get() : CATCH_NULL; } virtual ITracker& parent() CATCH_OVERRIDE { assert( m_parent ); // Should always be non-null except for root return *m_parent; } virtual void openChild() CATCH_OVERRIDE { if( m_runState != ExecutingChildren ) { m_runState = ExecutingChildren; if( m_parent ) m_parent->openChild(); } } virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } void open() { m_runState = Executing; moveToThis(); if( m_parent ) m_parent->openChild(); } virtual void close() CATCH_OVERRIDE { // Close any still open children (e.g. generators) while( &m_ctx.currentTracker() != this ) m_ctx.currentTracker().close(); switch( m_runState ) { case NotStarted: case CompletedSuccessfully: case Failed: throw std::logic_error( "Illogical state" ); case NeedsAnotherRun: break;; case Executing: m_runState = CompletedSuccessfully; break; case ExecutingChildren: if( m_children.empty() || m_children.back()->isComplete() ) m_runState = CompletedSuccessfully; break; default: throw std::logic_error( "Unexpected state" ); } moveToParent(); m_ctx.completeCycle(); } virtual void fail() CATCH_OVERRIDE { m_runState = Failed; if( m_parent ) m_parent->markAsNeedingAnotherRun(); moveToParent(); m_ctx.completeCycle(); } virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { m_runState = NeedsAnotherRun; } private: void moveToParent() { assert( m_parent ); m_ctx.setCurrentTracker( m_parent ); } void moveToThis() { m_ctx.setCurrentTracker( this ); } }; class SectionTracker : public TrackerBase { std::vector m_filters; public: SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) : TrackerBase( nameAndLocation, ctx, parent ) { if( parent ) { while( !parent->isSectionTracker() ) parent = &parent->parent(); SectionTracker& parentSection = static_cast( *parent ); addNextFilters( parentSection.m_filters ); } } virtual ~SectionTracker(); virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { SectionTracker* section = CATCH_NULL; ITracker& currentTracker = ctx.currentTracker(); if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { assert( childTracker ); assert( childTracker->isSectionTracker() ); section = static_cast( childTracker ); } else { section = new SectionTracker( nameAndLocation, ctx, ¤tTracker ); currentTracker.addChild( section ); } if( !ctx.completedCycle() ) section->tryOpen(); return *section; } void tryOpen() { if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) open(); } void addInitialFilters( std::vector const& filters ) { if( !filters.empty() ) { m_filters.push_back(""); // Root - should never be consulted m_filters.push_back(""); // Test Case - not a section filter m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); } } void addNextFilters( std::vector const& filters ) { if( filters.size() > 1 ) m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); } }; class IndexTracker : public TrackerBase { int m_size; int m_index; public: IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) : TrackerBase( nameAndLocation, ctx, parent ), m_size( size ), m_index( -1 ) {} virtual ~IndexTracker(); virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { IndexTracker* tracker = CATCH_NULL; ITracker& currentTracker = ctx.currentTracker(); if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { assert( childTracker ); assert( childTracker->isIndexTracker() ); tracker = static_cast( childTracker ); } else { tracker = new IndexTracker( nameAndLocation, ctx, ¤tTracker, size ); currentTracker.addChild( tracker ); } if( !ctx.completedCycle() && !tracker->isComplete() ) { if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) tracker->moveNext(); tracker->open(); } return *tracker; } int index() const { return m_index; } void moveNext() { m_index++; m_children.clear(); } virtual void close() CATCH_OVERRIDE { TrackerBase::close(); if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) m_runState = Executing; } }; inline ITracker& TrackerContext::startRun() { m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL ); m_currentTracker = CATCH_NULL; m_runState = Executing; return *m_rootTracker; } } // namespace TestCaseTracking using TestCaseTracking::ITracker; using TestCaseTracking::TrackerContext; using TestCaseTracking::SectionTracker; using TestCaseTracking::IndexTracker; } // namespace Catch CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS // #included from: catch_fatal_condition.hpp #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED namespace Catch { // Report the error condition inline void reportFatal( std::string const& message ) { IContext& context = Catch::getCurrentContext(); IResultCapture* resultCapture = context.getResultCapture(); resultCapture->handleFatalErrorCondition( message ); } } // namespace Catch #if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// // #included from: catch_windows_h_proxy.h #define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED #ifdef CATCH_DEFINES_NOMINMAX # define NOMINMAX #endif #ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif #ifdef __AFXDLL #include #else #include #endif #ifdef CATCH_DEFINES_NOMINMAX # undef NOMINMAX #endif #ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN # undef WIN32_LEAN_AND_MEAN #endif # if !defined ( CATCH_CONFIG_WINDOWS_SEH ) namespace Catch { struct FatalConditionHandler { void reset() {} }; } # else // CATCH_CONFIG_WINDOWS_SEH is defined namespace Catch { struct SignalDefs { DWORD id; const char* name; }; extern SignalDefs signalDefs[]; // There is no 1-1 mapping between signals and windows exceptions. // Windows can easily distinguish between SO and SigSegV, // but SigInt, SigTerm, etc are handled differently. SignalDefs signalDefs[] = { { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, }; struct FatalConditionHandler { static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { reportFatal(signalDefs[i].name); } } // If its not an exception we care about, pass it along. // This stops us from eating debugger breaks etc. return EXCEPTION_CONTINUE_SEARCH; } FatalConditionHandler() { isSet = true; // 32k seems enough for Catch to handle stack overflow, // but the value was found experimentally, so there is no strong guarantee guaranteeSize = 32 * 1024; exceptionHandlerHandle = CATCH_NULL; // Register as first handler in current chain exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); // Pass in guarantee size to be filled SetThreadStackGuarantee(&guaranteeSize); } static void reset() { if (isSet) { // Unregister handler and restore the old guarantee RemoveVectoredExceptionHandler(exceptionHandlerHandle); SetThreadStackGuarantee(&guaranteeSize); exceptionHandlerHandle = CATCH_NULL; isSet = false; } } ~FatalConditionHandler() { reset(); } private: static bool isSet; static ULONG guaranteeSize; static PVOID exceptionHandlerHandle; }; bool FatalConditionHandler::isSet = false; ULONG FatalConditionHandler::guaranteeSize = 0; PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL; } // namespace Catch # endif // CATCH_CONFIG_WINDOWS_SEH #else // Not Windows - assumed to be POSIX compatible ////////////////////////// # if !defined(CATCH_CONFIG_POSIX_SIGNALS) namespace Catch { struct FatalConditionHandler { void reset() {} }; } # else // CATCH_CONFIG_POSIX_SIGNALS is defined #include namespace Catch { struct SignalDefs { int id; const char* name; }; extern SignalDefs signalDefs[]; SignalDefs signalDefs[] = { { SIGINT, "SIGINT - Terminal interrupt signal" }, { SIGILL, "SIGILL - Illegal instruction signal" }, { SIGFPE, "SIGFPE - Floating point error signal" }, { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, { SIGTERM, "SIGTERM - Termination request signal" }, { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } }; struct FatalConditionHandler { static bool isSet; static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)]; static stack_t oldSigStack; static char altStackMem[SIGSTKSZ]; static void handleSignal( int sig ) { std::string name = ""; for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { SignalDefs &def = signalDefs[i]; if (sig == def.id) { name = def.name; break; } } reset(); reportFatal(name); raise( sig ); } FatalConditionHandler() { isSet = true; stack_t sigStack; sigStack.ss_sp = altStackMem; sigStack.ss_size = SIGSTKSZ; sigStack.ss_flags = 0; sigaltstack(&sigStack, &oldSigStack); struct sigaction sa = { 0 }; sa.sa_handler = handleSignal; sa.sa_flags = SA_ONSTACK; for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); } } ~FatalConditionHandler() { reset(); } static void reset() { if( isSet ) { // Set signals back to previous values -- hopefully nobody overwrote them in the meantime for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL); } // Return the old stack sigaltstack(&oldSigStack, CATCH_NULL); isSet = false; } } }; bool FatalConditionHandler::isSet = false; struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; stack_t FatalConditionHandler::oldSigStack = {}; char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; } // namespace Catch # endif // CATCH_CONFIG_POSIX_SIGNALS #endif // not Windows #include #include namespace Catch { class StreamRedirect { public: StreamRedirect( std::ostream& stream, std::string& targetString ) : m_stream( stream ), m_prevBuf( stream.rdbuf() ), m_targetString( targetString ) { stream.rdbuf( m_oss.rdbuf() ); } ~StreamRedirect() { m_targetString += m_oss.str(); m_stream.rdbuf( m_prevBuf ); } private: std::ostream& m_stream; std::streambuf* m_prevBuf; std::ostringstream m_oss; std::string& m_targetString; }; // StdErr has two constituent streams in C++, std::cerr and std::clog // This means that we need to redirect 2 streams into 1 to keep proper // order of writes and cannot use StreamRedirect on its own class StdErrRedirect { public: StdErrRedirect(std::string& targetString) :m_cerrBuf( cerr().rdbuf() ), m_clogBuf(clog().rdbuf()), m_targetString(targetString){ cerr().rdbuf(m_oss.rdbuf()); clog().rdbuf(m_oss.rdbuf()); } ~StdErrRedirect() { m_targetString += m_oss.str(); cerr().rdbuf(m_cerrBuf); clog().rdbuf(m_clogBuf); } private: std::streambuf* m_cerrBuf; std::streambuf* m_clogBuf; std::ostringstream m_oss; std::string& m_targetString; }; /////////////////////////////////////////////////////////////////////////// class RunContext : public IResultCapture, public IRunner { RunContext( RunContext const& ); void operator =( RunContext const& ); public: explicit RunContext( Ptr const& _config, Ptr const& reporter ) : m_runInfo( _config->name() ), m_context( getCurrentMutableContext() ), m_activeTestCase( CATCH_NULL ), m_config( _config ), m_reporter( reporter ), m_shouldReportUnexpected ( true ) { m_context.setRunner( this ); m_context.setConfig( m_config ); m_context.setResultCapture( this ); m_reporter->testRunStarting( m_runInfo ); } virtual ~RunContext() { m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); } void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); } void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); } Totals runTest( TestCase const& testCase ) { Totals prevTotals = m_totals; std::string redirectedCout; std::string redirectedCerr; TestCaseInfo testInfo = testCase.getTestCaseInfo(); m_reporter->testCaseStarting( testInfo ); m_activeTestCase = &testCase; do { ITracker& rootTracker = m_trackerContext.startRun(); assert( rootTracker.isSectionTracker() ); static_cast( rootTracker ).addInitialFilters( m_config->getSectionsToRun() ); do { m_trackerContext.startCycle(); m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) ); runCurrentTest( redirectedCout, redirectedCerr ); } while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); } // !TBD: deprecated - this will be replaced by indexed trackers while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); Totals deltaTotals = m_totals.delta( prevTotals ); if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { deltaTotals.assertions.failed++; deltaTotals.testCases.passed--; deltaTotals.testCases.failed++; } m_totals.testCases += deltaTotals.testCases; m_reporter->testCaseEnded( TestCaseStats( testInfo, deltaTotals, redirectedCout, redirectedCerr, aborting() ) ); m_activeTestCase = CATCH_NULL; m_testCaseTracker = CATCH_NULL; return deltaTotals; } Ptr config() const { return m_config; } private: // IResultCapture virtual void assertionEnded( AssertionResult const& result ) { if( result.getResultType() == ResultWas::Ok ) { m_totals.assertions.passed++; } else if( !result.isOk() ) { if( m_activeTestCase->getTestCaseInfo().okToFail() ) m_totals.assertions.failedButOk++; else m_totals.assertions.failed++; } // We have no use for the return value (whether messages should be cleared), because messages were made scoped // and should be let to clear themselves out. static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); // Reset working state m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); m_lastResult = result; } virtual bool lastAssertionPassed() { return m_totals.assertions.passed == (m_prevPassed + 1); } virtual void assertionPassed() { m_totals.assertions.passed++; m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"; m_lastAssertionInfo.macroName = ""; } virtual void assertionRun() { m_prevPassed = m_totals.assertions.passed; } virtual bool sectionStarted ( SectionInfo const& sectionInfo, Counts& assertions ) { ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) ); if( !sectionTracker.isOpen() ) return false; m_activeSections.push_back( §ionTracker ); m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; m_reporter->sectionStarting( sectionInfo ); assertions = m_totals.assertions; return true; } bool testForMissingAssertions( Counts& assertions ) { if( assertions.total() != 0 ) return false; if( !m_config->warnAboutMissingAssertions() ) return false; if( m_trackerContext.currentTracker().hasChildren() ) return false; m_totals.assertions.failed++; assertions.failed++; return true; } virtual void sectionEnded( SectionEndInfo const& endInfo ) { Counts assertions = m_totals.assertions - endInfo.prevAssertions; bool missingAssertions = testForMissingAssertions( assertions ); if( !m_activeSections.empty() ) { m_activeSections.back()->close(); m_activeSections.pop_back(); } m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); m_messages.clear(); } virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { if( m_unfinishedSections.empty() ) m_activeSections.back()->fail(); else m_activeSections.back()->close(); m_activeSections.pop_back(); m_unfinishedSections.push_back( endInfo ); } virtual void pushScopedMessage( MessageInfo const& message ) { m_messages.push_back( message ); } virtual void popScopedMessage( MessageInfo const& message ) { m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); } virtual std::string getCurrentTestName() const { return m_activeTestCase ? m_activeTestCase->getTestCaseInfo().name : std::string(); } virtual const AssertionResult* getLastResult() const { return &m_lastResult; } virtual void exceptionEarlyReported() { m_shouldReportUnexpected = false; } virtual void handleFatalErrorCondition( std::string const& message ) { // Don't rebuild the result -- the stringification itself can cause more fatal errors // Instead, fake a result data. AssertionResultData tempResult; tempResult.resultType = ResultWas::FatalErrorCondition; tempResult.message = message; AssertionResult result(m_lastAssertionInfo, tempResult); getResultCapture().assertionEnded(result); handleUnfinishedSections(); // Recreate section for test case (as we will lose the one that was in scope) TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); Counts assertions; assertions.failed = 1; SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); m_reporter->sectionEnded( testCaseSectionStats ); TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); Totals deltaTotals; deltaTotals.testCases.failed = 1; deltaTotals.assertions.failed = 1; m_reporter->testCaseEnded( TestCaseStats( testInfo, deltaTotals, std::string(), std::string(), false ) ); m_totals.testCases.failed++; testGroupEnded( std::string(), m_totals, 1, 1 ); m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); } public: // !TBD We need to do this another way! bool aborting() const { return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); } private: void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); m_reporter->sectionStarting( testCaseSection ); Counts prevAssertions = m_totals.assertions; double duration = 0; m_shouldReportUnexpected = true; try { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); seedRng( *m_config ); Timer timer; timer.start(); if( m_reporter->getPreferences().shouldRedirectStdOut ) { StreamRedirect coutRedir( Catch::cout(), redirectedCout ); StdErrRedirect errRedir( redirectedCerr ); invokeActiveTestCase(); } else { invokeActiveTestCase(); } duration = timer.getElapsedSeconds(); } catch( TestFailureException& ) { // This just means the test was aborted due to failure } catch(...) { // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions // are reported without translation at the point of origin. if (m_shouldReportUnexpected) { makeUnexpectedResultBuilder().useActiveException(); } } m_testCaseTracker->close(); handleUnfinishedSections(); m_messages.clear(); Counts assertions = m_totals.assertions - prevAssertions; bool missingAssertions = testForMissingAssertions( assertions ); SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); m_reporter->sectionEnded( testCaseSectionStats ); } void invokeActiveTestCase() { FatalConditionHandler fatalConditionHandler; // Handle signals m_activeTestCase->invoke(); fatalConditionHandler.reset(); } private: ResultBuilder makeUnexpectedResultBuilder() const { return ResultBuilder( m_lastAssertionInfo.macroName, m_lastAssertionInfo.lineInfo, m_lastAssertionInfo.capturedExpression, m_lastAssertionInfo.resultDisposition ); } void handleUnfinishedSections() { // If sections ended prematurely due to an exception we stored their // infos here so we can tear them down outside the unwind process. for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), itEnd = m_unfinishedSections.rend(); it != itEnd; ++it ) sectionEnded( *it ); m_unfinishedSections.clear(); } TestRunInfo m_runInfo; IMutableContext& m_context; TestCase const* m_activeTestCase; ITracker* m_testCaseTracker; ITracker* m_currentSectionTracker; AssertionResult m_lastResult; Ptr m_config; Totals m_totals; Ptr m_reporter; std::vector m_messages; AssertionInfo m_lastAssertionInfo; std::vector m_unfinishedSections; std::vector m_activeSections; TrackerContext m_trackerContext; size_t m_prevPassed; bool m_shouldReportUnexpected; }; IResultCapture& getResultCapture() { if( IResultCapture* capture = getCurrentContext().getResultCapture() ) return *capture; else throw std::logic_error( "No result capture instance" ); } } // end namespace Catch // #included from: internal/catch_version.h #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED namespace Catch { // Versioning information struct Version { Version( unsigned int _majorVersion, unsigned int _minorVersion, unsigned int _patchNumber, char const * const _branchName, unsigned int _buildNumber ); unsigned int const majorVersion; unsigned int const minorVersion; unsigned int const patchNumber; // buildNumber is only used if branchName is not null char const * const branchName; unsigned int const buildNumber; friend std::ostream& operator << ( std::ostream& os, Version const& version ); private: void operator=( Version const& ); }; inline Version libraryVersion(); } #include #include #include namespace Catch { Ptr createReporter( std::string const& reporterName, Ptr const& config ) { Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); if( !reporter ) { std::ostringstream oss; oss << "No reporter registered with name: '" << reporterName << "'"; throw std::domain_error( oss.str() ); } return reporter; } #if !defined(CATCH_CONFIG_DEFAULT_REPORTER) #define CATCH_CONFIG_DEFAULT_REPORTER "console" #endif Ptr makeReporter( Ptr const& config ) { std::vector reporters = config->getReporterNames(); if( reporters.empty() ) reporters.push_back( CATCH_CONFIG_DEFAULT_REPORTER ); Ptr reporter; for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); it != itEnd; ++it ) reporter = addReporter( reporter, createReporter( *it, config ) ); return reporter; } Ptr addListeners( Ptr const& config, Ptr reporters ) { IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); it != itEnd; ++it ) reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); return reporters; } Totals runTests( Ptr const& config ) { Ptr iconfig = config.get(); Ptr reporter = makeReporter( config ); reporter = addListeners( iconfig, reporter ); RunContext context( iconfig, reporter ); Totals totals; context.testGroupStarting( config->name(), 1, 1 ); TestSpec testSpec = config->testSpec(); if( !testSpec.hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); it != itEnd; ++it ) { if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) totals += context.runTest( *it ); else reporter->skipTest( *it ); } context.testGroupEnded( iconfig->name(), totals, 1, 1 ); return totals; } void applyFilenamesAsTags( IConfig const& config ) { std::vector const& tests = getAllTestCasesSorted( config ); for(std::size_t i = 0; i < tests.size(); ++i ) { TestCase& test = const_cast( tests[i] ); std::set tags = test.tags; std::string filename = test.lineInfo.file; std::string::size_type lastSlash = filename.find_last_of( "\\/" ); if( lastSlash != std::string::npos ) filename = filename.substr( lastSlash+1 ); std::string::size_type lastDot = filename.find_last_of( '.' ); if( lastDot != std::string::npos ) filename = filename.substr( 0, lastDot ); tags.insert( '#' + filename ); setTags( test, tags ); } } class Session : NonCopyable { static bool alreadyInstantiated; public: struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; Session() : m_cli( makeCommandLineParser() ) { if( alreadyInstantiated ) { std::string msg = "Only one instance of Catch::Session can ever be used"; Catch::cerr() << msg << std::endl; throw std::logic_error( msg ); } alreadyInstantiated = true; } ~Session() { Catch::cleanUp(); } void showHelp( std::string const& processName ) { Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; m_cli.usage( Catch::cout(), processName ); Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; } void libIdentify() { Catch::cout() << std::left << std::setw(16) << "description: " << "A Catch test executable\n" << std::left << std::setw(16) << "category: " << "testframework\n" << std::left << std::setw(16) << "framework: " << "Catch Test\n" << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; } int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { try { m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); if( m_configData.showHelp ) showHelp( m_configData.processName ); if( m_configData.libIdentify ) libIdentify(); m_config.reset(); } catch( std::exception& ex ) { { Colour colourGuard( Colour::Red ); Catch::cerr() << "\nError(s) in input:\n" << Text( ex.what(), TextAttributes().setIndent(2) ) << "\n\n"; } m_cli.usage( Catch::cout(), m_configData.processName ); return (std::numeric_limits::max)(); } return 0; } void useConfigData( ConfigData const& _configData ) { m_configData = _configData; m_config.reset(); } int run( int argc, char const* const* const argv ) { int returnCode = applyCommandLine( argc, argv ); if( returnCode == 0 ) returnCode = run(); return returnCode; } #if defined(WIN32) && defined(UNICODE) int run( int argc, wchar_t const* const* const argv ) { char **utf8Argv = new char *[ argc ]; for ( int i = 0; i < argc; ++i ) { int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); utf8Argv[ i ] = new char[ bufSize ]; WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); } int returnCode = applyCommandLine( argc, utf8Argv ); if( returnCode == 0 ) returnCode = run(); for ( int i = 0; i < argc; ++i ) delete [] utf8Argv[ i ]; delete [] utf8Argv; return returnCode; } #endif int run() { if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { Catch::cout() << "...waiting for enter/ return before starting" << std::endl; static_cast(std::getchar()); } int exitCode = runInternal(); if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; static_cast(std::getchar()); } return exitCode; } Clara::CommandLine const& cli() const { return m_cli; } std::vector const& unusedTokens() const { return m_unusedTokens; } ConfigData& configData() { return m_configData; } Config& config() { if( !m_config ) m_config = new Config( m_configData ); return *m_config; } private: int runInternal() { if( m_configData.showHelp || m_configData.libIdentify ) return 0; try { config(); // Force config to be constructed seedRng( *m_config ); if( m_configData.filenamesAsTags ) applyFilenamesAsTags( *m_config ); // Handle list request if( Option listed = list( config() ) ) return static_cast( *listed ); return static_cast( runTests( m_config ).assertions.failed ); } catch( std::exception& ex ) { Catch::cerr() << ex.what() << std::endl; return (std::numeric_limits::max)(); } } Clara::CommandLine m_cli; std::vector m_unusedTokens; ConfigData m_configData; Ptr m_config; }; bool Session::alreadyInstantiated = false; } // end namespace Catch // #included from: catch_registry_hub.hpp #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED // #included from: catch_test_case_registry_impl.hpp #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED #include #include #include #include namespace Catch { struct RandomNumberGenerator { typedef std::ptrdiff_t result_type; result_type operator()( result_type n ) const { return std::rand() % n; } #ifdef CATCH_CONFIG_CPP11_SHUFFLE static constexpr result_type min() { return 0; } static constexpr result_type max() { return 1000000; } result_type operator()() const { return std::rand() % max(); } #endif template static void shuffle( V& vector ) { RandomNumberGenerator rng; #ifdef CATCH_CONFIG_CPP11_SHUFFLE std::shuffle( vector.begin(), vector.end(), rng ); #else std::random_shuffle( vector.begin(), vector.end(), rng ); #endif } }; inline std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { std::vector sorted = unsortedTestCases; switch( config.runOrder() ) { case RunTests::InLexicographicalOrder: std::sort( sorted.begin(), sorted.end() ); break; case RunTests::InRandomOrder: { seedRng( config ); RandomNumberGenerator::shuffle( sorted ); } break; case RunTests::InDeclarationOrder: // already in declaration order break; } return sorted; } bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); } void enforceNoDuplicateTestCases( std::vector const& functions ) { std::set seenFunctions; for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); it != itEnd; ++it ) { std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); if( !prev.second ) { std::ostringstream ss; ss << Colour( Colour::Red ) << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n' << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; throw std::runtime_error(ss.str()); } } } std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { std::vector filtered; filtered.reserve( testCases.size() ); for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); it != itEnd; ++it ) if( matchTest( *it, testSpec, config ) ) filtered.push_back( *it ); return filtered; } std::vector const& getAllTestCasesSorted( IConfig const& config ) { return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); } class TestRegistry : public ITestCaseRegistry { public: TestRegistry() : m_currentSortOrder( RunTests::InDeclarationOrder ), m_unnamedCount( 0 ) {} virtual ~TestRegistry(); virtual void registerTest( TestCase const& testCase ) { std::string name = testCase.getTestCaseInfo().name; if( name.empty() ) { std::ostringstream oss; oss << "Anonymous test case " << ++m_unnamedCount; return registerTest( testCase.withName( oss.str() ) ); } m_functions.push_back( testCase ); } virtual std::vector const& getAllTests() const { return m_functions; } virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { if( m_sortedFunctions.empty() ) enforceNoDuplicateTestCases( m_functions ); if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { m_sortedFunctions = sortTests( config, m_functions ); m_currentSortOrder = config.runOrder(); } return m_sortedFunctions; } private: std::vector m_functions; mutable RunTests::InWhatOrder m_currentSortOrder; mutable std::vector m_sortedFunctions; size_t m_unnamedCount; std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; /////////////////////////////////////////////////////////////////////////// class FreeFunctionTestCase : public SharedImpl { public: FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} virtual void invoke() const { m_fun(); } private: virtual ~FreeFunctionTestCase(); TestFunction m_fun; }; inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { std::string className = classOrQualifiedMethodName; if( startsWith( className, '&' ) ) { std::size_t lastColons = className.rfind( "::" ); std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); if( penultimateColons == std::string::npos ) penultimateColons = 1; className = className.substr( penultimateColons, lastColons-penultimateColons ); } return className; } void registerTestCase ( ITestCase* testCase, char const* classOrQualifiedMethodName, NameAndDesc const& nameAndDesc, SourceLineInfo const& lineInfo ) { getMutableRegistryHub().registerTest ( makeTestCase ( testCase, extractClassName( classOrQualifiedMethodName ), nameAndDesc.name, nameAndDesc.description, lineInfo ) ); } void registerTestCaseFunction ( TestFunction function, SourceLineInfo const& lineInfo, NameAndDesc const& nameAndDesc ) { registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); } /////////////////////////////////////////////////////////////////////////// AutoReg::AutoReg ( TestFunction function, SourceLineInfo const& lineInfo, NameAndDesc const& nameAndDesc ) { registerTestCaseFunction( function, lineInfo, nameAndDesc ); } AutoReg::~AutoReg() {} } // end namespace Catch // #included from: catch_reporter_registry.hpp #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED #include namespace Catch { class ReporterRegistry : public IReporterRegistry { public: virtual ~ReporterRegistry() CATCH_OVERRIDE {} virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) return CATCH_NULL; return it->second->create( ReporterConfig( config ) ); } void registerReporter( std::string const& name, Ptr const& factory ) { m_factories.insert( std::make_pair( name, factory ) ); } void registerListener( Ptr const& factory ) { m_listeners.push_back( factory ); } virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { return m_factories; } virtual Listeners const& getListeners() const CATCH_OVERRIDE { return m_listeners; } private: FactoryMap m_factories; Listeners m_listeners; }; } // #included from: catch_exception_translator_registry.hpp #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED #ifdef __OBJC__ #import "Foundation/Foundation.h" #endif namespace Catch { class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { public: ~ExceptionTranslatorRegistry() { deleteAll( m_translators ); } virtual void registerTranslator( const IExceptionTranslator* translator ) { m_translators.push_back( translator ); } virtual std::string translateActiveException() const { try { #ifdef __OBJC__ // In Objective-C try objective-c exceptions first @try { return tryTranslators(); } @catch (NSException *exception) { return Catch::toString( [exception description] ); } #else return tryTranslators(); #endif } catch( TestFailureException& ) { throw; } catch( std::exception& ex ) { return ex.what(); } catch( std::string& msg ) { return msg; } catch( const char* msg ) { return msg; } catch(...) { return "Unknown exception"; } } std::string tryTranslators() const { if( m_translators.empty() ) throw; else return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); } private: std::vector m_translators; }; } // #included from: catch_tag_alias_registry.h #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED #include namespace Catch { class TagAliasRegistry : public ITagAliasRegistry { public: virtual ~TagAliasRegistry(); virtual Option find( std::string const& alias ) const; virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); private: std::map m_registry; }; } // end namespace Catch namespace Catch { namespace { class RegistryHub : public IRegistryHub, public IMutableRegistryHub { RegistryHub( RegistryHub const& ); void operator=( RegistryHub const& ); public: // IRegistryHub RegistryHub() { } virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { return m_reporterRegistry; } virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { return m_testCaseRegistry; } virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { return m_exceptionTranslatorRegistry; } virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE { return m_tagAliasRegistry; } public: // IMutableRegistryHub virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { m_reporterRegistry.registerReporter( name, factory ); } virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { m_reporterRegistry.registerListener( factory ); } virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { m_testCaseRegistry.registerTest( testInfo ); } virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { m_exceptionTranslatorRegistry.registerTranslator( translator ); } virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE { m_tagAliasRegistry.add( alias, tag, lineInfo ); } private: TestRegistry m_testCaseRegistry; ReporterRegistry m_reporterRegistry; ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; TagAliasRegistry m_tagAliasRegistry; }; // Single, global, instance inline RegistryHub*& getTheRegistryHub() { static RegistryHub* theRegistryHub = CATCH_NULL; if( !theRegistryHub ) theRegistryHub = new RegistryHub(); return theRegistryHub; } } IRegistryHub& getRegistryHub() { return *getTheRegistryHub(); } IMutableRegistryHub& getMutableRegistryHub() { return *getTheRegistryHub(); } void cleanUp() { delete getTheRegistryHub(); getTheRegistryHub() = CATCH_NULL; cleanUpContext(); } std::string translateActiveException() { return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); } } // end namespace Catch // #included from: catch_notimplemented_exception.hpp #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED #include namespace Catch { NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) : m_lineInfo( lineInfo ) { std::ostringstream oss; oss << lineInfo << ": function "; oss << "not implemented"; m_what = oss.str(); } const char* NotImplementedException::what() const CATCH_NOEXCEPT { return m_what.c_str(); } } // end namespace Catch // #included from: catch_context_impl.hpp #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED // #included from: catch_stream.hpp #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED #include #include #include namespace Catch { template class StreamBufImpl : public StreamBufBase { char data[bufferSize]; WriterF m_writer; public: StreamBufImpl() { setp( data, data + sizeof(data) ); } ~StreamBufImpl() CATCH_NOEXCEPT { sync(); } private: int overflow( int c ) { sync(); if( c != EOF ) { if( pbase() == epptr() ) m_writer( std::string( 1, static_cast( c ) ) ); else sputc( static_cast( c ) ); } return 0; } int sync() { if( pbase() != pptr() ) { m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); setp( pbase(), epptr() ); } return 0; } }; /////////////////////////////////////////////////////////////////////////// FileStream::FileStream( std::string const& filename ) { m_ofs.open( filename.c_str() ); if( m_ofs.fail() ) { std::ostringstream oss; oss << "Unable to open file: '" << filename << '\''; throw std::domain_error( oss.str() ); } } std::ostream& FileStream::stream() const { return m_ofs; } struct OutputDebugWriter { void operator()( std::string const&str ) { writeToDebugConsole( str ); } }; DebugOutStream::DebugOutStream() : m_streamBuf( new StreamBufImpl() ), m_os( m_streamBuf.get() ) {} std::ostream& DebugOutStream::stream() const { return m_os; } // Store the streambuf from cout up-front because // cout may get redirected when running tests CoutStream::CoutStream() : m_os( Catch::cout().rdbuf() ) {} std::ostream& CoutStream::stream() const { return m_os; } #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions std::ostream& cout() { return std::cout; } std::ostream& cerr() { return std::cerr; } std::ostream& clog() { return std::clog; } #endif } namespace Catch { class Context : public IMutableContext { Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} Context( Context const& ); void operator=( Context const& ); public: virtual ~Context() { deleteAllValues( m_generatorsByTestName ); } public: // IContext virtual IResultCapture* getResultCapture() { return m_resultCapture; } virtual IRunner* getRunner() { return m_runner; } virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { return getGeneratorsForCurrentTest() .getGeneratorInfo( fileInfo, totalSize ) .getCurrentIndex(); } virtual bool advanceGeneratorsForCurrentTest() { IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); return generators && generators->moveNext(); } virtual Ptr getConfig() const { return m_config; } public: // IMutableContext virtual void setResultCapture( IResultCapture* resultCapture ) { m_resultCapture = resultCapture; } virtual void setRunner( IRunner* runner ) { m_runner = runner; } virtual void setConfig( Ptr const& config ) { m_config = config; } friend IMutableContext& getCurrentMutableContext(); private: IGeneratorsForTest* findGeneratorsForCurrentTest() { std::string testName = getResultCapture()->getCurrentTestName(); std::map::const_iterator it = m_generatorsByTestName.find( testName ); return it != m_generatorsByTestName.end() ? it->second : CATCH_NULL; } IGeneratorsForTest& getGeneratorsForCurrentTest() { IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); if( !generators ) { std::string testName = getResultCapture()->getCurrentTestName(); generators = createGeneratorsForTest(); m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); } return *generators; } private: Ptr m_config; IRunner* m_runner; IResultCapture* m_resultCapture; std::map m_generatorsByTestName; }; namespace { Context* currentContext = CATCH_NULL; } IMutableContext& getCurrentMutableContext() { if( !currentContext ) currentContext = new Context(); return *currentContext; } IContext& getCurrentContext() { return getCurrentMutableContext(); } void cleanUpContext() { delete currentContext; currentContext = CATCH_NULL; } } // #included from: catch_console_colour_impl.hpp #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED // #included from: catch_errno_guard.hpp #define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED #include namespace Catch { class ErrnoGuard { public: ErrnoGuard():m_oldErrno(errno){} ~ErrnoGuard() { errno = m_oldErrno; } private: int m_oldErrno; }; } namespace Catch { namespace { struct IColourImpl { virtual ~IColourImpl() {} virtual void use( Colour::Code _colourCode ) = 0; }; struct NoColourImpl : IColourImpl { void use( Colour::Code ) {} static IColourImpl* instance() { static NoColourImpl s_instance; return &s_instance; } }; } // anon namespace } // namespace Catch #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) # ifdef CATCH_PLATFORM_WINDOWS # define CATCH_CONFIG_COLOUR_WINDOWS # else # define CATCH_CONFIG_COLOUR_ANSI # endif #endif #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// namespace Catch { namespace { class Win32ColourImpl : public IColourImpl { public: Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) { CONSOLE_SCREEN_BUFFER_INFO csbiInfo; GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); } virtual void use( Colour::Code _colourCode ) { switch( _colourCode ) { case Colour::None: return setTextAttribute( originalForegroundAttributes ); case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); case Colour::Red: return setTextAttribute( FOREGROUND_RED ); case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); case Colour::Grey: return setTextAttribute( 0 ); case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); case Colour::Bright: throw std::logic_error( "not a colour" ); } } private: void setTextAttribute( WORD _textAttribute ) { SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); } HANDLE stdoutHandle; WORD originalForegroundAttributes; WORD originalBackgroundAttributes; }; IColourImpl* platformColourInstance() { static Win32ColourImpl s_instance; Ptr config = getCurrentContext().getConfig(); UseColour::YesOrNo colourMode = config ? config->useColour() : UseColour::Auto; if( colourMode == UseColour::Auto ) colourMode = !isDebuggerActive() ? UseColour::Yes : UseColour::No; return colourMode == UseColour::Yes ? &s_instance : NoColourImpl::instance(); } } // end anon namespace } // end namespace Catch #elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// #include namespace Catch { namespace { // use POSIX/ ANSI console terminal codes // Thanks to Adam Strzelecki for original contribution // (http://github.com/nanoant) // https://github.com/philsquared/Catch/pull/131 class PosixColourImpl : public IColourImpl { public: virtual void use( Colour::Code _colourCode ) { switch( _colourCode ) { case Colour::None: case Colour::White: return setColour( "[0m" ); case Colour::Red: return setColour( "[0;31m" ); case Colour::Green: return setColour( "[0;32m" ); case Colour::Blue: return setColour( "[0;34m" ); case Colour::Cyan: return setColour( "[0;36m" ); case Colour::Yellow: return setColour( "[0;33m" ); case Colour::Grey: return setColour( "[1;30m" ); case Colour::LightGrey: return setColour( "[0;37m" ); case Colour::BrightRed: return setColour( "[1;31m" ); case Colour::BrightGreen: return setColour( "[1;32m" ); case Colour::BrightWhite: return setColour( "[1;37m" ); case Colour::Bright: throw std::logic_error( "not a colour" ); } } static IColourImpl* instance() { static PosixColourImpl s_instance; return &s_instance; } private: void setColour( const char* _escapeCode ) { Catch::cout() << '\033' << _escapeCode; } }; IColourImpl* platformColourInstance() { ErrnoGuard guard; Ptr config = getCurrentContext().getConfig(); UseColour::YesOrNo colourMode = config ? config->useColour() : UseColour::Auto; if( colourMode == UseColour::Auto ) colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) ? UseColour::Yes : UseColour::No; return colourMode == UseColour::Yes ? PosixColourImpl::instance() : NoColourImpl::instance(); } } // end anon namespace } // end namespace Catch #else // not Windows or ANSI /////////////////////////////////////////////// namespace Catch { static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } } // end namespace Catch #endif // Windows/ ANSI/ None namespace Catch { Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } Colour::~Colour(){ if( !m_moved ) use( None ); } void Colour::use( Code _colourCode ) { static IColourImpl* impl = platformColourInstance(); impl->use( _colourCode ); } } // end namespace Catch // #included from: catch_generators_impl.hpp #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED #include #include #include namespace Catch { struct GeneratorInfo : IGeneratorInfo { GeneratorInfo( std::size_t size ) : m_size( size ), m_currentIndex( 0 ) {} bool moveNext() { if( ++m_currentIndex == m_size ) { m_currentIndex = 0; return false; } return true; } std::size_t getCurrentIndex() const { return m_currentIndex; } std::size_t m_size; std::size_t m_currentIndex; }; /////////////////////////////////////////////////////////////////////////// class GeneratorsForTest : public IGeneratorsForTest { public: ~GeneratorsForTest() { deleteAll( m_generatorsInOrder ); } IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { std::map::const_iterator it = m_generatorsByName.find( fileInfo ); if( it == m_generatorsByName.end() ) { IGeneratorInfo* info = new GeneratorInfo( size ); m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); m_generatorsInOrder.push_back( info ); return *info; } return *it->second; } bool moveNext() { std::vector::const_iterator it = m_generatorsInOrder.begin(); std::vector::const_iterator itEnd = m_generatorsInOrder.end(); for(; it != itEnd; ++it ) { if( (*it)->moveNext() ) return true; } return false; } private: std::map m_generatorsByName; std::vector m_generatorsInOrder; }; IGeneratorsForTest* createGeneratorsForTest() { return new GeneratorsForTest(); } } // end namespace Catch // #included from: catch_assertionresult.hpp #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED namespace Catch { AssertionInfo::AssertionInfo():macroName(""), capturedExpression(""), resultDisposition(ResultDisposition::Normal), secondArg(""){} AssertionInfo::AssertionInfo( char const * _macroName, SourceLineInfo const& _lineInfo, char const * _capturedExpression, ResultDisposition::Flags _resultDisposition, char const * _secondArg) : macroName( _macroName ), lineInfo( _lineInfo ), capturedExpression( _capturedExpression ), resultDisposition( _resultDisposition ), secondArg( _secondArg ) {} AssertionResult::AssertionResult() {} AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) : m_info( info ), m_resultData( data ) {} AssertionResult::~AssertionResult() {} // Result was a success bool AssertionResult::succeeded() const { return Catch::isOk( m_resultData.resultType ); } // Result was a success, or failure is suppressed bool AssertionResult::isOk() const { return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); } ResultWas::OfType AssertionResult::getResultType() const { return m_resultData.resultType; } bool AssertionResult::hasExpression() const { return m_info.capturedExpression[0] != 0; } bool AssertionResult::hasMessage() const { return !m_resultData.message.empty(); } std::string capturedExpressionWithSecondArgument( char const * capturedExpression, char const * secondArg ) { return (secondArg[0] == 0 || secondArg[0] == '"' && secondArg[1] == '"') ? capturedExpression : std::string(capturedExpression) + ", " + secondArg; } std::string AssertionResult::getExpression() const { if( isFalseTest( m_info.resultDisposition ) ) return '!' + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); else return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); } std::string AssertionResult::getExpressionInMacro() const { if( m_info.macroName[0] == 0 ) return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); else return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )"; } bool AssertionResult::hasExpandedExpression() const { return hasExpression() && getExpandedExpression() != getExpression(); } std::string AssertionResult::getExpandedExpression() const { return m_resultData.reconstructExpression(); } std::string AssertionResult::getMessage() const { return m_resultData.message; } SourceLineInfo AssertionResult::getSourceInfo() const { return m_info.lineInfo; } std::string AssertionResult::getTestMacroName() const { return m_info.macroName; } void AssertionResult::discardDecomposedExpression() const { m_resultData.decomposedExpression = CATCH_NULL; } void AssertionResult::expandDecomposedExpression() const { m_resultData.reconstructExpression(); } } // end namespace Catch // #included from: catch_test_case_info.hpp #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED #include namespace Catch { inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { if( startsWith( tag, '.' ) || tag == "hide" || tag == "!hide" ) return TestCaseInfo::IsHidden; else if( tag == "!throws" ) return TestCaseInfo::Throws; else if( tag == "!shouldfail" ) return TestCaseInfo::ShouldFail; else if( tag == "!mayfail" ) return TestCaseInfo::MayFail; else if( tag == "!nonportable" ) return TestCaseInfo::NonPortable; else return TestCaseInfo::None; } inline bool isReservedTag( std::string const& tag ) { return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); } inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { if( isReservedTag( tag ) ) { std::ostringstream ss; ss << Colour(Colour::Red) << "Tag name [" << tag << "] not allowed.\n" << "Tag names starting with non alpha-numeric characters are reserved\n" << Colour(Colour::FileName) << _lineInfo << '\n'; throw std::runtime_error(ss.str()); } } TestCase makeTestCase( ITestCase* _testCase, std::string const& _className, std::string const& _name, std::string const& _descOrTags, SourceLineInfo const& _lineInfo ) { bool isHidden( startsWith( _name, "./" ) ); // Legacy support // Parse out tags std::set tags; std::string desc, tag; bool inTag = false; for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { char c = _descOrTags[i]; if( !inTag ) { if( c == '[' ) inTag = true; else desc += c; } else { if( c == ']' ) { TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); if( prop == TestCaseInfo::IsHidden ) isHidden = true; else if( prop == TestCaseInfo::None ) enforceNotReservedTag( tag, _lineInfo ); tags.insert( tag ); tag.clear(); inTag = false; } else tag += c; } } if( isHidden ) { tags.insert( "hide" ); tags.insert( "." ); } TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); return TestCase( _testCase, info ); } void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) { testCaseInfo.tags = tags; testCaseInfo.lcaseTags.clear(); std::ostringstream oss; for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { oss << '[' << *it << ']'; std::string lcaseTag = toLower( *it ); testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); testCaseInfo.lcaseTags.insert( lcaseTag ); } testCaseInfo.tagsAsString = oss.str(); } TestCaseInfo::TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, std::set const& _tags, SourceLineInfo const& _lineInfo ) : name( _name ), className( _className ), description( _description ), lineInfo( _lineInfo ), properties( None ) { setTags( *this, _tags ); } TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) : name( other.name ), className( other.className ), description( other.description ), tags( other.tags ), lcaseTags( other.lcaseTags ), tagsAsString( other.tagsAsString ), lineInfo( other.lineInfo ), properties( other.properties ) {} bool TestCaseInfo::isHidden() const { return ( properties & IsHidden ) != 0; } bool TestCaseInfo::throws() const { return ( properties & Throws ) != 0; } bool TestCaseInfo::okToFail() const { return ( properties & (ShouldFail | MayFail ) ) != 0; } bool TestCaseInfo::expectedToFail() const { return ( properties & (ShouldFail ) ) != 0; } TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} TestCase::TestCase( TestCase const& other ) : TestCaseInfo( other ), test( other.test ) {} TestCase TestCase::withName( std::string const& _newName ) const { TestCase other( *this ); other.name = _newName; return other; } void TestCase::swap( TestCase& other ) { test.swap( other.test ); name.swap( other.name ); className.swap( other.className ); description.swap( other.description ); tags.swap( other.tags ); lcaseTags.swap( other.lcaseTags ); tagsAsString.swap( other.tagsAsString ); std::swap( TestCaseInfo::properties, static_cast( other ).properties ); std::swap( lineInfo, other.lineInfo ); } void TestCase::invoke() const { test->invoke(); } bool TestCase::operator == ( TestCase const& other ) const { return test.get() == other.test.get() && name == other.name && className == other.className; } bool TestCase::operator < ( TestCase const& other ) const { return name < other.name; } TestCase& TestCase::operator = ( TestCase const& other ) { TestCase temp( other ); swap( temp ); return *this; } TestCaseInfo const& TestCase::getTestCaseInfo() const { return *this; } } // end namespace Catch // #included from: catch_version.hpp #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED namespace Catch { Version::Version ( unsigned int _majorVersion, unsigned int _minorVersion, unsigned int _patchNumber, char const * const _branchName, unsigned int _buildNumber ) : majorVersion( _majorVersion ), minorVersion( _minorVersion ), patchNumber( _patchNumber ), branchName( _branchName ), buildNumber( _buildNumber ) {} std::ostream& operator << ( std::ostream& os, Version const& version ) { os << version.majorVersion << '.' << version.minorVersion << '.' << version.patchNumber; // branchName is never null -> 0th char is \0 if it is empty if (version.branchName[0]) { os << '-' << version.branchName << '.' << version.buildNumber; } return os; } inline Version libraryVersion() { static Version version( 1, 10, 0, "", 0 ); return version; } } // #included from: catch_message.hpp #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED namespace Catch { MessageInfo::MessageInfo( std::string const& _macroName, SourceLineInfo const& _lineInfo, ResultWas::OfType _type ) : macroName( _macroName ), lineInfo( _lineInfo ), type( _type ), sequence( ++globalCount ) {} // This may need protecting if threading support is added unsigned int MessageInfo::globalCount = 0; //////////////////////////////////////////////////////////////////////////// ScopedMessage::ScopedMessage( MessageBuilder const& builder ) : m_info( builder.m_info ) { m_info.message = builder.m_stream.str(); getResultCapture().pushScopedMessage( m_info ); } ScopedMessage::ScopedMessage( ScopedMessage const& other ) : m_info( other.m_info ) {} ScopedMessage::~ScopedMessage() { if ( !std::uncaught_exception() ){ getResultCapture().popScopedMessage(m_info); } } } // end namespace Catch // #included from: catch_legacy_reporter_adapter.hpp #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED // #included from: catch_legacy_reporter_adapter.h #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED namespace Catch { // Deprecated struct IReporter : IShared { virtual ~IReporter(); virtual bool shouldRedirectStdout() const = 0; virtual void StartTesting() = 0; virtual void EndTesting( Totals const& totals ) = 0; virtual void StartGroup( std::string const& groupName ) = 0; virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; virtual void Aborted() = 0; virtual void Result( AssertionResult const& result ) = 0; }; class LegacyReporterAdapter : public SharedImpl { public: LegacyReporterAdapter( Ptr const& legacyReporter ); virtual ~LegacyReporterAdapter(); virtual ReporterPreferences getPreferences() const; virtual void noMatchingTestCases( std::string const& ); virtual void testRunStarting( TestRunInfo const& ); virtual void testGroupStarting( GroupInfo const& groupInfo ); virtual void testCaseStarting( TestCaseInfo const& testInfo ); virtual void sectionStarting( SectionInfo const& sectionInfo ); virtual void assertionStarting( AssertionInfo const& ); virtual bool assertionEnded( AssertionStats const& assertionStats ); virtual void sectionEnded( SectionStats const& sectionStats ); virtual void testCaseEnded( TestCaseStats const& testCaseStats ); virtual void testGroupEnded( TestGroupStats const& testGroupStats ); virtual void testRunEnded( TestRunStats const& testRunStats ); virtual void skipTest( TestCaseInfo const& ); private: Ptr m_legacyReporter; }; } namespace Catch { LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) : m_legacyReporter( legacyReporter ) {} LegacyReporterAdapter::~LegacyReporterAdapter() {} ReporterPreferences LegacyReporterAdapter::getPreferences() const { ReporterPreferences prefs; prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); return prefs; } void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { m_legacyReporter->StartTesting(); } void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { m_legacyReporter->StartGroup( groupInfo.name ); } void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { m_legacyReporter->StartTestCase( testInfo ); } void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); } void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { // Not on legacy interface } bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); it != itEnd; ++it ) { if( it->type == ResultWas::Info ) { ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); rb << it->message; rb.setResultType( ResultWas::Info ); AssertionResult result = rb.build(); m_legacyReporter->Result( result ); } } } m_legacyReporter->Result( assertionStats.assertionResult ); return true; } void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { if( sectionStats.missingAssertions ) m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); } void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { m_legacyReporter->EndTestCase ( testCaseStats.testInfo, testCaseStats.totals, testCaseStats.stdOut, testCaseStats.stdErr ); } void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { if( testGroupStats.aborting ) m_legacyReporter->Aborted(); m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); } void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { m_legacyReporter->EndTesting( testRunStats.totals ); } void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { } } // #included from: catch_timer.hpp #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wc++11-long-long" #endif #ifdef CATCH_PLATFORM_WINDOWS #else #include #endif namespace Catch { namespace { #ifdef CATCH_PLATFORM_WINDOWS UInt64 getCurrentTicks() { static UInt64 hz=0, hzo=0; if (!hz) { QueryPerformanceFrequency( reinterpret_cast( &hz ) ); QueryPerformanceCounter( reinterpret_cast( &hzo ) ); } UInt64 t; QueryPerformanceCounter( reinterpret_cast( &t ) ); return ((t-hzo)*1000000)/hz; } #else UInt64 getCurrentTicks() { timeval t; gettimeofday(&t,CATCH_NULL); return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); } #endif } void Timer::start() { m_ticks = getCurrentTicks(); } unsigned int Timer::getElapsedMicroseconds() const { return static_cast(getCurrentTicks() - m_ticks); } unsigned int Timer::getElapsedMilliseconds() const { return static_cast(getElapsedMicroseconds()/1000); } double Timer::getElapsedSeconds() const { return getElapsedMicroseconds()/1000000.0; } } // namespace Catch #ifdef __clang__ #pragma clang diagnostic pop #endif // #included from: catch_common.hpp #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED #include #include namespace Catch { bool startsWith( std::string const& s, std::string const& prefix ) { return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); } bool startsWith( std::string const& s, char prefix ) { return !s.empty() && s[0] == prefix; } bool endsWith( std::string const& s, std::string const& suffix ) { return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); } bool endsWith( std::string const& s, char suffix ) { return !s.empty() && s[s.size()-1] == suffix; } bool contains( std::string const& s, std::string const& infix ) { return s.find( infix ) != std::string::npos; } char toLowerCh(char c) { return static_cast( std::tolower( c ) ); } void toLowerInPlace( std::string& s ) { std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); } std::string toLower( std::string const& s ) { std::string lc = s; toLowerInPlace( lc ); return lc; } std::string trim( std::string const& str ) { static char const* whitespaceChars = "\n\r\t "; std::string::size_type start = str.find_first_not_of( whitespaceChars ); std::string::size_type end = str.find_last_not_of( whitespaceChars ); return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); } bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { bool replaced = false; std::size_t i = str.find( replaceThis ); while( i != std::string::npos ) { replaced = true; str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); if( i < str.size()-withThis.size() ) i = str.find( replaceThis, i+withThis.size() ); else i = std::string::npos; } return replaced; } pluralise::pluralise( std::size_t count, std::string const& label ) : m_count( count ), m_label( label ) {} std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { os << pluraliser.m_count << ' ' << pluraliser.m_label; if( pluraliser.m_count != 1 ) os << 's'; return os; } SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){} SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) : file( _file ), line( _line ) {} bool SourceLineInfo::empty() const { return file[0] == '\0'; } bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); } bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); } void seedRng( IConfig const& config ) { if( config.rngSeed() != 0 ) std::srand( config.rngSeed() ); } unsigned int rngSeed() { return getCurrentContext().getConfig()->rngSeed(); } std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { #ifndef __GNUG__ os << info.file << '(' << info.line << ')'; #else os << info.file << ':' << info.line; #endif return os; } void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { std::ostringstream oss; oss << locationInfo << ": Internal Catch error: '" << message << '\''; if( alwaysTrue() ) throw std::logic_error( oss.str() ); } } // #included from: catch_section.hpp #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED namespace Catch { SectionInfo::SectionInfo ( SourceLineInfo const& _lineInfo, std::string const& _name, std::string const& _description ) : name( _name ), description( _description ), lineInfo( _lineInfo ) {} Section::Section( SectionInfo const& info ) : m_info( info ), m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) { m_timer.start(); } #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17 #endif Section::~Section() { if( m_sectionIncluded ) { SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); if( std::uncaught_exception() ) getResultCapture().sectionEndedEarly( endInfo ); else getResultCapture().sectionEnded( endInfo ); } } #if defined(_MSC_VER) #pragma warning(pop) #endif // This indicates whether the section should be executed or not Section::operator bool() const { return m_sectionIncluded; } } // end namespace Catch // #included from: catch_debugger.hpp #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED #ifdef CATCH_PLATFORM_MAC #include #include #include #include #include namespace Catch{ // The following function is taken directly from the following technical note: // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html // Returns true if the current process is being debugged (either // running under the debugger or has a debugger attached post facto). bool isDebuggerActive(){ int mib[4]; struct kinfo_proc info; size_t size; // Initialize the flags so that, if sysctl fails for some bizarre // reason, we get a predictable result. info.kp_proc.p_flag = 0; // Initialize mib, which tells sysctl the info we want, in this case // we're looking for information about a specific process ID. mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; mib[3] = getpid(); // Call sysctl. size = sizeof(info); if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; return false; } // We're being debugged if the P_TRACED flag is set. return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); } } // namespace Catch #elif defined(CATCH_PLATFORM_LINUX) #include #include namespace Catch{ // The standard POSIX way of detecting a debugger is to attempt to // ptrace() the process, but this needs to be done from a child and not // this process itself to still allow attaching to this process later // if wanted, so is rather heavy. Under Linux we have the PID of the // "debugger" (which doesn't need to be gdb, of course, it could also // be strace, for example) in /proc/$PID/status, so just get it from // there instead. bool isDebuggerActive(){ // Libstdc++ has a bug, where std::ifstream sets errno to 0 // This way our users can properly assert over errno values ErrnoGuard guard; std::ifstream in("/proc/self/status"); for( std::string line; std::getline(in, line); ) { static const int PREFIX_LEN = 11; if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { // We're traced if the PID is not 0 and no other PID starts // with 0 digit, so it's enough to check for just a single // character. return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; } } return false; } } // namespace Catch #elif defined(_MSC_VER) extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); namespace Catch { bool isDebuggerActive() { return IsDebuggerPresent() != 0; } } #elif defined(__MINGW32__) extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); namespace Catch { bool isDebuggerActive() { return IsDebuggerPresent() != 0; } } #else namespace Catch { inline bool isDebuggerActive() { return false; } } #endif // Platform #ifdef CATCH_PLATFORM_WINDOWS namespace Catch { void writeToDebugConsole( std::string const& text ) { ::OutputDebugStringA( text.c_str() ); } } #else namespace Catch { void writeToDebugConsole( std::string const& text ) { // !TBD: Need a version for Mac/ XCode and other IDEs Catch::cout() << text; } } #endif // Platform // #included from: catch_tostring.hpp #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED namespace Catch { namespace Detail { const std::string unprintableString = "{?}"; namespace { const int hexThreshold = 255; struct Endianness { enum Arch { Big, Little }; static Arch which() { union _{ int asInt; char asChar[sizeof (int)]; } u; u.asInt = 1; return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; } }; } std::string rawMemoryToString( const void *object, std::size_t size ) { // Reverse order for little endian architectures int i = 0, end = static_cast( size ), inc = 1; if( Endianness::which() == Endianness::Little ) { i = end-1; end = inc = -1; } unsigned char const *bytes = static_cast(object); std::ostringstream os; os << "0x" << std::setfill('0') << std::hex; for( ; i != end; i += inc ) os << std::setw(2) << static_cast(bytes[i]); return os.str(); } } std::string toString( std::string const& value ) { std::string s = value; if( getCurrentContext().getConfig()->showInvisibles() ) { for(size_t i = 0; i < s.size(); ++i ) { std::string subs; switch( s[i] ) { case '\n': subs = "\\n"; break; case '\t': subs = "\\t"; break; default: break; } if( !subs.empty() ) { s = s.substr( 0, i ) + subs + s.substr( i+1 ); ++i; } } } return '"' + s + '"'; } std::string toString( std::wstring const& value ) { std::string s; s.reserve( value.size() ); for(size_t i = 0; i < value.size(); ++i ) s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; return Catch::toString( s ); } std::string toString( const char* const value ) { return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); } std::string toString( char* const value ) { return Catch::toString( static_cast( value ) ); } std::string toString( const wchar_t* const value ) { return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); } std::string toString( wchar_t* const value ) { return Catch::toString( static_cast( value ) ); } std::string toString( int value ) { std::ostringstream oss; oss << value; if( value > Detail::hexThreshold ) oss << " (0x" << std::hex << value << ')'; return oss.str(); } std::string toString( unsigned long value ) { std::ostringstream oss; oss << value; if( value > Detail::hexThreshold ) oss << " (0x" << std::hex << value << ')'; return oss.str(); } std::string toString( unsigned int value ) { return Catch::toString( static_cast( value ) ); } template std::string fpToString( T value, int precision ) { std::ostringstream oss; oss << std::setprecision( precision ) << std::fixed << value; std::string d = oss.str(); std::size_t i = d.find_last_not_of( '0' ); if( i != std::string::npos && i != d.size()-1 ) { if( d[i] == '.' ) i++; d = d.substr( 0, i+1 ); } return d; } std::string toString( const double value ) { return fpToString( value, 10 ); } std::string toString( const float value ) { return fpToString( value, 5 ) + 'f'; } std::string toString( bool value ) { return value ? "true" : "false"; } std::string toString( char value ) { if ( value == '\r' ) return "'\\r'"; if ( value == '\f' ) return "'\\f'"; if ( value == '\n' ) return "'\\n'"; if ( value == '\t' ) return "'\\t'"; if ( '\0' <= value && value < ' ' ) return toString( static_cast( value ) ); char chstr[] = "' '"; chstr[1] = value; return chstr; } std::string toString( signed char value ) { return toString( static_cast( value ) ); } std::string toString( unsigned char value ) { return toString( static_cast( value ) ); } #ifdef CATCH_CONFIG_CPP11_LONG_LONG std::string toString( long long value ) { std::ostringstream oss; oss << value; if( value > Detail::hexThreshold ) oss << " (0x" << std::hex << value << ')'; return oss.str(); } std::string toString( unsigned long long value ) { std::ostringstream oss; oss << value; if( value > Detail::hexThreshold ) oss << " (0x" << std::hex << value << ')'; return oss.str(); } #endif #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ) { return "nullptr"; } #endif #ifdef __OBJC__ std::string toString( NSString const * const& nsstring ) { if( !nsstring ) return "nil"; return "@" + toString([nsstring UTF8String]); } std::string toString( NSString * CATCH_ARC_STRONG & nsstring ) { if( !nsstring ) return "nil"; return "@" + toString([nsstring UTF8String]); } std::string toString( NSObject* const& nsObject ) { return toString( [nsObject description] ); } #endif } // end namespace Catch // #included from: catch_result_builder.hpp #define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED namespace Catch { ResultBuilder::ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, ResultDisposition::Flags resultDisposition, char const* secondArg ) : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition, secondArg ), m_shouldDebugBreak( false ), m_shouldThrow( false ), m_guardException( false ), m_usedStream( false ) {} ResultBuilder::~ResultBuilder() { #if defined(CATCH_CONFIG_FAST_COMPILE) if ( m_guardException ) { stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; captureResult( ResultWas::ThrewException ); getCurrentContext().getResultCapture()->exceptionEarlyReported(); } #endif } ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { m_data.resultType = result; return *this; } ResultBuilder& ResultBuilder::setResultType( bool result ) { m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; return *this; } void ResultBuilder::endExpression( DecomposedExpression const& expr ) { // Flip bool results if FalseTest flag is set if( isFalseTest( m_assertionInfo.resultDisposition ) ) { m_data.negate( expr.isBinaryExpression() ); } getResultCapture().assertionRun(); if(getCurrentContext().getConfig()->includeSuccessfulResults() || m_data.resultType != ResultWas::Ok) { AssertionResult result = build( expr ); handleResult( result ); } else getResultCapture().assertionPassed(); } void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { m_assertionInfo.resultDisposition = resultDisposition; stream().oss << Catch::translateActiveException(); captureResult( ResultWas::ThrewException ); } void ResultBuilder::captureResult( ResultWas::OfType resultType ) { setResultType( resultType ); captureExpression(); } void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { if( expectedMessage.empty() ) captureExpectedException( Matchers::Impl::MatchAllOf() ); else captureExpectedException( Matchers::Equals( expectedMessage ) ); } void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase const& matcher ) { assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); AssertionResultData data = m_data; data.resultType = ResultWas::Ok; data.reconstructedExpression = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); std::string actualMessage = Catch::translateActiveException(); if( !matcher.match( actualMessage ) ) { data.resultType = ResultWas::ExpressionFailed; data.reconstructedExpression = actualMessage; } AssertionResult result( m_assertionInfo, data ); handleResult( result ); } void ResultBuilder::captureExpression() { AssertionResult result = build(); handleResult( result ); } void ResultBuilder::handleResult( AssertionResult const& result ) { getResultCapture().assertionEnded( result ); if( !result.isOk() ) { if( getCurrentContext().getConfig()->shouldDebugBreak() ) m_shouldDebugBreak = true; if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) m_shouldThrow = true; } } void ResultBuilder::react() { #if defined(CATCH_CONFIG_FAST_COMPILE) if (m_shouldDebugBreak) { /////////////////////////////////////////////////////////////////// // To inspect the state during test, you need to go one level up the callstack // To go back to the test and change execution, jump over the throw statement /////////////////////////////////////////////////////////////////// CATCH_BREAK_INTO_DEBUGGER(); } #endif if( m_shouldThrow ) throw Catch::TestFailureException(); } bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } AssertionResult ResultBuilder::build() const { return build( *this ); } // CAVEAT: The returned AssertionResult stores a pointer to the argument expr, // a temporary DecomposedExpression, which in turn holds references to // operands, possibly temporary as well. // It should immediately be passed to handleResult; if the expression // needs to be reported, its string expansion must be composed before // the temporaries are destroyed. AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const { assert( m_data.resultType != ResultWas::Unknown ); AssertionResultData data = m_data; if(m_usedStream) data.message = m_stream().oss.str(); data.decomposedExpression = &expr; // for lazy reconstruction return AssertionResult( m_assertionInfo, data ); } void ResultBuilder::reconstructExpression( std::string& dest ) const { dest = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); } void ResultBuilder::setExceptionGuard() { m_guardException = true; } void ResultBuilder::unsetExceptionGuard() { m_guardException = false; } } // end namespace Catch // #included from: catch_tag_alias_registry.hpp #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED namespace Catch { TagAliasRegistry::~TagAliasRegistry() {} Option TagAliasRegistry::find( std::string const& alias ) const { std::map::const_iterator it = m_registry.find( alias ); if( it != m_registry.end() ) return it->second; else return Option(); } std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { std::string expandedTestSpec = unexpandedTestSpec; for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); it != itEnd; ++it ) { std::size_t pos = expandedTestSpec.find( it->first ); if( pos != std::string::npos ) { expandedTestSpec = expandedTestSpec.substr( 0, pos ) + it->second.tag + expandedTestSpec.substr( pos + it->first.size() ); } } return expandedTestSpec; } void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) { std::ostringstream oss; oss << Colour( Colour::Red ) << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << Colour( Colour::FileName ) << lineInfo << '\n'; throw std::domain_error( oss.str().c_str() ); } if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { std::ostringstream oss; oss << Colour( Colour::Red ) << "error: tag alias, \"" << alias << "\" already registered.\n" << "\tFirst seen at " << Colour( Colour::Red ) << find(alias)->lineInfo << '\n' << Colour( Colour::Red ) << "\tRedefined at " << Colour( Colour::FileName) << lineInfo << '\n'; throw std::domain_error( oss.str().c_str() ); } } ITagAliasRegistry::~ITagAliasRegistry() {} ITagAliasRegistry const& ITagAliasRegistry::get() { return getRegistryHub().getTagAliasRegistry(); } RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { getMutableRegistryHub().registerTagAlias( alias, tag, lineInfo ); } } // end namespace Catch // #included from: catch_matchers_string.hpp namespace Catch { namespace Matchers { namespace StdString { CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) : m_caseSensitivity( caseSensitivity ), m_str( adjustString( str ) ) {} std::string CasedString::adjustString( std::string const& str ) const { return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; } std::string CasedString::caseSensitivitySuffix() const { return m_caseSensitivity == CaseSensitive::No ? " (case insensitive)" : std::string(); } StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) : m_comparator( comparator ), m_operation( operation ) { } std::string StringMatcherBase::describe() const { std::string description; description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + m_comparator.caseSensitivitySuffix().size()); description += m_operation; description += ": \""; description += m_comparator.m_str; description += "\""; description += m_comparator.caseSensitivitySuffix(); return description; } EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} bool EqualsMatcher::match( std::string const& source ) const { return m_comparator.adjustString( source ) == m_comparator.m_str; } ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} bool ContainsMatcher::match( std::string const& source ) const { return contains( m_comparator.adjustString( source ), m_comparator.m_str ); } StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} bool StartsWithMatcher::match( std::string const& source ) const { return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); } EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} bool EndsWithMatcher::match( std::string const& source ) const { return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); } } // namespace StdString StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); } StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); } StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); } StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); } } // namespace Matchers } // namespace Catch // #included from: ../reporters/catch_reporter_multi.hpp #define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED namespace Catch { class MultipleReporters : public SharedImpl { typedef std::vector > Reporters; Reporters m_reporters; public: void add( Ptr const& reporter ) { m_reporters.push_back( reporter ); } public: // IStreamingReporter virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { return m_reporters[0]->getPreferences(); } virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->noMatchingTestCases( spec ); } virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->testRunStarting( testRunInfo ); } virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->testGroupStarting( groupInfo ); } virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->testCaseStarting( testInfo ); } virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->sectionStarting( sectionInfo ); } virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->assertionStarting( assertionInfo ); } // The return value indicates if the messages buffer should be cleared: virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { bool clearBuffer = false; for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) clearBuffer |= (*it)->assertionEnded( assertionStats ); return clearBuffer; } virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->sectionEnded( sectionStats ); } virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->testCaseEnded( testCaseStats ); } virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->testGroupEnded( testGroupStats ); } virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->testRunEnded( testRunStats ); } virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->skipTest( testInfo ); } virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { return this; } }; Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { Ptr resultingReporter; if( existingReporter ) { MultipleReporters* multi = existingReporter->tryAsMulti(); if( !multi ) { multi = new MultipleReporters; resultingReporter = Ptr( multi ); if( existingReporter ) multi->add( existingReporter ); } else resultingReporter = existingReporter; multi->add( additionalReporter ); } else resultingReporter = additionalReporter; return resultingReporter; } } // end namespace Catch // #included from: ../reporters/catch_reporter_xml.hpp #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED // #included from: catch_reporter_bases.hpp #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED #include #include #include #include namespace Catch { namespace { // Because formatting using c++ streams is stateful, drop down to C is required // Alternatively we could use stringstream, but its performance is... not good. std::string getFormattedDuration( double duration ) { // Max exponent + 1 is required to represent the whole part // + 1 for decimal point // + 3 for the 3 decimal places // + 1 for null terminator const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; char buffer[maxDoubleSize]; // Save previous errno, to prevent sprintf from overwriting it ErrnoGuard guard; #ifdef _MSC_VER sprintf_s(buffer, "%.3f", duration); #else sprintf(buffer, "%.3f", duration); #endif return std::string(buffer); } } struct StreamingReporterBase : SharedImpl { StreamingReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) { m_reporterPrefs.shouldRedirectStdOut = false; } virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { return m_reporterPrefs; } virtual ~StreamingReporterBase() CATCH_OVERRIDE; virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { currentTestRunInfo = _testRunInfo; } virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { currentGroupInfo = _groupInfo; } virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { currentTestCaseInfo = _testInfo; } virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_sectionStack.push_back( _sectionInfo ); } virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { m_sectionStack.pop_back(); } virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { currentTestCaseInfo.reset(); } virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { currentGroupInfo.reset(); } virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { currentTestCaseInfo.reset(); currentGroupInfo.reset(); currentTestRunInfo.reset(); } virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { // Don't do anything with this by default. // It can optionally be overridden in the derived class. } Ptr m_config; std::ostream& stream; LazyStat currentTestRunInfo; LazyStat currentGroupInfo; LazyStat currentTestCaseInfo; std::vector m_sectionStack; ReporterPreferences m_reporterPrefs; }; struct CumulativeReporterBase : SharedImpl { template struct Node : SharedImpl<> { explicit Node( T const& _value ) : value( _value ) {} virtual ~Node() {} typedef std::vector > ChildNodes; T value; ChildNodes children; }; struct SectionNode : SharedImpl<> { explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} virtual ~SectionNode(); bool operator == ( SectionNode const& other ) const { return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; } bool operator == ( Ptr const& other ) const { return operator==( *other ); } SectionStats stats; typedef std::vector > ChildSections; typedef std::vector Assertions; ChildSections childSections; Assertions assertions; std::string stdOut; std::string stdErr; }; struct BySectionInfo { BySectionInfo( SectionInfo const& other ) : m_other( other ) {} BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} bool operator() ( Ptr const& node ) const { return ((node->stats.sectionInfo.name == m_other.name) && (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); } private: void operator=( BySectionInfo const& ); SectionInfo const& m_other; }; typedef Node TestCaseNode; typedef Node TestGroupNode; typedef Node TestRunNode; CumulativeReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) { m_reporterPrefs.shouldRedirectStdOut = false; } ~CumulativeReporterBase(); virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { return m_reporterPrefs; } virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); Ptr node; if( m_sectionStack.empty() ) { if( !m_rootSection ) m_rootSection = new SectionNode( incompleteStats ); node = m_rootSection; } else { SectionNode& parentNode = *m_sectionStack.back(); SectionNode::ChildSections::const_iterator it = std::find_if( parentNode.childSections.begin(), parentNode.childSections.end(), BySectionInfo( sectionInfo ) ); if( it == parentNode.childSections.end() ) { node = new SectionNode( incompleteStats ); parentNode.childSections.push_back( node ); } else node = *it; } m_sectionStack.push_back( node ); m_deepestSection = node; } virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { assert( !m_sectionStack.empty() ); SectionNode& sectionNode = *m_sectionStack.back(); sectionNode.assertions.push_back( assertionStats ); // AssertionResult holds a pointer to a temporary DecomposedExpression, // which getExpandedExpression() calls to build the expression string. // Our section stack copy of the assertionResult will likely outlive the // temporary, so it must be expanded or discarded now to avoid calling // a destroyed object later. prepareExpandedExpression( sectionNode.assertions.back().assertionResult ); return true; } virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { assert( !m_sectionStack.empty() ); SectionNode& node = *m_sectionStack.back(); node.stats = sectionStats; m_sectionStack.pop_back(); } virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { Ptr node = new TestCaseNode( testCaseStats ); assert( m_sectionStack.size() == 0 ); node->children.push_back( m_rootSection ); m_testCases.push_back( node ); m_rootSection.reset(); assert( m_deepestSection ); m_deepestSection->stdOut = testCaseStats.stdOut; m_deepestSection->stdErr = testCaseStats.stdErr; } virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { Ptr node = new TestGroupNode( testGroupStats ); node->children.swap( m_testCases ); m_testGroups.push_back( node ); } virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { Ptr node = new TestRunNode( testRunStats ); node->children.swap( m_testGroups ); m_testRuns.push_back( node ); testRunEndedCumulative(); } virtual void testRunEndedCumulative() = 0; virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} virtual void prepareExpandedExpression( AssertionResult& result ) const { if( result.isOk() ) result.discardDecomposedExpression(); else result.expandDecomposedExpression(); } Ptr m_config; std::ostream& stream; std::vector m_assertions; std::vector > > m_sections; std::vector > m_testCases; std::vector > m_testGroups; std::vector > m_testRuns; Ptr m_rootSection; Ptr m_deepestSection; std::vector > m_sectionStack; ReporterPreferences m_reporterPrefs; }; template char const* getLineOfChars() { static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; if( !*line ) { std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; } return line; } struct TestEventListenerBase : StreamingReporterBase { TestEventListenerBase( ReporterConfig const& _config ) : StreamingReporterBase( _config ) {} virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { return false; } }; } // end namespace Catch // #included from: ../internal/catch_reporter_registrars.hpp #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED namespace Catch { template class LegacyReporterRegistrar { class ReporterFactory : public IReporterFactory { virtual IStreamingReporter* create( ReporterConfig const& config ) const { return new LegacyReporterAdapter( new T( config ) ); } virtual std::string getDescription() const { return T::getDescription(); } }; public: LegacyReporterRegistrar( std::string const& name ) { getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } }; template class ReporterRegistrar { class ReporterFactory : public SharedImpl { // *** Please Note ***: // - If you end up here looking at a compiler error because it's trying to register // your custom reporter class be aware that the native reporter interface has changed // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. // However please consider updating to the new interface as the old one is now // deprecated and will probably be removed quite soon! // Please contact me via github if you have any questions at all about this. // In fact, ideally, please contact me anyway to let me know you've hit this - as I have // no idea who is actually using custom reporters at all (possibly no-one!). // The new interface is designed to minimise exposure to interface changes in the future. virtual IStreamingReporter* create( ReporterConfig const& config ) const { return new T( config ); } virtual std::string getDescription() const { return T::getDescription(); } }; public: ReporterRegistrar( std::string const& name ) { getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } }; template class ListenerRegistrar { class ListenerFactory : public SharedImpl { virtual IStreamingReporter* create( ReporterConfig const& config ) const { return new T( config ); } virtual std::string getDescription() const { return std::string(); } }; public: ListenerRegistrar() { getMutableRegistryHub().registerListener( new ListenerFactory() ); } }; } #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } // Deprecated - use the form without INTERNAL_ #define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } #define CATCH_REGISTER_LISTENER( listenerType ) \ namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } // #included from: ../internal/catch_xmlwriter.hpp #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED #include #include #include #include namespace Catch { class XmlEncode { public: enum ForWhat { ForTextNodes, ForAttributes }; XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) : m_str( str ), m_forWhat( forWhat ) {} void encodeTo( std::ostream& os ) const { // Apostrophe escaping not necessary if we always use " to write attributes // (see: http://www.w3.org/TR/xml/#syntax) for( std::size_t i = 0; i < m_str.size(); ++ i ) { char c = m_str[i]; switch( c ) { case '<': os << "<"; break; case '&': os << "&"; break; case '>': // See: http://www.w3.org/TR/xml/#syntax if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) os << ">"; else os << c; break; case '\"': if( m_forWhat == ForAttributes ) os << """; else os << c; break; default: // Escape control chars - based on contribution by @espenalb in PR #465 and // by @mrpi PR #588 if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast( c ); } else os << c; } } } friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { xmlEncode.encodeTo( os ); return os; } private: std::string m_str; ForWhat m_forWhat; }; class XmlWriter { public: class ScopedElement { public: ScopedElement( XmlWriter* writer ) : m_writer( writer ) {} ScopedElement( ScopedElement const& other ) : m_writer( other.m_writer ){ other.m_writer = CATCH_NULL; } ~ScopedElement() { if( m_writer ) m_writer->endElement(); } ScopedElement& writeText( std::string const& text, bool indent = true ) { m_writer->writeText( text, indent ); return *this; } template ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { m_writer->writeAttribute( name, attribute ); return *this; } private: mutable XmlWriter* m_writer; }; XmlWriter() : m_tagIsOpen( false ), m_needsNewline( false ), m_os( Catch::cout() ) { writeDeclaration(); } XmlWriter( std::ostream& os ) : m_tagIsOpen( false ), m_needsNewline( false ), m_os( os ) { writeDeclaration(); } ~XmlWriter() { while( !m_tags.empty() ) endElement(); } XmlWriter& startElement( std::string const& name ) { ensureTagClosed(); newlineIfNecessary(); m_os << m_indent << '<' << name; m_tags.push_back( name ); m_indent += " "; m_tagIsOpen = true; return *this; } ScopedElement scopedElement( std::string const& name ) { ScopedElement scoped( this ); startElement( name ); return scoped; } XmlWriter& endElement() { newlineIfNecessary(); m_indent = m_indent.substr( 0, m_indent.size()-2 ); if( m_tagIsOpen ) { m_os << "/>"; m_tagIsOpen = false; } else { m_os << m_indent << ""; } m_os << std::endl; m_tags.pop_back(); return *this; } XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { if( !name.empty() && !attribute.empty() ) m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; return *this; } XmlWriter& writeAttribute( std::string const& name, bool attribute ) { m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; return *this; } template XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { std::ostringstream oss; oss << attribute; return writeAttribute( name, oss.str() ); } XmlWriter& writeText( std::string const& text, bool indent = true ) { if( !text.empty() ){ bool tagWasOpen = m_tagIsOpen; ensureTagClosed(); if( tagWasOpen && indent ) m_os << m_indent; m_os << XmlEncode( text ); m_needsNewline = true; } return *this; } XmlWriter& writeComment( std::string const& text ) { ensureTagClosed(); m_os << m_indent << ""; m_needsNewline = true; return *this; } void writeStylesheetRef( std::string const& url ) { m_os << "\n"; } XmlWriter& writeBlankLine() { ensureTagClosed(); m_os << '\n'; return *this; } void ensureTagClosed() { if( m_tagIsOpen ) { m_os << ">" << std::endl; m_tagIsOpen = false; } } private: XmlWriter( XmlWriter const& ); void operator=( XmlWriter const& ); void writeDeclaration() { m_os << "\n"; } void newlineIfNecessary() { if( m_needsNewline ) { m_os << std::endl; m_needsNewline = false; } } bool m_tagIsOpen; bool m_needsNewline; std::vector m_tags; std::string m_indent; std::ostream& m_os; }; } namespace Catch { class XmlReporter : public StreamingReporterBase { public: XmlReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), m_xml(_config.stream()), m_sectionDepth( 0 ) { m_reporterPrefs.shouldRedirectStdOut = true; } virtual ~XmlReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as an XML document"; } virtual std::string getStylesheetRef() const { return std::string(); } void writeSourceInfo( SourceLineInfo const& sourceInfo ) { m_xml .writeAttribute( "filename", sourceInfo.file ) .writeAttribute( "line", sourceInfo.line ); } public: // StreamingReporterBase virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { StreamingReporterBase::noMatchingTestCases( s ); } virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testRunStarting( testInfo ); std::string stylesheetRef = getStylesheetRef(); if( !stylesheetRef.empty() ) m_xml.writeStylesheetRef( stylesheetRef ); m_xml.startElement( "Catch" ); if( !m_config->name().empty() ) m_xml.writeAttribute( "name", m_config->name() ); } virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { StreamingReporterBase::testGroupStarting( groupInfo ); m_xml.startElement( "Group" ) .writeAttribute( "name", groupInfo.name ); } virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testCaseStarting(testInfo); m_xml.startElement( "TestCase" ) .writeAttribute( "name", trim( testInfo.name ) ) .writeAttribute( "description", testInfo.description ) .writeAttribute( "tags", testInfo.tagsAsString ); writeSourceInfo( testInfo.lineInfo ); if ( m_config->showDurations() == ShowDurations::Always ) m_testCaseTimer.start(); m_xml.ensureTagClosed(); } virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { StreamingReporterBase::sectionStarting( sectionInfo ); if( m_sectionDepth++ > 0 ) { m_xml.startElement( "Section" ) .writeAttribute( "name", trim( sectionInfo.name ) ) .writeAttribute( "description", sectionInfo.description ); writeSourceInfo( sectionInfo.lineInfo ); m_xml.ensureTagClosed(); } } virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { AssertionResult const& result = assertionStats.assertionResult; bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); if( includeResults ) { // Print any info messages in tags. for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); it != itEnd; ++it ) { if( it->type == ResultWas::Info ) { m_xml.scopedElement( "Info" ) .writeText( it->message ); } else if ( it->type == ResultWas::Warning ) { m_xml.scopedElement( "Warning" ) .writeText( it->message ); } } } // Drop out if result was successful but we're not printing them. if( !includeResults && result.getResultType() != ResultWas::Warning ) return true; // Print the expression if there is one. if( result.hasExpression() ) { m_xml.startElement( "Expression" ) .writeAttribute( "success", result.succeeded() ) .writeAttribute( "type", result.getTestMacroName() ); writeSourceInfo( result.getSourceInfo() ); m_xml.scopedElement( "Original" ) .writeText( result.getExpression() ); m_xml.scopedElement( "Expanded" ) .writeText( result.getExpandedExpression() ); } // And... Print a result applicable to each result type. switch( result.getResultType() ) { case ResultWas::ThrewException: m_xml.startElement( "Exception" ); writeSourceInfo( result.getSourceInfo() ); m_xml.writeText( result.getMessage() ); m_xml.endElement(); break; case ResultWas::FatalErrorCondition: m_xml.startElement( "FatalErrorCondition" ); writeSourceInfo( result.getSourceInfo() ); m_xml.writeText( result.getMessage() ); m_xml.endElement(); break; case ResultWas::Info: m_xml.scopedElement( "Info" ) .writeText( result.getMessage() ); break; case ResultWas::Warning: // Warning will already have been written break; case ResultWas::ExplicitFailure: m_xml.startElement( "Failure" ); writeSourceInfo( result.getSourceInfo() ); m_xml.writeText( result.getMessage() ); m_xml.endElement(); break; default: break; } if( result.hasExpression() ) m_xml.endElement(); return true; } virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { StreamingReporterBase::sectionEnded( sectionStats ); if( --m_sectionDepth > 0 ) { XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); e.writeAttribute( "successes", sectionStats.assertions.passed ); e.writeAttribute( "failures", sectionStats.assertions.failed ); e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); if ( m_config->showDurations() == ShowDurations::Always ) e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); m_xml.endElement(); } } virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( testCaseStats ); XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); if ( m_config->showDurations() == ShowDurations::Always ) e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); if( !testCaseStats.stdOut.empty() ) m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); if( !testCaseStats.stdErr.empty() ) m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); m_xml.endElement(); } virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { StreamingReporterBase::testGroupEnded( testGroupStats ); // TODO: Check testGroupStats.aborting and act accordingly. m_xml.scopedElement( "OverallResults" ) .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); m_xml.endElement(); } virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { StreamingReporterBase::testRunEnded( testRunStats ); m_xml.scopedElement( "OverallResults" ) .writeAttribute( "successes", testRunStats.totals.assertions.passed ) .writeAttribute( "failures", testRunStats.totals.assertions.failed ) .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); m_xml.endElement(); } private: Timer m_testCaseTimer; XmlWriter m_xml; int m_sectionDepth; }; INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) } // end namespace Catch // #included from: ../reporters/catch_reporter_junit.hpp #define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED #include namespace Catch { namespace { std::string getCurrentTimestamp() { // Beware, this is not reentrant because of backward compatibility issues // Also, UTC only, again because of backward compatibility (%z is C++11) time_t rawtime; std::time(&rawtime); const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z"); #ifdef _MSC_VER std::tm timeInfo = {}; gmtime_s(&timeInfo, &rawtime); #else std::tm* timeInfo; timeInfo = std::gmtime(&rawtime); #endif char timeStamp[timeStampSize]; const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; #ifdef _MSC_VER std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); #else std::strftime(timeStamp, timeStampSize, fmt, timeInfo); #endif return std::string(timeStamp); } } class JunitReporter : public CumulativeReporterBase { public: JunitReporter( ReporterConfig const& _config ) : CumulativeReporterBase( _config ), xml( _config.stream() ), unexpectedExceptions( 0 ), m_okToFail( false ) { m_reporterPrefs.shouldRedirectStdOut = true; } virtual ~JunitReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results in an XML format that looks like Ant's junitreport target"; } virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { CumulativeReporterBase::testRunStarting( runInfo ); xml.startElement( "testsuites" ); } virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { suiteTimer.start(); stdOutForSuite.str(""); stdErrForSuite.str(""); unexpectedExceptions = 0; CumulativeReporterBase::testGroupStarting( groupInfo ); } virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) CATCH_OVERRIDE { m_okToFail = testCaseInfo.okToFail(); } virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) unexpectedExceptions++; return CumulativeReporterBase::assertionEnded( assertionStats ); } virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { stdOutForSuite << testCaseStats.stdOut; stdErrForSuite << testCaseStats.stdErr; CumulativeReporterBase::testCaseEnded( testCaseStats ); } virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { double suiteTime = suiteTimer.getElapsedSeconds(); CumulativeReporterBase::testGroupEnded( testGroupStats ); writeGroup( *m_testGroups.back(), suiteTime ); } virtual void testRunEndedCumulative() CATCH_OVERRIDE { xml.endElement(); } void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); TestGroupStats const& stats = groupNode.value; xml.writeAttribute( "name", stats.groupInfo.name ); xml.writeAttribute( "errors", unexpectedExceptions ); xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); xml.writeAttribute( "tests", stats.totals.assertions.total() ); xml.writeAttribute( "hostname", "tbd" ); // !TBD if( m_config->showDurations() == ShowDurations::Never ) xml.writeAttribute( "time", "" ); else xml.writeAttribute( "time", suiteTime ); xml.writeAttribute( "timestamp", getCurrentTimestamp() ); // Write test cases for( TestGroupNode::ChildNodes::const_iterator it = groupNode.children.begin(), itEnd = groupNode.children.end(); it != itEnd; ++it ) writeTestCase( **it ); xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); } void writeTestCase( TestCaseNode const& testCaseNode ) { TestCaseStats const& stats = testCaseNode.value; // All test cases have exactly one section - which represents the // test case itself. That section may have 0-n nested sections assert( testCaseNode.children.size() == 1 ); SectionNode const& rootSection = *testCaseNode.children.front(); std::string className = stats.testInfo.className; if( className.empty() ) { if( rootSection.childSections.empty() ) className = "global"; } writeSection( className, "", rootSection ); } void writeSection( std::string const& className, std::string const& rootName, SectionNode const& sectionNode ) { std::string name = trim( sectionNode.stats.sectionInfo.name ); if( !rootName.empty() ) name = rootName + '/' + name; if( !sectionNode.assertions.empty() || !sectionNode.stdOut.empty() || !sectionNode.stdErr.empty() ) { XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); if( className.empty() ) { xml.writeAttribute( "classname", name ); xml.writeAttribute( "name", "root" ); } else { xml.writeAttribute( "classname", className ); xml.writeAttribute( "name", name ); } xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); writeAssertions( sectionNode ); if( !sectionNode.stdOut.empty() ) xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); if( !sectionNode.stdErr.empty() ) xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); } for( SectionNode::ChildSections::const_iterator it = sectionNode.childSections.begin(), itEnd = sectionNode.childSections.end(); it != itEnd; ++it ) if( className.empty() ) writeSection( name, "", **it ); else writeSection( className, name, **it ); } void writeAssertions( SectionNode const& sectionNode ) { for( SectionNode::Assertions::const_iterator it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); it != itEnd; ++it ) writeAssertion( *it ); } void writeAssertion( AssertionStats const& stats ) { AssertionResult const& result = stats.assertionResult; if( !result.isOk() ) { std::string elementName; switch( result.getResultType() ) { case ResultWas::ThrewException: case ResultWas::FatalErrorCondition: elementName = "error"; break; case ResultWas::ExplicitFailure: elementName = "failure"; break; case ResultWas::ExpressionFailed: elementName = "failure"; break; case ResultWas::DidntThrowException: elementName = "failure"; break; // We should never see these here: case ResultWas::Info: case ResultWas::Warning: case ResultWas::Ok: case ResultWas::Unknown: case ResultWas::FailureBit: case ResultWas::Exception: elementName = "internalError"; break; } XmlWriter::ScopedElement e = xml.scopedElement( elementName ); xml.writeAttribute( "message", result.getExpandedExpression() ); xml.writeAttribute( "type", result.getTestMacroName() ); std::ostringstream oss; if( !result.getMessage().empty() ) oss << result.getMessage() << '\n'; for( std::vector::const_iterator it = stats.infoMessages.begin(), itEnd = stats.infoMessages.end(); it != itEnd; ++it ) if( it->type == ResultWas::Info ) oss << it->message << '\n'; oss << "at " << result.getSourceInfo(); xml.writeText( oss.str(), false ); } } XmlWriter xml; Timer suiteTimer; std::ostringstream stdOutForSuite; std::ostringstream stdErrForSuite; unsigned int unexpectedExceptions; bool m_okToFail; }; INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) } // end namespace Catch // #included from: ../reporters/catch_reporter_console.hpp #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED #include #include namespace Catch { struct ConsoleReporter : StreamingReporterBase { ConsoleReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), m_headerPrinted( false ) {} virtual ~ConsoleReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as plain lines of text"; } virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { stream << "No test cases matched '" << spec << '\'' << std::endl; } virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { AssertionResult const& result = _assertionStats.assertionResult; bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); // Drop out if result was successful but we're not printing them. if( !includeResults && result.getResultType() != ResultWas::Warning ) return false; lazyPrint(); AssertionPrinter printer( stream, _assertionStats, includeResults ); printer.print(); stream << std::endl; return true; } virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_headerPrinted = false; StreamingReporterBase::sectionStarting( _sectionInfo ); } virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { if( _sectionStats.missingAssertions ) { lazyPrint(); Colour colour( Colour::ResultError ); if( m_sectionStack.size() > 1 ) stream << "\nNo assertions in section"; else stream << "\nNo assertions in test case"; stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; } if( m_config->showDurations() == ShowDurations::Always ) { stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; } if( m_headerPrinted ) { m_headerPrinted = false; } StreamingReporterBase::sectionEnded( _sectionStats ); } virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { if( currentGroupInfo.used ) { printSummaryDivider(); stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; printTotals( _testGroupStats.totals ); stream << '\n' << std::endl; } StreamingReporterBase::testGroupEnded( _testGroupStats ); } virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { printTotalsDivider( _testRunStats.totals ); printTotals( _testRunStats.totals ); stream << std::endl; StreamingReporterBase::testRunEnded( _testRunStats ); } private: class AssertionPrinter { void operator= ( AssertionPrinter const& ); public: AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) : stream( _stream ), stats( _stats ), result( _stats.assertionResult ), colour( Colour::None ), message( result.getMessage() ), messages( _stats.infoMessages ), printInfoMessages( _printInfoMessages ) { switch( result.getResultType() ) { case ResultWas::Ok: colour = Colour::Success; passOrFail = "PASSED"; //if( result.hasMessage() ) if( _stats.infoMessages.size() == 1 ) messageLabel = "with message"; if( _stats.infoMessages.size() > 1 ) messageLabel = "with messages"; break; case ResultWas::ExpressionFailed: if( result.isOk() ) { colour = Colour::Success; passOrFail = "FAILED - but was ok"; } else { colour = Colour::Error; passOrFail = "FAILED"; } if( _stats.infoMessages.size() == 1 ) messageLabel = "with message"; if( _stats.infoMessages.size() > 1 ) messageLabel = "with messages"; break; case ResultWas::ThrewException: colour = Colour::Error; passOrFail = "FAILED"; messageLabel = "due to unexpected exception with "; if (_stats.infoMessages.size() == 1) messageLabel += "message"; if (_stats.infoMessages.size() > 1) messageLabel += "messages"; break; case ResultWas::FatalErrorCondition: colour = Colour::Error; passOrFail = "FAILED"; messageLabel = "due to a fatal error condition"; break; case ResultWas::DidntThrowException: colour = Colour::Error; passOrFail = "FAILED"; messageLabel = "because no exception was thrown where one was expected"; break; case ResultWas::Info: messageLabel = "info"; break; case ResultWas::Warning: messageLabel = "warning"; break; case ResultWas::ExplicitFailure: passOrFail = "FAILED"; colour = Colour::Error; if( _stats.infoMessages.size() == 1 ) messageLabel = "explicitly with message"; if( _stats.infoMessages.size() > 1 ) messageLabel = "explicitly with messages"; break; // These cases are here to prevent compiler warnings case ResultWas::Unknown: case ResultWas::FailureBit: case ResultWas::Exception: passOrFail = "** internal error **"; colour = Colour::Error; break; } } void print() const { printSourceInfo(); if( stats.totals.assertions.total() > 0 ) { if( result.isOk() ) stream << '\n'; printResultType(); printOriginalExpression(); printReconstructedExpression(); } else { stream << '\n'; } printMessage(); } private: void printResultType() const { if( !passOrFail.empty() ) { Colour colourGuard( colour ); stream << passOrFail << ":\n"; } } void printOriginalExpression() const { if( result.hasExpression() ) { Colour colourGuard( Colour::OriginalExpression ); stream << " "; stream << result.getExpressionInMacro(); stream << '\n'; } } void printReconstructedExpression() const { if( result.hasExpandedExpression() ) { stream << "with expansion:\n"; Colour colourGuard( Colour::ReconstructedExpression ); stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n'; } } void printMessage() const { if( !messageLabel.empty() ) stream << messageLabel << ':' << '\n'; for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); it != itEnd; ++it ) { // If this assertion is a warning ignore any INFO messages if( printInfoMessages || it->type != ResultWas::Info ) stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n'; } } void printSourceInfo() const { Colour colourGuard( Colour::FileName ); stream << result.getSourceInfo() << ": "; } std::ostream& stream; AssertionStats const& stats; AssertionResult const& result; Colour::Code colour; std::string passOrFail; std::string messageLabel; std::string message; std::vector messages; bool printInfoMessages; }; void lazyPrint() { if( !currentTestRunInfo.used ) lazyPrintRunInfo(); if( !currentGroupInfo.used ) lazyPrintGroupInfo(); if( !m_headerPrinted ) { printTestCaseAndSectionHeader(); m_headerPrinted = true; } } void lazyPrintRunInfo() { stream << '\n' << getLineOfChars<'~'>() << '\n'; Colour colour( Colour::SecondaryText ); stream << currentTestRunInfo->name << " is a Catch v" << libraryVersion() << " host application.\n" << "Run with -? for options\n\n"; if( m_config->rngSeed() != 0 ) stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; currentTestRunInfo.used = true; } void lazyPrintGroupInfo() { if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { printClosedHeader( "Group: " + currentGroupInfo->name ); currentGroupInfo.used = true; } } void printTestCaseAndSectionHeader() { assert( !m_sectionStack.empty() ); printOpenHeader( currentTestCaseInfo->name ); if( m_sectionStack.size() > 1 ) { Colour colourGuard( Colour::Headers ); std::vector::const_iterator it = m_sectionStack.begin()+1, // Skip first section (test case) itEnd = m_sectionStack.end(); for( ; it != itEnd; ++it ) printHeaderString( it->name, 2 ); } SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; if( !lineInfo.empty() ){ stream << getLineOfChars<'-'>() << '\n'; Colour colourGuard( Colour::FileName ); stream << lineInfo << '\n'; } stream << getLineOfChars<'.'>() << '\n' << std::endl; } void printClosedHeader( std::string const& _name ) { printOpenHeader( _name ); stream << getLineOfChars<'.'>() << '\n'; } void printOpenHeader( std::string const& _name ) { stream << getLineOfChars<'-'>() << '\n'; { Colour colourGuard( Colour::Headers ); printHeaderString( _name ); } } // if string has a : in first line will set indent to follow it on // subsequent lines void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { std::size_t i = _string.find( ": " ); if( i != std::string::npos ) i+=2; else i = 0; stream << Text( _string, TextAttributes() .setIndent( indent+i) .setInitialIndent( indent ) ) << '\n'; } struct SummaryColumn { SummaryColumn( std::string const& _label, Colour::Code _colour ) : label( _label ), colour( _colour ) {} SummaryColumn addRow( std::size_t count ) { std::ostringstream oss; oss << count; std::string row = oss.str(); for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { while( it->size() < row.size() ) *it = ' ' + *it; while( it->size() > row.size() ) row = ' ' + row; } rows.push_back( row ); return *this; } std::string label; Colour::Code colour; std::vector rows; }; void printTotals( Totals const& totals ) { if( totals.testCases.total() == 0 ) { stream << Colour( Colour::Warning ) << "No tests ran\n"; } else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { stream << Colour( Colour::ResultSuccess ) << "All tests passed"; stream << " (" << pluralise( totals.assertions.passed, "assertion" ) << " in " << pluralise( totals.testCases.passed, "test case" ) << ')' << '\n'; } else { std::vector columns; columns.push_back( SummaryColumn( "", Colour::None ) .addRow( totals.testCases.total() ) .addRow( totals.assertions.total() ) ); columns.push_back( SummaryColumn( "passed", Colour::Success ) .addRow( totals.testCases.passed ) .addRow( totals.assertions.passed ) ); columns.push_back( SummaryColumn( "failed", Colour::ResultError ) .addRow( totals.testCases.failed ) .addRow( totals.assertions.failed ) ); columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) .addRow( totals.testCases.failedButOk ) .addRow( totals.assertions.failedButOk ) ); printSummaryRow( "test cases", columns, 0 ); printSummaryRow( "assertions", columns, 1 ); } } void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { std::string value = it->rows[row]; if( it->label.empty() ) { stream << label << ": "; if( value != "0" ) stream << value; else stream << Colour( Colour::Warning ) << "- none -"; } else if( value != "0" ) { stream << Colour( Colour::LightGrey ) << " | "; stream << Colour( it->colour ) << value << ' ' << it->label; } } stream << '\n'; } static std::size_t makeRatio( std::size_t number, std::size_t total ) { std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; return ( ratio == 0 && number > 0 ) ? 1 : ratio; } static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { if( i > j && i > k ) return i; else if( j > k ) return j; else return k; } void printTotalsDivider( Totals const& totals ) { if( totals.testCases.total() > 0 ) { std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) findMax( failedRatio, failedButOkRatio, passedRatio )++; while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) findMax( failedRatio, failedButOkRatio, passedRatio )--; stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); if( totals.testCases.allPassed() ) stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); else stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); } else { stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); } stream << '\n'; } void printSummaryDivider() { stream << getLineOfChars<'-'>() << '\n'; } private: bool m_headerPrinted; }; INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) } // end namespace Catch // #included from: ../reporters/catch_reporter_compact.hpp #define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED namespace Catch { struct CompactReporter : StreamingReporterBase { CompactReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ) {} virtual ~CompactReporter(); static std::string getDescription() { return "Reports test results on a single line, suitable for IDEs"; } virtual ReporterPreferences getPreferences() const { ReporterPreferences prefs; prefs.shouldRedirectStdOut = false; return prefs; } virtual void noMatchingTestCases( std::string const& spec ) { stream << "No test cases matched '" << spec << '\'' << std::endl; } virtual void assertionStarting( AssertionInfo const& ) {} virtual bool assertionEnded( AssertionStats const& _assertionStats ) { AssertionResult const& result = _assertionStats.assertionResult; bool printInfoMessages = true; // Drop out if result was successful and we're not printing those if( !m_config->includeSuccessfulResults() && result.isOk() ) { if( result.getResultType() != ResultWas::Warning ) return false; printInfoMessages = false; } AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); printer.print(); stream << std::endl; return true; } virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE { if (m_config->showDurations() == ShowDurations::Always) { stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; } } virtual void testRunEnded( TestRunStats const& _testRunStats ) { printTotals( _testRunStats.totals ); stream << '\n' << std::endl; StreamingReporterBase::testRunEnded( _testRunStats ); } private: class AssertionPrinter { void operator= ( AssertionPrinter const& ); public: AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) : stream( _stream ) , stats( _stats ) , result( _stats.assertionResult ) , messages( _stats.infoMessages ) , itMessage( _stats.infoMessages.begin() ) , printInfoMessages( _printInfoMessages ) {} void print() { printSourceInfo(); itMessage = messages.begin(); switch( result.getResultType() ) { case ResultWas::Ok: printResultType( Colour::ResultSuccess, passedString() ); printOriginalExpression(); printReconstructedExpression(); if ( ! result.hasExpression() ) printRemainingMessages( Colour::None ); else printRemainingMessages(); break; case ResultWas::ExpressionFailed: if( result.isOk() ) printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); else printResultType( Colour::Error, failedString() ); printOriginalExpression(); printReconstructedExpression(); printRemainingMessages(); break; case ResultWas::ThrewException: printResultType( Colour::Error, failedString() ); printIssue( "unexpected exception with message:" ); printMessage(); printExpressionWas(); printRemainingMessages(); break; case ResultWas::FatalErrorCondition: printResultType( Colour::Error, failedString() ); printIssue( "fatal error condition with message:" ); printMessage(); printExpressionWas(); printRemainingMessages(); break; case ResultWas::DidntThrowException: printResultType( Colour::Error, failedString() ); printIssue( "expected exception, got none" ); printExpressionWas(); printRemainingMessages(); break; case ResultWas::Info: printResultType( Colour::None, "info" ); printMessage(); printRemainingMessages(); break; case ResultWas::Warning: printResultType( Colour::None, "warning" ); printMessage(); printRemainingMessages(); break; case ResultWas::ExplicitFailure: printResultType( Colour::Error, failedString() ); printIssue( "explicitly" ); printRemainingMessages( Colour::None ); break; // These cases are here to prevent compiler warnings case ResultWas::Unknown: case ResultWas::FailureBit: case ResultWas::Exception: printResultType( Colour::Error, "** internal error **" ); break; } } private: // Colour::LightGrey static Colour::Code dimColour() { return Colour::FileName; } #ifdef CATCH_PLATFORM_MAC static const char* failedString() { return "FAILED"; } static const char* passedString() { return "PASSED"; } #else static const char* failedString() { return "failed"; } static const char* passedString() { return "passed"; } #endif void printSourceInfo() const { Colour colourGuard( Colour::FileName ); stream << result.getSourceInfo() << ':'; } void printResultType( Colour::Code colour, std::string const& passOrFail ) const { if( !passOrFail.empty() ) { { Colour colourGuard( colour ); stream << ' ' << passOrFail; } stream << ':'; } } void printIssue( std::string const& issue ) const { stream << ' ' << issue; } void printExpressionWas() { if( result.hasExpression() ) { stream << ';'; { Colour colour( dimColour() ); stream << " expression was:"; } printOriginalExpression(); } } void printOriginalExpression() const { if( result.hasExpression() ) { stream << ' ' << result.getExpression(); } } void printReconstructedExpression() const { if( result.hasExpandedExpression() ) { { Colour colour( dimColour() ); stream << " for: "; } stream << result.getExpandedExpression(); } } void printMessage() { if ( itMessage != messages.end() ) { stream << " '" << itMessage->message << '\''; ++itMessage; } } void printRemainingMessages( Colour::Code colour = dimColour() ) { if ( itMessage == messages.end() ) return; // using messages.end() directly yields compilation error: std::vector::const_iterator itEnd = messages.end(); const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); { Colour colourGuard( colour ); stream << " with " << pluralise( N, "message" ) << ':'; } for(; itMessage != itEnd; ) { // If this assertion is a warning ignore any INFO messages if( printInfoMessages || itMessage->type != ResultWas::Info ) { stream << " '" << itMessage->message << '\''; if ( ++itMessage != itEnd ) { Colour colourGuard( dimColour() ); stream << " and"; } } } } private: std::ostream& stream; AssertionStats const& stats; AssertionResult const& result; std::vector messages; std::vector::const_iterator itMessage; bool printInfoMessages; }; // Colour, message variants: // - white: No tests ran. // - red: Failed [both/all] N test cases, failed [both/all] M assertions. // - white: Passed [both/all] N test cases (no assertions). // - red: Failed N tests cases, failed M assertions. // - green: Passed [both/all] N tests cases with M assertions. std::string bothOrAll( std::size_t count ) const { return count == 1 ? std::string() : count == 2 ? "both " : "all " ; } void printTotals( const Totals& totals ) const { if( totals.testCases.total() == 0 ) { stream << "No tests ran."; } else if( totals.testCases.failed == totals.testCases.total() ) { Colour colour( Colour::ResultError ); const std::string qualify_assertions_failed = totals.assertions.failed == totals.assertions.total() ? bothOrAll( totals.assertions.failed ) : std::string(); stream << "Failed " << bothOrAll( totals.testCases.failed ) << pluralise( totals.testCases.failed, "test case" ) << ", " "failed " << qualify_assertions_failed << pluralise( totals.assertions.failed, "assertion" ) << '.'; } else if( totals.assertions.total() == 0 ) { stream << "Passed " << bothOrAll( totals.testCases.total() ) << pluralise( totals.testCases.total(), "test case" ) << " (no assertions)."; } else if( totals.assertions.failed ) { Colour colour( Colour::ResultError ); stream << "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.'; } else { Colour colour( Colour::ResultSuccess ); stream << "Passed " << bothOrAll( totals.testCases.passed ) << pluralise( totals.testCases.passed, "test case" ) << " with " << pluralise( totals.assertions.passed, "assertion" ) << '.'; } } }; INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) } // end namespace Catch namespace Catch { // These are all here to avoid warnings about not having any out of line // virtual methods NonCopyable::~NonCopyable() {} IShared::~IShared() {} IStream::~IStream() CATCH_NOEXCEPT {} FileStream::~FileStream() CATCH_NOEXCEPT {} CoutStream::~CoutStream() CATCH_NOEXCEPT {} DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} IContext::~IContext() {} IResultCapture::~IResultCapture() {} ITestCase::~ITestCase() {} ITestCaseRegistry::~ITestCaseRegistry() {} IRegistryHub::~IRegistryHub() {} IMutableRegistryHub::~IMutableRegistryHub() {} IExceptionTranslator::~IExceptionTranslator() {} IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} IReporter::~IReporter() {} IReporterFactory::~IReporterFactory() {} IReporterRegistry::~IReporterRegistry() {} IStreamingReporter::~IStreamingReporter() {} AssertionStats::~AssertionStats() {} SectionStats::~SectionStats() {} TestCaseStats::~TestCaseStats() {} TestGroupStats::~TestGroupStats() {} TestRunStats::~TestRunStats() {} CumulativeReporterBase::SectionNode::~SectionNode() {} CumulativeReporterBase::~CumulativeReporterBase() {} StreamingReporterBase::~StreamingReporterBase() {} ConsoleReporter::~ConsoleReporter() {} CompactReporter::~CompactReporter() {} IRunner::~IRunner() {} IMutableContext::~IMutableContext() {} IConfig::~IConfig() {} XmlReporter::~XmlReporter() {} JunitReporter::~JunitReporter() {} TestRegistry::~TestRegistry() {} FreeFunctionTestCase::~FreeFunctionTestCase() {} IGeneratorInfo::~IGeneratorInfo() {} IGeneratorsForTest::~IGeneratorsForTest() {} WildcardPattern::~WildcardPattern() {} TestSpec::Pattern::~Pattern() {} TestSpec::NamePattern::~NamePattern() {} TestSpec::TagPattern::~TagPattern() {} TestSpec::ExcludedPattern::~ExcludedPattern() {} Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {} void Config::dummy() {} namespace TestCaseTracking { ITracker::~ITracker() {} TrackerBase::~TrackerBase() {} SectionTracker::~SectionTracker() {} IndexTracker::~IndexTracker() {} } } #ifdef __clang__ #pragma clang diagnostic pop #endif #endif #ifdef CATCH_CONFIG_MAIN // #included from: internal/catch_default_main.hpp #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED #ifndef __OBJC__ #if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) // Standard C/C++ Win32 Unicode wmain entry point extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { #else // Standard C/C++ main entry point int main (int argc, char * argv[]) { #endif int result = Catch::Session().run( argc, argv ); return ( result < 0xff ? result : 0xff ); } #else // __OBJC__ // Objective-C entry point int main (int argc, char * const argv[]) { #if !CATCH_ARC_ENABLED NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; #endif Catch::registerTestMethods(); int result = Catch::Session().run( argc, (char* const*)argv ); #if !CATCH_ARC_ENABLED [pool drain]; #endif return ( result < 0xff ? result : 0xff ); } #endif // __OBJC__ #endif #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED # undef CLARA_CONFIG_MAIN #endif ////// // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ #ifdef CATCH_CONFIG_PREFIX_ALL #if defined(CATCH_CONFIG_FAST_COMPILE) #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) #else #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) #endif #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) #define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) #if defined(CATCH_CONFIG_FAST_COMPILE) #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) #else #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) #endif #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) #ifdef CATCH_CONFIG_VARIADIC_MACROS #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #else #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) #define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) #endif #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) #define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) // "BDD-style" convenience wrappers #ifdef CATCH_CONFIG_VARIADIC_MACROS #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #else #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif #define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) #define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) #define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) #define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) #define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required #else #if defined(CATCH_CONFIG_FAST_COMPILE) #define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr ) #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) #else #define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr ) #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) #endif #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) #define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) #define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) #if defined(CATCH_CONFIG_FAST_COMPILE) #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) #else #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) #endif #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) #ifdef CATCH_CONFIG_VARIADIC_MACROS #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #else #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define FAIL( msg ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) #define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) #define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) #endif #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) #define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) #endif #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) // "BDD-style" convenience wrappers #ifdef CATCH_CONFIG_VARIADIC_MACROS #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #else #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif #define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) #define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) #define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) #define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) #define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) using Catch::Detail::Approx; // #included from: internal/catch_reenable_warnings.h #define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro # pragma warning(pop) # else # pragma clang diagnostic pop # endif #elif defined __GNUC__ # pragma GCC diagnostic pop #endif #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED measurement-kit-0.7.1/include/private/ext/http_parser.h000066400000000000000000000331011315356162600232400ustar00rootroot00000000000000/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. * * 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. */ #ifndef http_parser_h #define http_parser_h #ifdef __cplusplus extern "C" { #endif /* Also update SONAME in the Makefile whenever you change these. */ #define HTTP_PARSER_VERSION_MAJOR 2 #define HTTP_PARSER_VERSION_MINOR 7 #define HTTP_PARSER_VERSION_PATCH 1 #include #if defined(_WIN32) && !defined(__MINGW32__) && \ (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__) #include #include typedef __int8 int8_t; typedef unsigned __int8 uint8_t; typedef __int16 int16_t; typedef unsigned __int16 uint16_t; typedef __int32 int32_t; typedef unsigned __int32 uint32_t; typedef __int64 int64_t; typedef unsigned __int64 uint64_t; #else #include #endif /* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run * faster */ #ifndef HTTP_PARSER_STRICT # define HTTP_PARSER_STRICT 1 #endif /* Maximium header size allowed. If the macro is not defined * before including this header then the default is used. To * change the maximum header size, define the macro in the build * environment (e.g. -DHTTP_MAX_HEADER_SIZE=). To remove * the effective limit on the size of the header, define the macro * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) */ #ifndef HTTP_MAX_HEADER_SIZE # define HTTP_MAX_HEADER_SIZE (80*1024) #endif typedef struct http_parser http_parser; typedef struct http_parser_settings http_parser_settings; /* Callbacks should return non-zero to indicate an error. The parser will * then halt execution. * * The one exception is on_headers_complete. In a HTTP_RESPONSE parser * returning '1' from on_headers_complete will tell the parser that it * should not expect a body. This is used when receiving a response to a * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: * chunked' headers that indicate the presence of a body. * * Returning `2` from on_headers_complete will tell parser that it should not * expect neither a body nor any futher responses on this connection. This is * useful for handling responses to a CONNECT request which may not contain * `Upgrade` or `Connection: upgrade` headers. * * http_data_cb does not return data chunks. It will be called arbitrarily * many times for each string. E.G. you might get 10 callbacks for "on_url" * each providing just a few characters more data. */ typedef int (*http_data_cb) (http_parser*, const char *at, size_t length); typedef int (*http_cb) (http_parser*); /* Request Methods */ #define HTTP_METHOD_MAP(XX) \ XX(0, DELETE, DELETE) \ XX(1, GET, GET) \ XX(2, HEAD, HEAD) \ XX(3, POST, POST) \ XX(4, PUT, PUT) \ /* pathological */ \ XX(5, CONNECT, CONNECT) \ XX(6, OPTIONS, OPTIONS) \ XX(7, TRACE, TRACE) \ /* WebDAV */ \ XX(8, COPY, COPY) \ XX(9, LOCK, LOCK) \ XX(10, MKCOL, MKCOL) \ XX(11, MOVE, MOVE) \ XX(12, PROPFIND, PROPFIND) \ XX(13, PROPPATCH, PROPPATCH) \ XX(14, SEARCH, SEARCH) \ XX(15, UNLOCK, UNLOCK) \ XX(16, BIND, BIND) \ XX(17, REBIND, REBIND) \ XX(18, UNBIND, UNBIND) \ XX(19, ACL, ACL) \ /* subversion */ \ XX(20, REPORT, REPORT) \ XX(21, MKACTIVITY, MKACTIVITY) \ XX(22, CHECKOUT, CHECKOUT) \ XX(23, MERGE, MERGE) \ /* upnp */ \ XX(24, MSEARCH, M-SEARCH) \ XX(25, NOTIFY, NOTIFY) \ XX(26, SUBSCRIBE, SUBSCRIBE) \ XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ /* RFC-5789 */ \ XX(28, PATCH, PATCH) \ XX(29, PURGE, PURGE) \ /* CalDAV */ \ XX(30, MKCALENDAR, MKCALENDAR) \ /* RFC-2068, section 19.6.1.2 */ \ XX(31, LINK, LINK) \ XX(32, UNLINK, UNLINK) \ enum http_method { #define XX(num, name, string) HTTP_##name = num, HTTP_METHOD_MAP(XX) #undef XX }; enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; /* Flag values for http_parser.flags field */ enum flags { F_CHUNKED = 1 << 0 , F_CONNECTION_KEEP_ALIVE = 1 << 1 , F_CONNECTION_CLOSE = 1 << 2 , F_CONNECTION_UPGRADE = 1 << 3 , F_TRAILING = 1 << 4 , F_UPGRADE = 1 << 5 , F_SKIPBODY = 1 << 6 , F_CONTENTLENGTH = 1 << 7 }; /* Map for errno-related constants * * The provided argument should be a macro that takes 2 arguments. */ #define HTTP_ERRNO_MAP(XX) \ /* No error */ \ XX(OK, "success") \ \ /* Callback-related errors */ \ XX(CB_message_begin, "the on_message_begin callback failed") \ XX(CB_url, "the on_url callback failed") \ XX(CB_header_field, "the on_header_field callback failed") \ XX(CB_header_value, "the on_header_value callback failed") \ XX(CB_headers_complete, "the on_headers_complete callback failed") \ XX(CB_body, "the on_body callback failed") \ XX(CB_message_complete, "the on_message_complete callback failed") \ XX(CB_status, "the on_status callback failed") \ XX(CB_chunk_header, "the on_chunk_header callback failed") \ XX(CB_chunk_complete, "the on_chunk_complete callback failed") \ \ /* Parsing-related errors */ \ XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ XX(HEADER_OVERFLOW, \ "too many header bytes seen; overflow detected") \ XX(CLOSED_CONNECTION, \ "data received after completed connection: close message") \ XX(INVALID_VERSION, "invalid HTTP version") \ XX(INVALID_STATUS, "invalid HTTP status code") \ XX(INVALID_METHOD, "invalid HTTP method") \ XX(INVALID_URL, "invalid URL") \ XX(INVALID_HOST, "invalid host") \ XX(INVALID_PORT, "invalid port") \ XX(INVALID_PATH, "invalid path") \ XX(INVALID_QUERY_STRING, "invalid query string") \ XX(INVALID_FRAGMENT, "invalid fragment") \ XX(LF_EXPECTED, "LF character expected") \ XX(INVALID_HEADER_TOKEN, "invalid character in header") \ XX(INVALID_CONTENT_LENGTH, \ "invalid character in content-length header") \ XX(UNEXPECTED_CONTENT_LENGTH, \ "unexpected content-length header") \ XX(INVALID_CHUNK_SIZE, \ "invalid character in chunk size header") \ XX(INVALID_CONSTANT, "invalid constant string") \ XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ XX(STRICT, "strict mode assertion failed") \ XX(PAUSED, "parser is paused") \ XX(UNKNOWN, "an unknown error occurred") /* Define HPE_* values for each errno value above */ #define HTTP_ERRNO_GEN(n, s) HPE_##n, enum http_errno { HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) }; #undef HTTP_ERRNO_GEN /* Get an http_errno value from an http_parser */ #define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) struct http_parser { /** PRIVATE **/ unsigned int type : 2; /* enum http_parser_type */ unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */ unsigned int state : 7; /* enum state from http_parser.c */ unsigned int header_state : 7; /* enum header_state from http_parser.c */ unsigned int index : 7; /* index into current matcher */ unsigned int lenient_http_headers : 1; uint32_t nread; /* # bytes read in various scenarios */ uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ /** READ-ONLY **/ unsigned short http_major; unsigned short http_minor; unsigned int status_code : 16; /* responses only */ unsigned int method : 8; /* requests only */ unsigned int http_errno : 7; /* 1 = Upgrade header was present and the parser has exited because of that. * 0 = No upgrade header present. * Should be checked when http_parser_execute() returns in addition to * error checking. */ unsigned int upgrade : 1; /** PUBLIC **/ void *data; /* A pointer to get hook to the "connection" or "socket" object */ }; struct http_parser_settings { http_cb on_message_begin; http_data_cb on_url; http_data_cb on_status; http_data_cb on_header_field; http_data_cb on_header_value; http_cb on_headers_complete; http_data_cb on_body; http_cb on_message_complete; /* When on_chunk_header is called, the current chunk length is stored * in parser->content_length. */ http_cb on_chunk_header; http_cb on_chunk_complete; }; enum http_parser_url_fields { UF_SCHEMA = 0 , UF_HOST = 1 , UF_PORT = 2 , UF_PATH = 3 , UF_QUERY = 4 , UF_FRAGMENT = 5 , UF_USERINFO = 6 , UF_MAX = 7 }; /* Result structure for http_parser_parse_url(). * * Callers should index into field_data[] with UF_* values iff field_set * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and * because we probably have padding left over), we convert any port to * a uint16_t. */ struct http_parser_url { uint16_t field_set; /* Bitmask of (1 << UF_*) values */ uint16_t port; /* Converted UF_PORT string */ struct { uint16_t off; /* Offset into buffer in which field starts */ uint16_t len; /* Length of run in buffer */ } field_data[UF_MAX]; }; /* Returns the library version. Bits 16-23 contain the major version number, * bits 8-15 the minor version number and bits 0-7 the patch level. * Usage example: * * unsigned long version = http_parser_version(); * unsigned major = (version >> 16) & 255; * unsigned minor = (version >> 8) & 255; * unsigned patch = version & 255; * printf("http_parser v%u.%u.%u\n", major, minor, patch); */ unsigned long http_parser_version(void); void http_parser_init(http_parser *parser, enum http_parser_type type); /* Initialize http_parser_settings members to 0 */ void http_parser_settings_init(http_parser_settings *settings); /* Executes the parser. Returns number of parsed bytes. Sets * `parser->http_errno` on error. */ size_t http_parser_execute(http_parser *parser, const http_parser_settings *settings, const char *data, size_t len); /* If http_should_keep_alive() in the on_headers_complete or * on_message_complete callback returns 0, then this should be * the last message on the connection. * If you are the server, respond with the "Connection: close" header. * If you are the client, close the connection. */ int http_should_keep_alive(const http_parser *parser); /* Returns a string version of the HTTP method. */ const char *http_method_str(enum http_method m); /* Return a string name of the given error */ const char *http_errno_name(enum http_errno err); /* Return a string description of the given error */ const char *http_errno_description(enum http_errno err); /* Initialize all http_parser_url members to 0 */ void http_parser_url_init(struct http_parser_url *u); /* Parse a URL; return nonzero on failure */ int http_parser_parse_url(const char *buf, size_t buflen, int is_connect, struct http_parser_url *u); /* Pause or un-pause the parser; a nonzero value pauses */ void http_parser_pause(http_parser *parser, int paused); /* Checks if this is the final chunk of the body. */ int http_body_is_final(const http_parser *parser); #ifdef __cplusplus } #endif #endif measurement-kit-0.7.1/include/private/ext/tls_internal.h000066400000000000000000000021011315356162600233770ustar00rootroot00000000000000/* * This is a mock of tls_internal.h filling out all the functions that are * called by tls_verify with mocks. */ #ifndef PRIVATE_EXT_TLS_INTERNAL_H #define PRIVATE_EXT_TLS_INTERNAL_H #include #include struct tls { char *errmsg; int errnum; }; union tls_addr { struct in_addr ip4; struct in6_addr ip6; }; #ifdef __cplusplus extern "C" { #endif int tls_check_name(struct tls *ctx, X509 *cert, const char *name, int *match); #ifdef __cplusplus } #endif /* * Empty mocks for the tls_set_error* functions. One of them must be a * function such that we can ignore arguments. This is done to ensure * the compiler doesn't report warnings for `ctx` being unused. */ static inline void tls_set_errorx(struct tls *ctx, const char *errmsg, ...) __attribute__((format(printf, 2, 3))); static inline void tls_set_errorx(struct tls *ctx, const char *errmsg, ...) { (void)ctx; (void)errmsg; /* do nothing */ ; } #define tls_set_error tls_set_errorx #endif /* SRC_EXT_TLS_INTERNAL_H */ measurement-kit-0.7.1/include/private/http/000077500000000000000000000000001315356162600207155ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/http/request_impl.hpp000066400000000000000000000057071315356162600241500ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_HTTP_REQUEST_IMPL_HPP #define PRIVATE_HTTP_REQUEST_IMPL_HPP #include "private/common/json.hpp" #include "private/common/mock.hpp" #include "private/common/json.hpp" #include "private/common/mock.hpp" #include "../http/response_parser.hpp" #include namespace mk { namespace http { // TODO: mock more functions in request.cpp template void request_connect_impl(Settings settings, Callback> cb, Var reactor = Reactor::global(), Var logger = Logger::global()) { if (settings.find("http/url") == settings.end()) { cb(MissingUrlError(), nullptr); return; } ErrorOr url = parse_url_noexcept(settings.at("http/url")); if (!url) { cb(url.as_error(), nullptr); return; } if (url->schema == "httpo") { // tor_socks_port takes precedence because it's more specific if (settings.find("net/tor_socks_port") != settings.end()) { // XXX The following is a violation of layers because we are // setting a variable that NET code should set for itself; we // should do nothing in this case, lower layer should do std::string proxy = "127.0.0.1:"; proxy += settings["net/tor_socks_port"]; settings["net/socks5_proxy"] = proxy; } else if (settings.find("net/socks5_proxy") == settings.end()) { settings["net/socks5_proxy"] = "127.0.0.1:9050"; } } else if (url->schema == "https") { settings["net/ssl"] = true; } net_connect(url->address, url->port, cb, settings, reactor, logger); } template void request_json_string_impl( std::string method, std::string url, std::string data, http::Headers headers, Callback, nlohmann::json> cb, Settings settings, Var reactor, Var logger) { settings["http/url"] = url; settings["http/method"] = method; headers["Content-Type"] = "application/json"; logger->debug("%s to %s (body: '%s')", method.c_str(), url.c_str(), data.c_str()); request(settings, headers, data, [=](Error error, Var response) { nlohmann::json jresponse; if (error) { cb(error, response, jresponse); return; } error = json_parse_and_process(response->body, [&](auto json) { jresponse = std::move(json); }); cb(error, response, jresponse); }, reactor, logger, nullptr, 0); } } // namespace http } // namespace mk #endif measurement-kit-0.7.1/include/private/http/response_parser.hpp000066400000000000000000000162211315356162600246420ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_HTTP_RESPONSE_PARSER_HPP #define PRIVATE_HTTP_RESPONSE_PARSER_HPP #include "../ext/http_parser.h" #include #include namespace mk { namespace http { using namespace mk::net; enum class HeaderParserState { NOTHING = 0, FIELD = 1, VALUE = 2, }; class ResponseParserNg : public NonCopyable, public NonMovable { public: ResponseParserNg(Var = Logger::global()); void on_begin(std::function fn) { begin_fn_ = fn; } void on_response(std::function fn) { response_fn_ = fn; } void on_body(std::function fn) { body_fn_ = fn; } void on_end(std::function fn) { end_fn_ = fn; } void feed(Buffer &data) { buffer_ << data; parse(); } void feed(std::string data) { buffer_ << data; parse(); } void feed(const char c) { buffer_.write((const void *)&c, 1); parse(); } void eof() { parser_execute(nullptr, 0); } int do_message_begin_() { logger_->log(MK_LOG_DEBUG2, "http: BEGIN"); response_ = Response(); prev_ = HeaderParserState::NOTHING; field_ = ""; value_ = ""; if (begin_fn_) { begin_fn_(); } return 0; } int do_status_(const char *s, size_t n) { logger_->log(MK_LOG_DEBUG2, "http: STATUS"); response_.reason.append(s, n); return 0; } int do_header_field_(const char *s, size_t n) { logger_->log(MK_LOG_DEBUG2, "http: FIELD"); do_header_internal(HeaderParserState::FIELD, s, n); return 0; } int do_header_value_(const char *s, size_t n) { logger_->log(MK_LOG_DEBUG2, "http: VALUE"); do_header_internal(HeaderParserState::VALUE, s, n); return 0; } int do_headers_complete_() { logger_->log(MK_LOG_DEBUG2, "http: HEADERS_COMPLETE"); if (field_ != "") { // Also copy last header response_.headers[field_] = value_; } response_.http_major = parser_.http_major; response_.status_code = parser_.status_code; response_.http_minor = parser_.http_minor; std::stringstream sst; sst << "HTTP/" << response_.http_major << "." << response_.http_minor << " " << response_.status_code << " " << response_.reason; response_.response_line = sst.str(); logger_->debug("< %s", response_.response_line.c_str()); for (auto kv : response_.headers) { logger_->debug("< %s: %s", kv.first.c_str(), kv.second.c_str()); } if (response_fn_) { response_fn_(response_); } return 0; } int do_body_(const char *s, size_t n) { logger_->log(MK_LOG_DEBUG2, "http: BODY"); if (body_fn_) { body_fn_(std::string(s, n)); } return 0; } int do_message_complete_() { logger_->log(MK_LOG_DEBUG2, "http: END"); if (end_fn_) { end_fn_(); } return 0; } private: Delegate<> begin_fn_; Delegate response_fn_; Delegate body_fn_; Delegate<> end_fn_; Var logger_ = Logger::global(); http_parser parser_; http_parser_settings settings_; Buffer buffer_; // Variables used during parsing Response response_; HeaderParserState prev_ = HeaderParserState::NOTHING; std::string field_; std::string value_; void do_header_internal(HeaderParserState cur, const char *s, size_t n) { using HPS = HeaderParserState; // // This implements the finite state machine described by the // documentation of joyent/http-parser. // // See github.com/joyent/http-parser/blob/master/README.md#callbacks // if (prev_ == HPS::NOTHING && cur == HPS::FIELD) { field_ = std::string(s, n); } else if (prev_ == HPS::VALUE && cur == HPS::FIELD) { response_.headers[field_] = value_; field_ = std::string(s, n); } else if (prev_ == HPS::FIELD && cur == HPS::FIELD) { field_.append(s, n); } else if (prev_ == HPS::FIELD && cur == HPS::VALUE) { value_ = std::string(s, n); } else if (prev_ == HPS::VALUE && cur == HPS::VALUE) { value_.append(s, n); } else { throw HeaderParserInternalError(); } prev_ = cur; } void parse() { size_t total = 0; buffer_.for_each([&](const void *p, size_t n) { total += parser_execute(p, n); return true; }); buffer_.discard(total); } size_t parser_execute(const void *p, size_t n) { size_t x = http_parser_execute(&parser_, &settings_, (const char *)p, n); if (parser_.upgrade) { throw UpgradeError(); } if (x != n) { throw ParserError(map_parser_error_()); } return n; } Error map_parser_error_() { switch (HTTP_PARSER_ERRNO(&parser_)) { case HPE_OK: return NoError(); case HPE_INVALID_EOF_STATE: return ParserInvalidEofStateError(); case HPE_HEADER_OVERFLOW: return ParserHeaderOverflowError(); case HPE_CLOSED_CONNECTION: return ParserClosedConnectionError(); case HPE_INVALID_VERSION: return ParserInvalidVersionError(); case HPE_INVALID_STATUS: return ParserInvalidStatusError(); case HPE_INVALID_METHOD: return ParserInvalidMethodError(); case HPE_INVALID_URL: return ParserInvalidUrlError(); case HPE_INVALID_HOST: return ParserInvalidHostError(); case HPE_INVALID_PORT: return ParserInvalidPortError(); case HPE_INVALID_PATH: return ParserInvalidPathError(); case HPE_INVALID_QUERY_STRING: return ParserInvalidQueryStringError(); case HPE_INVALID_FRAGMENT: return ParserInvalidFragmentError(); case HPE_LF_EXPECTED: return ParserLfExpectedError(); case HPE_INVALID_HEADER_TOKEN: return ParserInvalidHeaderTokenError(); case HPE_INVALID_CONTENT_LENGTH: return ParserInvalidContentLengthError(); case HPE_UNEXPECTED_CONTENT_LENGTH: return ParserUnexpectedContentLengthError(); case HPE_INVALID_CHUNK_SIZE: return ParserInvalidChunkSizeError(); case HPE_INVALID_CONSTANT: return ParserInvalidConstantError(); case HPE_INVALID_INTERNAL_STATE: return ParserInvalidInternalStateError(); case HPE_STRICT: return ParserStrictModeAssertionError(); case HPE_PAUSED: return ParserPausedError(); default: // FALLTHROUGH break; }; return GenericParserError(); /* Should not happen */ } }; } // namespace http } // namespace mk #endif measurement-kit-0.7.1/include/private/libevent/000077500000000000000000000000001315356162600215465ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/libevent/connection.hpp000066400000000000000000000073631315356162600244270ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_LIBEVENT_CONNECTION_HPP #define PRIVATE_LIBEVENT_CONNECTION_HPP #include "../net/utils.hpp" #include "../net/emitter.hpp" #include #include #include #include namespace mk { namespace libevent { using namespace mk::net; class Connection : public EmitterBase, public NonMovable, public NonCopyable { public: static Var make(bufferevent *bev, Var reactor, Var logger) { Connection *conn = new Connection(bev, reactor, logger); conn->self = Var(conn); return conn->self; } ~Connection() override { if (bev != nullptr) { bufferevent_free(bev); } } protected: void adjust_timeout(double timeout) override { timeval tv, *tvp = mk::timeval_init(&tv, timeout); bufferevent *underlying = bufferevent_get_underlying(this->bev); if (underlying) { // When we have a underlying bufferevent (i.e., a socket) set the // timeout to it rather than to the outer buffer because we have // seen running a long download that setting the timeout of the SSL // bufferevent leads to interrupted download due to timeout. if (bufferevent_set_timeouts(underlying, tvp, tvp) != 0) { throw std::runtime_error("cannot set timeout"); } return; } if (bufferevent_set_timeouts(this->bev, tvp, tvp) != 0) { throw std::runtime_error("cannot set timeout"); } } void start_writing() override { output_buff >> bufferevent_get_output(bev); } void start_reading() override { if (bufferevent_enable(this->bev, EV_READ) != 0) { throw std::runtime_error("cannot enable read"); } } void stop_reading() override { if (bufferevent_disable(this->bev, EV_READ) != 0) { throw std::runtime_error("cannot disable read"); } } void shutdown() override; template Endpoint sockname_peername_() { // Assumption: in the common case this operation won't fail. When it // fails, we'll just return an empty endpoint. assert(bev != nullptr); auto fd = bufferevent_getfd(bev); if (fd == -1) { logger->warn("connection: bufferevent attached to invalid socket"); return {}; } sockaddr_storage ss{}; socklen_t sslen = sizeof (ss); if (func(fd, (sockaddr *)&ss, &sslen) != 0) { logger->warn("connection: cannot get socket name / peer name"); return {}; } ErrorOr epnt = endpoint_from_sockaddr_storage(&ss); if (!epnt) { logger->warn("connection: cannot get endpoint from " "sockaddr_storage structure"); return {}; } return *epnt; } Endpoint sockname() override { return sockname_peername_<::getsockname>(); } Endpoint peername() override { return sockname_peername_<::getpeername>(); } // They MUST be public because they're called by C code public: void handle_event_(short); void handle_read_(); void handle_write_(); private: Connection(bufferevent *bev, Var, Var); bufferevent *bev = nullptr; Var self; Callback<> close_cb; bool suppressed_eof = false; bool shutdown_called = false; }; } // namespace libevent } // namespace mk #endif measurement-kit-0.7.1/include/private/libevent/dns.hpp000066400000000000000000000011731315356162600230450ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_LIBEVENT_DNS_HPP #define PRIVATE_LIBEVENT_DNS_HPP #include namespace mk { namespace libevent { void query( dns::QueryClass dns_class, dns::QueryType dns_type, std::string name, Callback> cb, Settings settings, Var reactor, Var logger ); Error dns_error(int code); } // namespace libevent } // namespace mk #endif measurement-kit-0.7.1/include/private/libevent/dns_impl.hpp000066400000000000000000000312321315356162600240650ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_DNS_QUERY_IMPL_HPP #define PRIVATE_DNS_QUERY_IMPL_HPP #include "private/common/mock.hpp" #include "private/common/mock.hpp" #include "../common/utils.hpp" #include "../net/utils.hpp" #include "../libevent/dns.hpp" #include #include #include #include #include #include extern "C" { void handle_resolve( int code, char type, int count, int ttl, void *addresses, void *opaque); } struct evdns_base; namespace mk { namespace libevent { using namespace mk::dns; class QueryContext : public NonMovable, public NonCopyable { public: ~QueryContext() { if (base != nullptr) { evdns_base_free(base, 0); } } double ticks; evdns_base *base = nullptr; Var message; Callback> callback; Var logger = Logger::global(); QueryContext( evdns_base *b, Callback> c, Var m, Var l = Logger::global()) { base = b; callback = c; message = m; ticks = mk::time_now(); logger = l; } }; struct evdns_base_deleter { void operator()(evdns_base* p) { constexpr int fail_requests = 1; evdns_base_free(p, fail_requests); } }; struct evaddrinfo_deleter { void operator()(evutil_addrinfo* p) { evutil_freeaddrinfo(p); } }; using evdns_base_uptr = std::unique_ptr; using evaddrinfo_uptr = std::unique_ptr; template static inline evdns_base *create_evdns_base( Settings settings, Var reactor = Reactor::global()) { event_base *evb = reactor->get_event_base(); const int initialize_nameservers = settings.count("dns/nameserver") ? 0 : 1; evdns_base_uptr base(evdns_base_new(evb, initialize_nameservers)); if (!base) { throw std::bad_alloc(); } if (!initialize_nameservers) { // libevent can't handle link-local IPv6 nameserver in // evdns_base_nameserver_ip_add, and there is no way to parse alike // addresses in platform-independent way, so that's why getaddrinfo(). // fe80::227:22ff:fe45:3a92%wlan0 -- Android // fe80::227:22ff:fe45:3a92%wlp1s0 -- Ubuntu Linux evutil_addrinfo hints = { }; hints.ai_family = PF_UNSPEC; hints.ai_flags = EVUTIL_AI_NUMERICSERV | EVUTIL_AI_NUMERICHOST; hints.ai_socktype = SOCK_DGRAM; evutil_addrinfo *res = nullptr; std::string port{"53"}; if (settings.count("dns/port")) { port = settings["dns/port"]; } const int eaierr = evutil_getaddrinfo(settings["dns/nameserver"].c_str(), port.c_str(), &hints, &res); evaddrinfo_uptr ai(res); if (eaierr) { throw std::runtime_error(std::string("Cannot parse server address: ") + evutil_gai_strerror(eaierr)); } constexpr unsigned unused = 0; // libevent API does not use it :-/ const int nserr = evdns_base_nameserver_sockaddr_add(base.get(), ai->ai_addr, ai->ai_addrlen, unused); if (nserr != 0) { throw std::runtime_error("Cannot set server address: " + std::to_string(nserr)); } } if (settings.find("dns/attempts") != settings.end() && evdns_base_set_option( base.get(), "attempts", settings["dns/attempts"].c_str()) != 0) { throw std::runtime_error("Cannot set 'attempts' option"); } if (settings.find("dns/timeout") != settings.end() && evdns_base_set_option( base.get(), "timeout", settings["dns/timeout"].c_str()) != 0) { throw std::runtime_error("Cannot set 'timeout' option"); } // By default we don't randomize the query's case // XXX check that randomize case is a valid value std::string randomiz{"0"}; if (settings.find("dns/randomize_case") != settings.end()) { randomiz = settings["dns/randomize_case"]; } if (evdns_base_set_option(base.get(), "randomize-case", randomiz.c_str()) != 0) { throw std::runtime_error("Cannot set 'randomize-case' option"); } return base.release(); } template static inline std::vector build_answers_evdns( int code, char type, int count, int ttl, void *addresses, Var logger = Logger::global()) { std::vector answers; if (code != DNS_ERR_NONE) { logger->debug("dns: request failed: %d", code); // do not process the results if there was an error } else if (type == DNS_PTR) { logger->debug("dns: PTR"); Answer answer; answer.code = code; answer.ttl = ttl; answer.type = MK_DNS_TYPE_PTR; // Note: cast magic copied from libevent regress tests answer.hostname = std::string(*(char **)addresses); logger->debug("dns: adding %s", answer.hostname.c_str()); answers.push_back(answer); } else if (type == DNS_IPv4_A || type == DNS_IPv6_AAAA) { int family; int size; char string[128]; // Is wide enough (max. IPv6 length is 45 chars) if (type == DNS_IPv4_A) { family = PF_INET; size = 4; logger->debug("dns: IPv4"); } else { family = PF_INET6; size = 16; logger->debug("dns: IPv6"); } // // Note: make sure in advance `i * size` won't overflow, // this is here only for robustness. // if (count >= 0 && count <= INT_MAX / size + 1) { for (auto i = 0; i < count; ++i) { // Note: address already in network byte order if (inet_ntop(family, (char *)addresses + i * size, string, sizeof(string)) == NULL) { logger->warn("dns: unexpected inet_ntop failure"); throw std::runtime_error("Unexpected inet_ntop failure"); } Answer answer; answer.code = code; answer.ttl = ttl; if (family == PF_INET) { answer.ipv4 = string; answer.type = MK_DNS_TYPE_A; } else if (family == PF_INET6) { answer.ipv6 = string; answer.type = MK_DNS_TYPE_AAAA; } logger->debug("dns: adding '%s'", string); answers.push_back(answer); } } else { logger->warn("dns: too many addresses"); throw std::runtime_error("We got more responses than the maximum " "integer size. Something is very wrong."); } } else { logger->warn("dns: invalid response type"); throw std::runtime_error("Invalid response type."); } return answers; } static inline void dns_callback(int code, char type, int count, int ttl, void *addresses, QueryContext *context) { context->message->error_code = code; switch (code) { case DNS_ERR_NONE: case DNS_ERR_FORMAT: case DNS_ERR_SERVERFAILED: case DNS_ERR_NOTEXIST: case DNS_ERR_NOTIMPL: case DNS_ERR_REFUSED: case DNS_ERR_TRUNCATED: case DNS_ERR_NODATA: context->message->rtt = mk::time_now() - context->ticks; break; default: context->message->rtt = 0.0; break; } context->message->answers = build_answers_evdns(code, type, count, ttl, addresses, context->logger); try { if (context->message->error_code != DNS_ERR_NONE) { context->callback(dns_error(context->message->error_code), context->message); } else { context->callback(NoError(), context->message); } } catch (const Error &) { // suppress Error exceptions because we don't want this kind // of exception to terminate the program } delete context; } template void query_impl(QueryClass dns_class, QueryType dns_type, std::string name, Callback> cb, Settings settings, Var reactor, Var logger) { Var message(new Message); Query query; evdns_base *base; try { base = create_evdns_base(settings, reactor); } catch (std::runtime_error &) { cb(GenericError(), nullptr); // TODO: refine error thrown here return; } catch (std::bad_alloc &) { throw; // Let this propagate as we can do nothing } if (dns_class != MK_DNS_CLASS_IN) { evdns_base_free(base, 1); cb(UnsupportedClassError(), nullptr); return; } // Allow PTR queries if (dns_type == MK_DNS_TYPE_PTR) { std::string s; if ((s = net::unreverse_ipv4(name)) != "") { dns_type = MK_DNS_TYPE_REVERSE_A; name = s; } else if ((s = net::unreverse_ipv6(name)) != "") { dns_type = MK_DNS_TYPE_REVERSE_AAAA; name = s; } else { evdns_base_free(base, 1); cb(InvalidNameForPTRError(), nullptr); return; } } query.type = dns_type; query.qclass = dns_class; query.name = name; message->queries.push_back(query); // // Note: evdns_base_resolve_xxx() return a evdns_request // object that may be used to cancel the request. Yet, the // semantic of cancelling a request is such that evdns // could invoke the callback of a pending request if such // request was cancelled when its corresponding response // was already pending. This seems to be confirmed by // comments in libevent's evdns.c: // // This does nothing if the request's callback is // already running (pending_cb is set) // // For the above reason this class does not explicitly // cancel pending evdns requests and uses the `cancelled` // variable to keep track of cancelled requests. // if (dns_type == MK_DNS_TYPE_A) { logger->debug("dns query: IN A %s", name.c_str()); QueryContext *context = new QueryContext(base, cb, message); if (evdns_base_resolve_ipv4(base, name.c_str(), DNS_QUERY_NO_SEARCH, handle_resolve, context) == nullptr) { delete context; cb(ResolverError(), nullptr); } return; } if (dns_type == MK_DNS_TYPE_AAAA) { logger->debug("dns query: IN AAAA %s", name.c_str()); QueryContext *context = new QueryContext(base, cb, message); if (evdns_base_resolve_ipv6(base, name.c_str(), DNS_QUERY_NO_SEARCH, handle_resolve, context) == nullptr) { delete context; cb(ResolverError(), nullptr); } return; } if (dns_type == MK_DNS_TYPE_REVERSE_A) { logger->debug("dns query: IN REVERSE_A %s", name.c_str()); in_addr netaddr; if (inet_pton(AF_INET, name.c_str(), &netaddr) != 1) { evdns_base_free(base, 1); cb(InvalidIPv4AddressError(), nullptr); return; } QueryContext *context = new QueryContext(base, cb, message); if (evdns_base_resolve_reverse(base, &netaddr, DNS_QUERY_NO_SEARCH, handle_resolve, context) == nullptr) { delete context; cb(ResolverError(), nullptr); } return; } if (dns_type == MK_DNS_TYPE_REVERSE_AAAA) { logger->debug("dns query: IN REVERSE_AAAA %s", name.c_str()); in6_addr netaddr; if (inet_pton(AF_INET6, name.c_str(), &netaddr) != 1) { evdns_base_free(base, 1); cb(InvalidIPv6AddressError(), nullptr); return; } QueryContext *context = new QueryContext(base, cb, message); if (evdns_base_resolve_reverse_ipv6(base, &netaddr, DNS_QUERY_NO_SEARCH, handle_resolve, context) == nullptr) { delete context; cb(ResolverError(), nullptr); return; } return; } evdns_base_free(base, 1); cb(UnsupportedTypeError(), nullptr); } } // namespace libevent } // namespace mk #endif measurement-kit-0.7.1/include/private/libevent/listen.hpp000066400000000000000000000037651315356162600235700ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_LIBEVENT_LISTEN_HPP #define PRIVATE_LIBEVENT_LISTEN_HPP #include "../libevent/connection.hpp" #include "../net/utils.hpp" #include #include extern "C" { void mk_listener_cb(evconnlistener *sl, evutil_socket_t s, sockaddr *saddr, int salen, void *opaque); } // extern "C" namespace mk { namespace libevent { typedef std::function ListenCb; typedef std::function ListenInternalCb; inline void listen4(std::string address, int port, ListenCb cb) { sockaddr_storage storage; socklen_t salen; if (net::storage_init(&storage, &salen, PF_INET, address.c_str(), port, Logger::global()) != 0) { throw ValueError(); } auto cbp = new ListenInternalCb([cb](evutil_socket_t so) { // See similar comment in connect_impl.hpp for DEFER rationale static const int flgs = BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS; bufferevent *bev = bufferevent_socket_new( Reactor::global()->get_event_base(), so, flgs); if (bev == nullptr) { (void)evutil_closesocket(so); return; } if (net::disable_nagle(so) != NoError()) { bufferevent_free(bev); return; } cb(bev); }); // Note: the listener is never freed and hence Valgrind is probably // going to complain that we have a memory leak here. evconnlistener *sl = evconnlistener_new_bind( Reactor::global()->get_event_base(), mk_listener_cb, cbp, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1, (sockaddr *)&storage, salen); if (sl == nullptr) { delete cbp; throw net::EvconnlistenerNewBindError(); } } } // namespace libevent } // namespace net #endif measurement-kit-0.7.1/include/private/libevent/poller.hpp000066400000000000000000000022201315356162600235500ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_LIBEVENT_POLLER_HPP #define PRIVATE_LIBEVENT_POLLER_HPP #include namespace mk { namespace libevent { class Poller : public Reactor { public: Poller(); ~Poller() override; event_base *get_event_base() override; void call_soon(Callback<> &&) override; void call_later(double, Callback<> &&) override; void run() override; void loop_once(); void stop() override; void pollfd(socket_t, short, double, Callback &&) override; // BEGIN internal functions used to test periodic event functionality void handle_periodic_(); void on_periodic_(Callback); // END internal functions used to test periodic event functionality // Public because this simplifies unit testing and because this // class is not meant to be used directly but as Var Var base_; Delegate periodic_cb_; }; } // namespace libevent } // namespace mk #endif measurement-kit-0.7.1/include/private/libevent/poller_impl.hpp000066400000000000000000000112421315356162600245750ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_LIBEVENT_POLLER_IMPL_HPP #define PRIVATE_LIBEVENT_POLLER_IMPL_HPP #include "private/common/mock.hpp" #include "private/common/mock.hpp" #include "../common/utils.hpp" #include "../libevent/poller.hpp" #include #include #include #include #include extern "C" { void mk_call_later_cb(evutil_socket_t, short, void *p); void mk_loop_periodic_cb(evutil_socket_t, short, void *ptr); void mk_pollfd_cb(evutil_socket_t, short, void *p); } // extern "C" namespace mk { namespace libevent { template void library_singleton_() { static bool initialized = 0; if (initialized) { return; } initialized = true; if (evthread_use_pthreads() != 0) { throw std::runtime_error("evthread_use_pthreads() failed"); } struct sigaction sa; memset(&sa, 0, sizeof (sa)); sa.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &sa, nullptr) != 0) { throw std::runtime_error("sigaction() failed"); } } template Var poller_alloc_evbase() { // When we create the first event-base ever we also run the library // singleton, to initialize locking and signals. library_singleton_(); Var base(event_base_new(), [](event_base *p) { if (p != nullptr) { event_base_free(p); } }); if (!base) { throw std::bad_alloc(); } return base; } template void poller_call_later(Var base, double timeo, Callback<> cb) { timeval tv; auto cbp = new Callback<>(cb); if (event_base_once(base.get(), -1, EV_TIMEOUT, mk_call_later_cb, cbp, timeval_init(&tv, timeo)) != 0) { delete cbp; throw std::runtime_error("event_base_once() failed"); } } template void poller_loop(Var base, Poller *poller) { // Register a persistent periodic event to make sure that the event // loop is not going to exit if we run out of events. This is required // to make sure that the ordinary libevent loop works like tor event // loop (also based on libevent), which does not exit in any case. // // Note that the development version of libevent has a flag to implement // the behavior described above, but the stable libevent doesn't. timeval ten_seconds; Var persist( event_new(base.get(), -1, EV_PERSIST, mk_loop_periodic_cb, poller), [](event *p) { if (p != nullptr) { event_free(p); } }); if (!persist) { throw std::runtime_error("event_new() failed"); } if (event_add(persist.get(), timeval_init(&ten_seconds, 10.0)) != 0) { throw std::runtime_error("event_add() failed"); } auto result = event_base_dispatch(base.get()); if (result < 0) { throw std::runtime_error("event_base_dispatch() failed"); } if (result == 1) { warn("loop: no pending and/or active events"); } } template void poller_loop_once(Var base) { auto result = event_base_loop(base.get(), EVLOOP_ONCE); if (result < 0) { throw std::runtime_error("event_base_loop() failed"); } if (result == 1) { warn("loop: no pending and/or active events"); } } template void poller_break_loop(Var base) { if (event_base_loopbreak(base.get()) != 0) { throw std::runtime_error("event_base_loopbreak() failed"); } } template void poller_pollfd( Var base, socket_t sockfd, short events, Callback callback, double timeo) { timeval tv; short evflags = EV_TIMEOUT; if ((events & MK_POLLIN) != 0) { evflags |= EV_READ; } if ((events & MK_POLLOUT) != 0) { evflags |= EV_WRITE; } auto cbp = new Callback(callback); if (event_base_once(base.get(), sockfd, evflags, mk_pollfd_cb, cbp, timeval_init(&tv, timeo)) != 0) { delete cbp; throw std::runtime_error("event_base_once() failed"); } } } // namespace libevent } // namespace mk #endif measurement-kit-0.7.1/include/private/mlabns/000077500000000000000000000000001315356162600212125ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/mlabns/mlabns_impl.hpp000066400000000000000000000074571315356162600242350ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_MLABNS_MLABNS_IMPL_HPP #define PRIVATE_MLABNS_MLABNS_IMPL_HPP #include "private/common/json.hpp" #include "private/common/mock.hpp" #include #include #include using json = nlohmann::json; namespace mk { namespace mlabns { static inline ErrorOr as_query(Settings &settings) { std::string query; std::string policy = settings.get("mlabns/policy", ""); std::string metro = settings.get("mlabns/metro", ""); std::string address_family = settings.get("mlabns/address_family", ""); if (policy == "" && metro == "" && address_family == "") { return query; } if (policy != "") { if (policy != "geo" && policy != "random" && policy != "metro" && policy != "country") { return InvalidPolicyError(); } if (query != "") { query += "&"; } query += "policy=" + policy; } if (metro != "") { std::regex valid_metro("^[a-z]{3}$"); if (!std::regex_match(metro, valid_metro)) { return InvalidMetroError(); } if (query != "") { query += "&"; } query += "metro=" + metro; } if (address_family != "") { if (address_family != "ipv4" && address_family != "ipv6") { return InvalidAddressFamilyError(); } if (query != "") { query += "&"; } query += "address_family=" + address_family; } query = "?" + query; return query; } template void query_impl(std::string tool, Callback callback, Settings settings, Var reactor, Var logger) { ErrorOr query = as_query(settings); if (!query) { callback(query.as_error(), Reply()); return; } std::string url = settings.get("mlabns/base_url", std::string{ "https://mlab-ns.appspot.com/" }); std::regex valid_tool("^[a-z]+$"); if (!std::regex_match(tool, valid_tool)) { callback(InvalidToolNameError(), Reply()); return; } url += tool; url += *query; logger->debug("query mlabns for tool %s", tool.c_str()); logger->debug("mlabns url: %s", url.c_str()); request_json_no_body("GET", url, {}, [callback, logger](Error error, Var /*response*/, nlohmann::json json_response) { if (error) { logger->warn("mlabns: HTTP error: %s", error.explain().c_str()); callback(error, Reply()); return; } Reply reply; Error err = json_process(json_response, [&](auto node) { reply.city = node.at("city"); reply.url = node.at("url"); for (auto ip2 : node.at("ip")) { reply.ip.push_back(ip2); } reply.fqdn = node.at("fqdn"); reply.site = node.at("site"); reply.country = node.at("country"); }); if (err) { logger->warn("mlabns: cannot parse json: %s", err.explain().c_str()); } else { logger->info("Discovered mlab test server: %s", reply.fqdn.c_str()); } callback(err, reply); }, settings, reactor, logger); } } // namespace mlabns } // namespace mk #endif measurement-kit-0.7.1/include/private/ndt/000077500000000000000000000000001315356162600205235ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/ndt/internal.hpp000066400000000000000000000211711315356162600230520ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NDT_INTERNAL_HPP #define PRIVATE_NDT_INTERNAL_HPP // This implementation targets v3.7.0 of the NDT protocol // See #include "../common/utils.hpp" #include "measure_speed.hpp" #include #include #include /* ____ __ _ _ _ _ | _ \ ___ / _(_)_ __ (_) |_(_) ___ _ __ ___ | | | |/ _ \ |_| | '_ \| | __| |/ _ \| '_ \/ __| | |_| | __/ _| | | | | | |_| | (_) | | | \__ \ |____/ \___|_| |_|_| |_|_|\__|_|\___/|_| |_|___/ Definitions used by the NDT test. */ #define COMM_FAILURE 0 #define SRV_QUEUE 1 #define MSG_LOGIN 2 #define TEST_PREPARE 3 #define TEST_START 4 #define TEST_MSG 5 #define TEST_FINALIZE 6 #define MSG_ERROR 7 #define MSG_RESULTS 8 #define MSG_LOGOUT 9 #define MSG_WAITING 10 #define MSG_EXTENDED_LOGIN 11 // Those are the original defines of NDT. I'd rather use them in the // implementation rather than using our define names. #define TEST_MID MK_NDT_MIDDLEBOX #define TEST_C2S MK_NDT_UPLOAD #define TEST_S2C MK_NDT_DOWNLOAD #define TEST_SFW MK_NDT_SIMPLE_FIREWALL #define TEST_STATUS MK_NDT_STATUS #define TEST_META MK_NDT_META #define TEST_C2S_EXT MK_NDT_UPLOAD_EXT #define TEST_S2C_EXT MK_NDT_DOWNLOAD_EXT static inline std::string id_to_name(int id) { switch (id) { case MK_NDT_MIDDLEBOX: return "middlebox"; case MK_NDT_UPLOAD: return "upload"; case MK_NDT_DOWNLOAD: return "download"; case MK_NDT_SIMPLE_FIREWALL: return "simple_firewall"; case MK_NDT_STATUS: return "status"; case MK_NDT_META: return "meta"; case MK_NDT_UPLOAD_EXT: return "upload_ext"; case MK_NDT_DOWNLOAD_EXT: return "download_ext"; default: break; } return "unknown"; } #define KICKOFF_MESSAGE "123456 654321" #define KICKOFF_MESSAGE_SIZE (sizeof(KICKOFF_MESSAGE) - 1) #define NDT_PORT 3001 #define NDT_TIMEOUT 10.0 // During the handshake we declare to be measurement-kit version such and // such that is compatible with version v3.7.0 of NDT #define MSG_NDT_VERSION "v3.7.0" #define TEST_C2S_DURATION 10.0 #define SRV_QUEUE_HEARTBEAT 9990 #define SRV_QUEUE_SERVER_FAULT 9977 #define SRV_QUEUE_SERVER_BUSY 9987 #define SRV_QUEUE_SERVER_BUSY_60s 9999 namespace mk { namespace ndt { using json = nlohmann::json; using namespace mk::net; using namespace mk::report; /* ____ _ _ / ___|___ _ __ | |_ _____ _| |_ | | / _ \| '_ \| __/ _ \ \/ / __| | |__| (_) | | | | || __/> <| |_ \____\___/|_| |_|\__\___/_/\_\\__| Data structure representing a NDT test. */ struct Context { std::string address; Var buff = Buffer::make(); Callback callback; Var entry; std::list granted_suite; size_t granted_suite_count = 0; size_t current_test_count = 0; Var logger = Logger::global(); int port = NDT_PORT; Var reactor = Reactor::global(); Settings settings; // We always set these two tests because they are the bare minimum // required to talk to a NDT server. Other sets could be added as flags // by the user using the options passed to the run() function. int test_suite = TEST_STATUS | TEST_META; double timeout = NDT_TIMEOUT; Var txp; }; /* __ __ | \/ | ___ ___ ___ __ _ __ _ ___ ___ | |\/| |/ _ \/ __/ __|/ _` |/ _` |/ _ \/ __| | | | | __/\__ \__ \ (_| | (_| | __/\__ \ |_| |_|\___||___/___/\__,_|\__, |\___||___/ |___/ Sending and receiving NDT protocol messages. */ namespace messages { void read_ll(Var ctx, Callback callback, Var reactor = Reactor::global()); void read_json(Var ctx, Callback callback, Var reactor = Reactor::global()); void read_msg(Var ctx, Callback callback, Var reactor = Reactor::global()); ErrorOr format_msg_extended_login(unsigned char tests); ErrorOr format_test_msg(std::string s); ErrorOr format_msg_waiting(); void write(Var, Buffer, Callback); void write_noasync(Var, Buffer); Error add_to_report(Var entry, std::string key, std::string item); } // namespace messages /* ____ _ _ | _ \ _ __ ___ | |_ ___ ___ ___ | | | |_) | '__/ _ \| __/ _ \ / __/ _ \| | | __/| | | (_) | || (_) | (_| (_) | | |_| |_| \___/ \__\___/ \___\___/|_| Implementation of NDT's control protocol. */ namespace protocol { void connect(Var ctx, Callback callback); void send_extended_login(Var ctx, Callback callback); void recv_and_ignore_kickoff(Var ctx, Callback callback); void wait_in_queue(Var ctx, Callback callback); void recv_version(Var ctx, Callback callback); void recv_tests_id(Var ctx, Callback callback); void run_tests(Var ctx, Callback callback); void recv_results_and_logout(Var ctx, Callback callback); void wait_close(Var ctx, Callback callback); void disconnect_and_callback(Var ctx, Error err); } // namespace protocol /* _____ _ ____ ____ ____ |_ _|__ ___| |_ / ___|___ \/ ___| | |/ _ \/ __| __| | | __) \___ \ | | __/\__ \ |_ | |___ / __/ ___) | |_|\___||___/\__| \____|_____|____/ Client to server test: upload data and measure speed. */ namespace test_c2s { void coroutine(Var, std::string address, int port, double runtime, Callback> cb, double timeout = 10.0, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); void run(Var ctx, Callback callback); } // namespace test_c2s /* _____ _ __ __ _____ _____ _ |_ _|__ ___| |_ | \/ | ____|_ _|/ \ | |/ _ \/ __| __| | |\/| | _| | | / _ \ | | __/\__ \ |_ | | | | |___ | |/ ___ \ |_|\___||___/\__| |_| |_|_____| |_/_/ \_\ META test: send metadata describing the client to the server */ namespace test_meta { void run(Var ctx, Callback callback); } // namespace test_meta /* _____ _ ____ ____ ____ |_ _|__ ___| |_ / ___|___ \ / ___| | |/ _ \/ __| __| \___ \ __) | | | | __/\__ \ |_ ___) / __/| |___ |_|\___||___/\__| |____/_____|\____| Test sever to client: download data and measure speed */ namespace test_s2c { struct Params { int port = -1; double duration = 10.0; // ignored by our implementation bool snaps_enabled = false; // we always take snaps, never report them double snaps_delay = 0.5; // we ignore what is sent by the server double snaps_offeset = 0.0; // ignored by our implementation int num_streams = 1; Params(){} // This constructor only sets the port and all the other settings // instead remain at their default value Params(int port) : port(port) {} }; void coroutine(Var report_entry, std::string address, Params params, Callback> cb, double timeout = 10.0, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); void finalizing_test(Var ctx, Var cur_entry, Callback callback); void run(Var ctx, Callback callback); } // namespace test_s2c /* _ _ _ _ _ | | | | |_(_) |___ | | | | __| | / __| | |_| | |_| | \__ \ \___/ \__|_|_|___/ Useful functions used by all modules. */ inline void log_speed(Var logger, std::string type, int num_streams, double elapsed, double speed) { if (speed > 0 && elapsed < 10.0) { std::stringstream ss; ss << type << " (elapsed " << std::fixed << std::setprecision(2) << elapsed << " s) " << std::fixed << std::setprecision(2) << speed << " kbit/s " << "(num_streams " << num_streams << ")"; logger->progress_relative(0.025, ss.str().c_str()); } logger->log(MK_LOG_EVENT | MK_LOG_INFO, R"xx({ "type": "%s", "elapsed": [%lf, "s"], "num_streams": %d, "speed": [%lf, "kbit/s"] })xx", type.c_str(), elapsed, num_streams, speed); } } // namespace mk } // namespace ndt #endif measurement-kit-0.7.1/include/private/ndt/measure_speed.hpp000066400000000000000000000024671315356162600240660ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NDT_MEASURE_SPEED_HPP #define PRIVATE_NDT_MEASURE_SPEED_HPP #include #include namespace mk { namespace ndt { class MeasureSpeed { public: const double start_time = mk::time_now(); double previous = start_time; double snap_delay = -1.0; size_t total = 0; MeasureSpeed(double delay) { snap_delay = delay; } MeasureSpeed() {} double speed(double ct) const { double elapsed = ct - previous; if (elapsed <= 0.0) { return 0.0; } return (total * 8.0) / 1000.0 / elapsed; } double speed() const { return speed(mk::time_now()); } void reset(double ct) { previous = ct; total = 0; } void maybe_speed(double ct, Callback cb) { if (snap_delay > 0.0 and ct - previous >= snap_delay) { cb(ct - start_time, speed(ct)); reset(ct); } } void maybe_speed(Callback cb) { maybe_speed(mk::time_now(), cb); } }; } // namespace ndt } // namespace mk #endif measurement-kit-0.7.1/include/private/ndt/messages_impl.hpp000066400000000000000000000077321315356162600240750ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NDT_MESSAGES_IMPL_HPP #define PRIVATE_NDT_MESSAGES_IMPL_HPP /* * To have UINT16_MAX defined. Required on Android API < 21. * * See . */ #define __STDC_LIMIT_MACROS #include "private/common/mock.hpp" #include "../ndt/internal.hpp" #include namespace mk { namespace ndt { namespace messages { /* +----------+------------+-------------------+ | type (1) | length (2) | payload (0-65535) | +----------+------------+-------------------+ */ template void read_ll_impl(Var ctx, Callback callback, Var reactor) { // Receive message type (1 byte) and length (2 bytes) net_readn_first(ctx->txp, ctx->buff, 3, [=](Error err) { if (err) { callback(ReadingMessageTypeLengthError(err), 0, ""); return; } ErrorOr type = ctx->buff->read_uint8(); ErrorOr length = ctx->buff->read_uint16(); // Note: we don't check for `type` and `length` true-ness because // we are after a readn() which should ensure enough space is there, // hence, if that's not the case, we'll see an exception // Now read the message payload (`*length` bytes in total) net_readn_second(ctx->txp, ctx->buff, *length, [=](Error err) { if (err) { callback(ReadingMessagePayloadError(err), 0, ""); return; } std::string s = ctx->buff->readn(*length); // TODO: rather than using assert() here we should modify readn() // to return ErrorOr<> (exceptions are better than asserts) assert(s.size() == *length); ctx->logger->debug("< [%d]: (%d) %s", *length, *type, s.c_str()); callback(NoError(), *type, s); }, reactor); }, reactor); } // Like `read_ll()` but decode the payload using JSON template void read_json_impl(Var ctx, Callback callback, Var reactor) { read_ll(ctx, [=](Error err, uint8_t type, std::string m) { json message; if (err) { callback(err, 0, message); return; } try { message = json::parse(m); } catch (const std::invalid_argument &) { callback(JsonParseError(), 0, message); return; } callback(NoError(), type, message); }, reactor); } // Like `read_json()` but return the `msg` field only template void read_msg_impl(Var ctx, Callback callback, Var reactor) { read_json(ctx, [=](Error error, uint8_t type, json message) { if (error) { callback(error, 0, ""); return; } std::string s; try { s = message.at("msg"); } catch (const std::out_of_range &) { callback(JsonKeyError(), 0, ""); return; } catch (const std::domain_error &) { callback(JsonDomainError(), 0, ""); return; } callback(NoError(), type, s); }, reactor); } static inline ErrorOr format_any(unsigned char type, json message) { Buffer out; out.write_uint8(type); std::string s = message.dump(); if (s.size() > UINT16_MAX) { return MessageTooLongError(); } // Cast safe because we've just excluded the case where it's bigger uint16_t length = (uint16_t)s.size(); out.write_uint16(length); out.write(s.data(), s.size()); return out; } } // namespace messages } // namespace ndt } // namespace mk #endif measurement-kit-0.7.1/include/private/ndt/protocol_impl.hpp000066400000000000000000000255141315356162600241250ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NDT_PROTOCOL_IMPL_HPP #define PRIVATE_NDT_PROTOCOL_IMPL_HPP #include "private/common/mock.hpp" #include "private/common/mock.hpp" #include "../ndt/internal.hpp" namespace mk { namespace ndt { namespace protocol { template void connect_impl(Var ctx, Callback callback) { ctx->logger->debug("ndt: connect ..."); net_connect(ctx->address, ctx->port, [=](Error err, Var txp) { ctx->logger->debug("ndt: connect ... %d", (int)err); if (err) { callback(ConnectControlConnectionError(err)); return; } txp->set_timeout(ctx->timeout); ctx->txp = txp; ctx->logger->debug("Connected to %s:%d", ctx->address.c_str(), ctx->port); callback(NoError()); }, ctx->settings, ctx->reactor, ctx->logger); } template void send_extended_login_impl(Var ctx, Callback callback) { ctx->logger->debug("ndt: send login ..."); ErrorOr out = messages_format_msg_extended_login(ctx->test_suite); if (!out) { ctx->logger->debug("ndt: send login ... %d", (int)out.as_error()); callback(FormatExtendedLoginMessageError(out.as_error())); return; } messages_write(ctx, *out, [=](Error err) { ctx->logger->debug("ndt: send login ... %d", (int)err); if (err) { callback(WriteExtendedLoginMessageError(err)); return; } ctx->logger->debug("Sent LOGIN with test suite: %d", ctx->test_suite); callback(NoError()); }); } template void recv_and_ignore_kickoff_impl(Var ctx, Callback callback) { ctx->logger->debug("ndt: recv and ignore kickoff ..."); net_readn(ctx->txp, ctx->buff, KICKOFF_MESSAGE_SIZE, [=](Error err) { ctx->logger->debug("ndt: recv and ignore kickoff ... %d", (int)err); if (err) { callback(ReadingKickoffMessageError(err)); return; } std::string s = ctx->buff->readn(KICKOFF_MESSAGE_SIZE); if (s != KICKOFF_MESSAGE) { callback(InvalidKickoffMessageError()); return; } ctx->logger->debug("Got legacy KICKOFF message (ignored)"); callback(NoError()); }, ctx->reactor); } template void wait_in_queue_impl(Var ctx, Callback callback) { ctx->logger->debug("ndt: wait in queue ..."); messages_read_msg(ctx, [=](Error err, uint8_t type, std::string s) { ctx->logger->debug("ndt: wait in queue ... %d", (int)err); if (err) { callback(ReadingSrvQueueMessageError(err)); return; } if (type != SRV_QUEUE) { callback(NotSrvQueueMessageError()); return; } ErrorOr wait_time = lexical_cast_noexcept(s); if (!wait_time) { callback(InvalidSrvQueueMessageError(wait_time.as_error())); return; } if (*wait_time > 0) { if (*wait_time == SRV_QUEUE_SERVER_FAULT) { ctx->logger->warn("Server fault; aborting test"); callback(QueueServerFaultError()); return; } if (*wait_time == SRV_QUEUE_SERVER_BUSY or *wait_time == SRV_QUEUE_SERVER_BUSY_60s) { // Original NDT does exit(0) in both of these cases ctx->logger->warn("Server busy; aborting test"); callback(QueueServerBusyError()); return; } if (*wait_time == SRV_QUEUE_HEARTBEAT) { ctx->logger->info("Got HEARTBEAT message; responding..."); ErrorOr buff = messages_format_msg_waiting(); if (!buff) { callback(FormatMsgWaitingError(buff.as_error())); return; } messages_write_noasync(ctx, *buff); } else { ctx->logger->info("Number of clients in queue: %d", *wait_time); } // TODO: in theory the server can keep us in queue forever... call_soon([=]() { wait_in_queue_impl(ctx, callback); }, ctx->reactor); return; } ctx->logger->debug("Authorized to run the test"); callback(NoError()); }, ctx->reactor); } template void recv_version_impl(Var ctx, Callback callback) { ctx->logger->debug("ndt: recv server version ..."); messages_read_msg(ctx, [=](Error err, uint8_t type, std::string s) { ctx->logger->debug("ndt: recv server version ... %d", (int)err); if (err) { callback(ReadingServerVersionMessageError(err)); return; } if (type != MSG_LOGIN) { callback(NotServerVersionMessageError()); return; } ctx->logger->info("Server version: %s", s.c_str()); (*ctx->entry)["server_version"] = s; // TODO: validate the server version? callback(NoError()); }, ctx->reactor); } template void recv_tests_id_impl(Var ctx, Callback callback) { ctx->logger->debug("ndt: recv tests ID ..."); messages_read_msg(ctx, [=](Error err, uint8_t type, std::string s) { ctx->logger->debug("ndt: recv tests ID ... %d", (int)err); if (err) { callback(ReadingTestsIdMessageError(err)); return; } if (type != MSG_LOGIN) { callback(NotTestsIdMessageError()); return; } ctx->logger->debug("Authorized tests: %s", s.c_str()); ctx->granted_suite = split(s); ctx->granted_suite_count = ctx->granted_suite.size(); callback(NoError()); }, ctx->reactor); } template void run_tests_impl(Var ctx, Callback callback) { if (ctx->granted_suite.size() <= 0) { callback(NoError()); return; } std::string s = ctx->granted_suite.front(); ctx->granted_suite.pop_front(); ErrorOr num = lexical_cast_noexcept(s); if (!num) { callback(InvalidTestIdError(num.as_error())); return; } std::function, Callback)> func; if (*num == TEST_C2S) { func = test_c2s_run; } else if (*num == TEST_META) { func = test_meta_run; } else if (*num == TEST_S2C or *num == TEST_S2C_EXT) { func = test_s2c_run; } else { /* nothing */ } if (!func) { ctx->logger->warn("ndt: unknown test: %d", *num); // The spec says that the connection MUST be closed if we receive // an test we do not requested for; this is what happens below when // the callback of this stage is called with an error argument callback(UnknownTestIdError()); return; } ctx->logger->debug("Run test with id %d ...", *num); func(ctx, [=](Error err) { ctx->logger->debug("Run test with id %d ... complete (%s)", *num, err.explain().c_str()); (*ctx->entry)["phase_result"][id_to_name(*num)] = err.as_ooni_error(); run_tests_impl(ctx, callback); }); } template void recv_results_and_logout_impl(Var ctx, Callback callback) { ctx->logger->debug("ndt: recv RESULTS ..."); messages_read_msg(ctx, [=](Error err, uint8_t type, std::string s) { ctx->logger->debug("ndt: recv RESULTS ... %d", (int)err); if (err) { callback(ReadingResultsOrLogoutError(err)); return; } if (type == MSG_RESULTS) { for (auto x : split(s, "\n")) { if (x != "") { ctx->logger->debug("%s", x.c_str()); (void)messages::add_to_report(ctx->entry, "summary_data", x); } } // XXX: here we have the potential to loop forever... recv_results_and_logout_impl(ctx, callback); return; } if (type != MSG_LOGOUT) { callback(NotResultsOrLogoutError()); return; } ctx->logger->debug("Got LOGOUT"); callback(NoError()); }, ctx->reactor); } template void wait_close_impl(Var ctx, Callback callback) { ctx->logger->debug("ndt: wait close ..."); ctx->txp->set_timeout(1.0); // TODO: here we should probably use ctx->buff Var buffer(new Buffer); net_read(ctx->txp, buffer, [=](Error err) { ctx->logger->debug("ndt: wait close ... %d", (int)err); // Note: the server SHOULD close the connection if (err == EofError()) { ctx->logger->debug("Connection closed"); callback(NoError()); return; } if (err == TimeoutError()) { ctx->logger->info("Closing connection after 1.0 sec timeout"); callback(NoError()); return; } if (err) { callback(WaitingCloseError(err)); return; } ctx->logger->debug("ndt: got extra data: %s", buffer->read().c_str()); callback(DataAfterLogoutError()); }, ctx->reactor); } static inline void disconnect_and_callback_impl(Var ctx, Error err) { if (ctx->txp) { Var txp = ctx->txp; ctx->txp = nullptr; txp->close([=]() { ctx->callback(err); }); return; } ctx->callback(err); } } // namespace protocol } // namespace mk } // namespace ndt #endif measurement-kit-0.7.1/include/private/ndt/run_impl.hpp000066400000000000000000000141731315356162600230670ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NDT_RUN_IMPL_HPP #define PRIVATE_NDT_RUN_IMPL_HPP #include "private/common/mock.hpp" #include "private/common/mock.hpp" #include "../ndt/internal.hpp" #include namespace mk { namespace ndt { using Phase = void (*)(Var, Callback); using Cleanup = void (*)(Var, Error); template void run_with_specific_server_impl(Var entry, std::string address, int port, Callback callback, Settings settings, Var reactor, Var logger) { // Note: this implementation is a template because that allows us to // easily change the functions implementing each phase of the protocol // thus enabling quick experimentation and unit testing. Var ctx(new Context); ctx->address = address; ctx->callback = callback; ctx->entry = entry; ctx->logger = logger; ctx->reactor = reactor; ctx->port = port; ctx->settings = settings; // If the user has not configured the test_suite to run, default with // running the download and the uploade phases of the test. ctx->test_suite |= settings.get("test_suite", TEST_C2S | TEST_S2C); dump_settings(ctx->settings, "ndt", ctx->logger); // Initialize entry keys that may be set by this routine (*ctx->entry)["client_resolver"] = nullptr; /* Set later by parent */ (*ctx->entry)["failure"] = nullptr; (*ctx->entry)["server_address"] = address; (*ctx->entry)["server_port"] = port; (*ctx->entry)["server_version"] = nullptr; (*ctx->entry)["summary_data"] = Entry::object(); (*ctx->entry)["test_c2s"] = Entry::array(); (*ctx->entry)["test_s2c"] = Entry::array(); (*ctx->entry)["test_suite"] = ctx->test_suite; #define TRAP_ERRORS(e) \ if (e) { \ disconnect_and_callback(ctx, e); \ return; \ } // The following code implements this sequence diagram: // https://raw.githubusercontent.com/wiki/ndt-project/ndt/NDTProtocol.images/ndt_10.png connect(ctx, [ctx](Error err) { TRAP_ERRORS(err); ctx->logger->progress_relative(0.01, "Connected to test server"); send_login(ctx, [ctx](Error err) { TRAP_ERRORS(err); ctx->logger->progress_relative(0.01, "Logged in with test server"); recv_and_ignore_kickoff(ctx, [ctx](Error err) { TRAP_ERRORS(err); ctx->logger->progress_relative(0.01, "Waiting for our turn in queue"); wait_in_queue(ctx, [ctx](Error err) { TRAP_ERRORS(err); ctx->logger->progress_relative(0.01, "Authorized to run test"); recv_version(ctx, [ctx](Error err) { TRAP_ERRORS(err); ctx->logger->progress_relative(0.01, "Got server version"); recv_tests_id(ctx, [ctx](Error err) { TRAP_ERRORS(err); ctx->logger->progress_relative( 0.01, "Got authorized tests identifiers"); run_tests(ctx, [ctx](Error err) { TRAP_ERRORS(err); // Progress printed by run_tests() recv_results_and_logout(ctx, [ctx](Error err) { TRAP_ERRORS(err); ctx->logger->progress_relative( 0.01, "Received results from server"); wait_close(ctx, [ctx](Error err) { ctx->logger->progress_relative( 0.01, "Connection with server closed"); disconnect_and_callback(ctx, err); }); }); }); }); }); }); }); }); }); #undef TRAP_ERRORS } template void run_impl(Var entry, Callback callback, Settings settings, Var reactor, Var logger) { ErrorOr port = settings.get_noexcept("port", NDT_PORT); if (!port) { callback(InvalidPortError(port.as_error())); return; } std::string address = settings.get("address", ""); if (address != "") { run_with_specific_server(entry, address, *port, callback, settings, reactor, logger); return; } mlabns_query(settings.get("mlabns_tool_name", "ndt"), [=](Error err, mlabns::Reply reply) { if (err) { callback(MlabnsQueryError(err)); return; } run_with_specific_server(entry, reply.fqdn, *port, callback, settings, reactor, logger); }, settings, reactor, logger); } } // namespace ndt } // namespace mk #endif measurement-kit-0.7.1/include/private/ndt/test_c2s_impl.hpp000066400000000000000000000223401315356162600240040ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NDT_TEST_C2S_IMPL_HPP #define PRIVATE_NDT_TEST_C2S_IMPL_HPP #include "private/common/mock.hpp" #include "private/common/mock.hpp" #include "../ndt/internal.hpp" namespace mk { namespace ndt { namespace test_c2s { template void coroutine_impl(Var report_entry, std::string address, int port, double runtime, Callback> cb, double timeout, Settings settings, Var reactor, Var logger) { // Performance note: This implementation does some string copies // when sending but in localhost testing this does not seem to be // a problem when sending against a MK based discard server. // // Otherwise, a possible improvement would be to have a fixed // size buffer and bypass bufferevent's output logic. // // In my tests (where speed of course depends on the computer you // use), I was able to send at over 1.1 GiB/s and similar speeds // were achieved using stripped down NDT code from `test_c2s_clt.c`. dump_settings(settings, "ndt/c2s", logger); std::string str = random_printable(8192); logger->debug("ndt: connect ..."); net_connect(address, port, [=](Error err, Var txp) { logger->debug("ndt: connect ... %d", (int)err); if (err) { cb(err, nullptr); return; } (*report_entry)["connect_times"].push_back(txp->connect_time()); logger->info("Connected to %s:%d", address.c_str(), port); logger->debug("ndt: suspend coroutine"); cb(NoError(), [=](Callback cb) { double begin = time_now(); Var snap(new MeasureSpeed(0.5)); logger->debug("ndt: resume coroutine"); logger->info("Starting upload"); txp->set_timeout(timeout); txp->on_flush([=]() { double now = time_now(); snap->maybe_speed(now, [&](double el, double x) { log_speed(logger, "upload-speed", 1, el, x); (*report_entry)["sender_data"].push_back({ el, x }); }); if (now - begin > runtime) { logger->info("Elapsed enough time"); txp->emit_error(NoError()); return; } txp->write(str.data(), str.size()); snap->total += str.size(); }); txp->on_error([=](Error err) { logger->info("Ending upload (%d)", (int)err); txp->close([=]() { logger->info("Connection to %s:%d closed", address.c_str(), port); cb(err); }); }); txp->write(str.data(), str.size()); }); }, settings, reactor, logger); } template void run_impl(Var ctx, Callback callback) { // The server sends us the PREPARE message containing the port number ctx->logger->debug("ndt: recv TEST_PREPARE ..."); messages_read_msg_first(ctx, [=](Error err, uint8_t type, std::string s) { ctx->logger->debug("ndt: recv TEST_PREPARE ... %d", (int)err); if (err) { callback(ReadingTestPrepareError(err)); return; } if (type != TEST_PREPARE) { callback(NotTestPrepareError()); return; } ErrorOr port = lexical_cast_noexcept(s); if (!port || *port < 0 || *port > 65535) { callback(InvalidPortError()); return; } Var cur_entry(new Entry); (*cur_entry)["connect_times"] = Entry::array(); (*cur_entry)["params"] = {{"num_streams", 1}}; (*cur_entry)["receiver_data"] = {{"avg_speed", nullptr}}; (*cur_entry)["sender_data"] = Entry::array(); // We connect to the port and wait for coroutine to pause ctx->logger->debug("ndt: start c2s coroutine ..."); coroutine( cur_entry, ctx->address, *port, TEST_C2S_DURATION, [=](Error err, Continuation cc) { ctx->logger->debug("ndt: start c2s coroutine ... %d", (int)err); if (err) { callback(ConnectTestConnectionError(err)); return; } // The server sends us the START message to tell we can start ctx->logger->debug("ndt: recv TEST_START ..."); messages_read_msg_second(ctx, [=](Error err, uint8_t type, std::string) { ctx->logger->debug("ndt: recv TEST_START ... %d", (int)err); if (err) { callback(ReadingTestStartError(err)); return; } if (type != TEST_START) { callback(NotTestStartError()); return; } // We resume coroutine and wait for its completion ctx->logger->debug("ndt: resume c2s coroutine"); cc([=](Error err) { ctx->logger->debug("ndt: c2s coroutine complete"); if (err) { if (err != BrokenPipeError()) { callback(err); return; } ctx->logger->debug("ndt: tolerating broken pipe"); } // The server sends us MSG containing throughput ctx->logger->debug("ndt: recv TEST_MSG ..."); messages_read_msg_third(ctx, [=](Error err, uint8_t type, std::string s) { ctx->logger->debug("ndt: recv TEST_MSG ... %d", (int)err); if (err) { callback(ReadingTestMsgError(err)); return; } if (type != TEST_MSG) { callback(NotTestMsgError()); return; } ctx->logger->info( "C2S speed calculated by server: %s kbit/s", s.c_str()); ErrorOr x = lexical_cast_noexcept(s); if (!!x) { (*cur_entry)["receiver_data"]["avg_speed"] = *x; } (*ctx->entry)["test_c2s"].push_back(*cur_entry); // The server sends us the FINALIZE message ctx->logger->debug("ndt: recv TEST_FINALIZE ..."); messages_read_msg_fourth( ctx, [=](Error err, uint8_t type, std::string) { ctx->logger->debug( "ndt: recv TEST_FINALIZE ... %d", (int)err); if (err) { callback(ReadingTestFinalizeError(err)); return; } if (type != TEST_FINALIZE) { callback(NotTestFinalizeError()); return; } // The C2S phase is now finished callback(NoError()); }, ctx->reactor); }, ctx->reactor); }); }, ctx->reactor); }, ctx->timeout, ctx->settings, ctx->reactor, ctx->logger); }, ctx->reactor); } } // namespace test_c2s } // namespace ndt } // namespace mk #endif measurement-kit-0.7.1/include/private/ndt/test_meta_impl.hpp000066400000000000000000000116311315356162600242440ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NDT_TEST_META_IMPL_HPP #define PRIVATE_NDT_TEST_META_IMPL_HPP #include "private/common/mock.hpp" #include "private/common/mock.hpp" #include "../ndt/internal.hpp" namespace mk { namespace ndt { namespace test_meta { template void run_impl(Var ctx, Callback cb) { auto callback = [=](Error err) { ctx->logger->progress_relative(0.01, "Sent metadata to server"); cb(err); }; // The server sends the PREPARE and START messages back to back ctx->logger->debug("ndt: recv TEST_PREPARE ..."); messages_read_msg_first(ctx, [=](Error err, uint8_t type, std::string) { ctx->logger->debug("ndt: recv TEST_PREPARE ... %d", (int)err); if (err) { callback(ReadingTestPrepareError(err)); return; } if (type != TEST_PREPARE) { callback(NotTestPrepareError()); return; } ctx->logger->debug("ndt: recv TEST_START ..."); messages_read_msg_second( ctx, [=](Error err, uint8_t type, std::string) { ctx->logger->debug("ndt: recv TEST_START ... %d", (int)err); if (err) { callback(ReadingTestStartError(err)); return; } if (type != TEST_START) { callback(NotTestStartError()); return; } // Now we send all the TEST messages containing metadata ErrorOr out; ctx->logger->debug("send client.version"); out = messages_format_test_msg_first( "client.version:" MEASUREMENT_KIT_VERSION); if (!out) { callback(SerializingClientVersionError()); return; } messages::write_noasync(ctx, *out); ctx->logger->debug("send client.version ... 0"); ctx->logger->debug("send client.application"); out = messages_format_test_msg_second( "client.application:measurement-kit"); if (!out) { callback(SerializingClientApplicationError()); return; } messages::write_noasync(ctx, *out); ctx->logger->debug("send client.application ... 0"); // XXX not sending: client.os.name // XXX not sending: client.browser.name // XXX not sending: client.kernel.version // Now we send the empty TEST message to signal we're done ctx->logger->debug("ndt: send final empty message"); out = messages_format_test_msg_third(""); if (!out) { callback(SerializingFinalMetaError()); return; } messages_write(ctx, *out, [=](Error err) { ctx->logger->debug("ndt: send final empty message ... %d", (int)err); if (err) { callback(WritingMetaError(err)); return; } ctx->logger->debug("Sent additional metadata to server"); // Now we read the FINALIZE message ctx->logger->debug("ndt: recv TEST_FINALIZE ..."); messages_read_msg_third( ctx, [=](Error err, uint8_t type, std::string) { ctx->logger->debug("ndt: recv TEST_FINALIZE ... %d", (int)err); if (err) { callback(ReadingTestFinalizeError(err)); return; } if (type != TEST_FINALIZE) { callback(NotTestFinalizeError()); return; } // We're done callback(NoError()); }, ctx->reactor); }); }, ctx->reactor); }, ctx->reactor); } } // namespace test_meta } // namespace mk } // namespace ndt #endif measurement-kit-0.7.1/include/private/ndt/test_s2c_impl.hpp000066400000000000000000000320361315356162600240070ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NDT_TEST_S2C_IMPL_HPP #define PRIVATE_NDT_TEST_S2C_IMPL_HPP #include "private/common/mock.hpp" #include "private/common/mock.hpp" #include "../ndt/internal.hpp" namespace mk { namespace ndt { namespace test_s2c { using namespace mk::report; template void coroutine_impl(Var report_entry, std::string address, Params params, Callback> cb, double timeout, Settings settings, Var reactor, Var logger) { dump_settings(settings, "ndt/s2c", logger); // The coroutine connects to the remote endpoint and then pauses logger->debug("ndt: connect ..."); net_connect_many( address, params.port, params.num_streams, [=](Error err, std::vector> txp_list) { logger->debug("ndt: connect ... %d", (int)err); if (err) { cb(err, nullptr); return; } (*report_entry)["connect_times"] = Entry::array(); for (auto &txp : txp_list) { (*report_entry)["connect_times"].push_back(txp->connect_time()); } logger->debug("Connected to %s:%d", address.c_str(), params.port); logger->debug("ndt: suspend coroutine"); cb(NoError(), [=](Callback cb) { // The coroutine is resumed and receives data logger->debug("ndt: resume coroutine"); logger->debug("Starting download"); Var average(new MeasureSpeed); // Note: we parse but ignore the server's snap delay Var snaps(new MeasureSpeed(0.5)); Var num_completed{new size_t{0}}; size_t num_flows = txp_list.size(); log_speed(logger, "download-speed", params.num_streams, 0.0, 0.0); (*report_entry)["params"]["num_streams"] = params.num_streams; (*report_entry)["params"]["snaps_delay"] = params.snaps_delay; for (auto txp : txp_list) { txp->set_timeout(timeout); txp->on_data([=](Buffer data) { average->total += data.length(); snaps->total += data.length(); double ct = time_now(); // Note: we stop printing the speed when at least // one connection has terminated the test if (*num_completed == 0) { snaps->maybe_speed(ct, [&](double el, double x) { log_speed(logger, "download-speed", params.num_streams, el, x); (*report_entry)["receiver_data"].push_back({el, x}); }); } // TODO: force close the connection after a given // large amount of time has passed }); txp->on_error([=](Error err) { if (err == EofError()) { err = NoError(); } if (err) { logger->info("Ending download (%d)", err.code); } txp->close([=]() { ++(*num_completed); // Note: in this callback we cannot reference // txp_list or txp because that would keep // alive txp indefinitely, so we use the num_flows // variable instead (note that this means that // the `=` only copies what you use, a thing that // I was totally unaware of!) if (*num_completed < num_flows) { return; } double speed = average->speed(); logger->debug("S2C speed %lf kbit/s", speed); // XXX We need to define what we consider // error when we have parallel flows cb((num_flows == 1) ? err : NoError(), speed); }); }); } }); }, settings, reactor, logger); } template void finalizing_test_impl(Var ctx, Var cur_entry, Callback callback) { ctx->logger->debug("ndt: recv TEST_MSG ..."); messages_read_msg(ctx, [=](Error err, uint8_t type, std::string s) { ctx->logger->debug("ndt: recv TEST_MSG ... %d", (int)err); if (err) { callback(ReadingTestMsgError(err)); return; } if (type == TEST_FINALIZE) { // Okay, now that we've reached the final state, we can append // the current entry to the entry of the whole NDT test (*ctx->entry)["test_s2c"].push_back(*cur_entry); callback(NoError()); return; } if (type != TEST_MSG) { callback(NotTestMsgError()); return; } for (auto e : split(s, "\n")) { if (e != "") { ctx->logger->debug("%s", e.c_str()); messages::add_to_report(cur_entry, "web100_data", e); } } // XXX: Here we can loop forever finalizing_test_impl(ctx, cur_entry, callback); }, ctx->reactor); } template void run_impl(Var ctx, Callback callback) { // The server sends us the PREPARE message containing the port number ctx->logger->debug("ndt: recv TEST_PREPARE ..."); messages_read_msg_first(ctx, [=](Error err, uint8_t type, std::string s) { ctx->logger->debug("ndt: recv TEST_PREPARE ... %d", err.code); if (err) { callback(ReadingTestPrepareError(err)); return; } if (type != TEST_PREPARE) { callback(NotTestPrepareError()); return; } Params params; std::vector vec = split>(s); ErrorOr port = lexical_cast_noexcept(vec[0]); if (!port || *port < 0 || *port > 65535) { ctx->logger->warn("Received invalid port: %s", vec[0].c_str()); callback(InvalidPortError()); return; } params.port = *port; // Here we are being liberal; in theory we should only accept these // extra parameters when the test is S2C_EXT if (vec.size() >= 2) { ErrorOr duration = lexical_cast_noexcept(vec[1]); if (!duration or *duration < 0 or *duration > 60000.0) { ctx->logger->warn("Received invalid duration: %s", vec[1].c_str()); callback(InvalidDurationError()); return; } params.duration = *duration / 1000.0; } ctx->logger->debug("Duration: %f s", params.duration); ctx->logger->debug("Snaps-enabled: /* ignored */"); // TODO: implement if (vec.size() >= 4) { ErrorOr snaps_delay = lexical_cast_noexcept(vec[3]); if (!snaps_delay or *snaps_delay < 250.0) { ctx->logger->warn("Received invalid snaps-delay: %s", vec[3].c_str()); callback(InvalidSnapsDelayError()); return; } params.snaps_delay = *snaps_delay / 1000.0; } ctx->logger->debug("Snaps-delay: %f s", params.snaps_delay); ctx->logger->debug("Snaps-offset: /* ignored */"); // TODO: implement if (vec.size() >= 6) { ErrorOr num_streams = lexical_cast_noexcept(vec[5]); if (!num_streams or *num_streams < 1 or *num_streams > 8) { ctx->logger->warn("Received invalid num-streams: %s", vec[5].c_str()); callback(InvalidNumStreamsError()); return; } params.num_streams = *num_streams; } ctx->logger->debug("Num-streams: %d", params.num_streams); Var cur_entry(new Entry); (*cur_entry)["web100_data"] = Entry::object(); (*cur_entry)["params"] = Entry::object(); (*cur_entry)["receiver_data"] = Entry::array(); // We connect to the port and wait for coroutine to pause ctx->logger->debug("ndt: start s2c coroutine ..."); coroutine( cur_entry, ctx->address, params, [=](Error err, Continuation cc) { ctx->logger->debug("ndt: start s2c coroutine ... %d", (int)err); if (err) { callback(ConnectTestConnectionError(err)); return; } // The server sends us the START message to tell we can start ctx->logger->debug("ndt: recv TEST_START ..."); messages_read_msg_second(ctx, [=](Error err, uint8_t type, std::string) { ctx->logger->debug("ndt: recv TEST_START ... %d", (int)err); if (err) { callback(ReadingTestStartError(err)); return; } if (type != TEST_START) { callback(NotTestStartError()); return; } // We resume coroutine and wait for its completion ctx->logger->debug("ndt: resume s2c coroutine"); cc([=](Error err, double speed) { ctx->logger->debug("ndt: s2c coroutine complete"); if (err) { callback(err); return; } // The server sends us MSG containing throughput ctx->logger->debug("ndt: recv TEST_MSG ..."); messages_read_json(ctx, [=](Error err, uint8_t type, json m) { ctx->logger->debug("ndt: recv TEST_MSG ... %d", (int)err); if (err) { callback(ReadingTestMsgError(err)); return; } if (type != TEST_MSG) { callback(NotTestMsgError()); return; } // TODO: if we will ever parse `m` remember about // possible access errors for json objects ctx->logger->debug("ndt: speed %s", m.dump().c_str()); // We send our measured throughput to the server ctx->logger->debug("ndt: send TEST_MSG ..."); ErrorOr out = messages_format_test_msg( lexical_cast(speed)); if (!out) { callback(SerializingTestMsgError()); return; } messages_write(ctx, *out, [=](Error err) { ctx->logger->debug("ndt: send TEST_MSG ... %d", (int)err); if (err) { callback(WritingTestMsgError(err)); return; } // We enter into the final state of this test finalizing_test(ctx, cur_entry, callback); }); }, ctx->reactor); }); }, ctx->reactor); }, ctx->timeout, ctx->settings, ctx->reactor, ctx->logger); }, ctx->reactor); } } // namespace test_s2c } // namespace ndt } // namespace mk #endif measurement-kit-0.7.1/include/private/ndt/utils.hpp000066400000000000000000000013721315356162600223770ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NDT_UTILS_HPP #define PRIVATE_NDT_UTILS_HPP #include "../ndt/internal.hpp" namespace mk { namespace ndt { namespace utils { report::Entry compute_ping(report::Entry &test_s2c, Var logger); report::Entry compute_speed(report::Entry &sender_or_receiver_data, const char *speed_type, Var logger); report::Entry compute_simple_stats(report::Entry &entry, Var logger); report::Entry compute_advanced_stats(report::Entry &entry, Var logger); } // namespace utils } // namespace ndt } // namespace mk #endif measurement-kit-0.7.1/include/private/net/000077500000000000000000000000001315356162600205245ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/net/builtin_ca_bundle.hpp000066400000000000000000000007101315356162600246750ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NET_BUILTIN_CA_BUNDLE_HPP #define PRIVATE_NET_BUILTIN_CA_BUNDLE_HPP #include #include #include #include namespace mk { namespace net { std::vector builtin_ca_bundle(); } // namespace net } // namespace mk #endif measurement-kit-0.7.1/include/private/net/connect.hpp000066400000000000000000000037441315356162600226760ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NET_CONNECT_HPP #define PRIVATE_NET_CONNECT_HPP #include "../common/utils.hpp" #include "../ext/tls_internal.h" #include #include #include struct bufferevent; struct ssl_st; extern "C" { void mk_bufferevent_on_event(bufferevent *, short, void *); } namespace mk { namespace net { class ConnectResult { public: dns::ResolveHostnameResult resolve_result; std::vector connect_result; double connect_time = 0.0; bufferevent *connected_bev = nullptr; }; typedef std::function, bufferevent *)> ConnectFirstOfCb; void connect_first_of(Var result, int port, ConnectFirstOfCb cb, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global(), size_t index = 0, Var> errors = nullptr); void connect_logic(std::string hostname, int port, Callback> cb, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()); void connect_ssl(bufferevent *orig_bev, ssl_st *ssl, std::string hostname, Callback cb, Var = Reactor::global(), Var = Logger::global()); class ConnectManyCtx { public: int left = 0; // Signed to detect programmer errors ConnectManyCb callback; std::vector> connections; std::string address; int port = 0; Settings settings; Var reactor = Reactor::global(); Var logger = Logger::global(); }; } // namespace mk } // namespace net #endif measurement-kit-0.7.1/include/private/net/connect_impl.hpp000066400000000000000000000154751315356162600237230ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NET_CONNECT_IMPL_HPP #define PRIVATE_NET_CONNECT_IMPL_HPP #include "private/common/mock.hpp" #include "private/common/mock.hpp" #include #include #include #include #include "../common/utils.hpp" #include "../net/connect.hpp" #include "../net/utils.hpp" struct bufferevent; extern "C" { void mk_bufferevent_on_event(bufferevent *, short, void *); } namespace mk { namespace net { // Proxy required because `make_sockaddr` is overloaded static Error make_sockaddr_proxy(std::string s, std::string p, sockaddr_storage *ss, socklen_t *len) { return make_sockaddr(s, p, ss, len); } template void connect_base(std::string address, int port, Callback cb, double timeout = 10.0, Var reactor = Reactor::global(), Var logger = Logger::global()) { std::string endpoint = [&]() { Endpoint endpoint; endpoint.hostname = address; endpoint.port = (uint16_t)port; /* XXX We should change the prototype */ return serialize_endpoint(endpoint); }(); logger->debug("connect_base %s", endpoint.c_str()); std::string port_string = std::to_string(port); sockaddr_storage storage = {}; socklen_t salen = 0; Error err = make_sockaddr_proxy(address, port_string, &storage, &salen); if (err != NoError()) { logger->warn("cannot parse endpoint: '%s'", endpoint.c_str()); cb(err, nullptr, 0.0); return; } sockaddr *saddr = (sockaddr *)&storage; /* * Rationale for deferring callbacks: * * When using IOCP on Windows, the kernel calls callbacks when selected * events occur (i.e., there is no loop that guarantees callbacks run in * the same thread); set DEFER_CALLBACKS to tell libevent to serialize * bufferevent's callbacks into the event loop to avoid creating MT issues * in code that otherwise (on Unices) is single threaded. * * Yes, the current implementation forces serializing the callbacks also * on Unix where this wouldn't be needed thus adding some overhead. For * uniformity, I am for serializing for all platforms and then, if we see * that there's too much overhead, to only enable that on Windows. */ static const int flags = BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS; bufferevent *bev; if ((bev = bufferevent_socket_new(reactor->get_event_base(), -1, flags)) == nullptr) { throw GenericError(); // This should not happen } timeval tv, *tvp = timeval_init(&tv, timeout); if (bufferevent_set_timeouts(bev, tvp, tvp) != 0) { bufferevent_free(bev); throw GenericError(); // This should not happen } double begin = mk::time_now(); if (bufferevent_socket_connect(bev, saddr, salen) != 0) { logger->warn("connect() for %s failed immediately", endpoint.c_str()); bufferevent_free(bev); Error sys_error = mk::net::map_errno(errno); if (sys_error == NoError()) { sys_error = GenericError(); /* We must report an error */ } logger->warn("reason why connect() has failed: %s", sys_error.as_ooni_error().c_str()); cb(sys_error, nullptr, 0.0); return; } logger->debug("connect() in progress..."); // WARNING: set callbacks after connect() otherwise we free `bev` twice // NOTE: In case of `new` failure we let the stack unwind bufferevent_setcb( bev, nullptr, nullptr, mk_bufferevent_on_event, new Callback([=](Error err, bufferevent *bev) { if (err) { logger->warn("connect() for %s failed in its callback", endpoint.c_str()); bufferevent_free(bev); logger->warn("reason why connect() has failed: %s", err.as_ooni_error().c_str()); cb(err, nullptr, 0.0); return; } double elapsed = mk::time_now() - begin; logger->debug("connect time: %f", elapsed); cb(err, bev, elapsed); })); } template void connect_many_impl(Var ctx) { // Implementation note: this function connects sequentially, which // is slower but also much simpler to implement and verify if (ctx->left <= 0) { Error err = NoError(); ctx->callback(err, ctx->connections); return; } net_connect(ctx->address, ctx->port, [=](Error err, Var txp) { ctx->connections.push_back(std::move(txp)); if (err) { ctx->callback(err, ctx->connections); return; } --ctx->left; connect_many_impl(ctx); }, ctx->settings, ctx->reactor, ctx->logger); } static inline Var connect_many_make(std::string address, int port, int count, ConnectManyCb callback, Settings settings, Var reactor, Var logger) { Var ctx(new ConnectManyCtx); ctx->left = count; ctx->callback = callback; ctx->address = address; ctx->port = port; ctx->settings = settings; ctx->reactor = reactor; ctx->logger = logger; return ctx; } static inline Var make_txp(Var txp, double timeout, Var r) { if (timeout > 0.0) { txp->set_timeout(timeout); } if (!!r) { txp->set_connect_time_(r->connect_time); txp->set_connect_errors_(r->connect_result); txp->set_dns_result_(r->resolve_result); } return txp; } template Var make_txp(double timeout, Var r, Args &&... args) { // Note: need to pass through `make_shared` because the new Transport that // cannot inherit from `shared_ptr` because of the new NDK is less simple // to use than the one that inherited from `shared_ptr`. I guess there must // be some constructor override that is missing. return make_txp( Var{std::make_shared(std::forward(args)...)}, timeout, r); } } // namespace mk } // namespace net #endif measurement-kit-0.7.1/include/private/net/emitter.hpp000066400000000000000000000157751315356162600227250ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NET_EMITTER_HPP #define PRIVATE_NET_EMITTER_HPP #include #include namespace mk { namespace net { class EmitterBase : public Transport { public: EmitterBase(Var reactor, Var logger) : reactor(reactor), logger(logger) {} ~EmitterBase() override; /* * TransportEmitter */ void emit_connect() override { logger->log(MK_LOG_DEBUG2, "emitter: emit 'connect' event"); if (close_pending) { logger->log(MK_LOG_DEBUG2, "emitter: already closed; ignoring"); return; } if (!do_connect) { logger->log(MK_LOG_DEBUG2, "emitter: no handler set; ignoring"); return; } do_connect(); } void emit_data(Buffer data) override { logger->log(MK_LOG_DEBUG2, "emitter: emit 'data' event " "(num_bytes = %zu)", data.length()); if (close_pending) { logger->log(MK_LOG_DEBUG2, "emitter: already closed; ignoring"); return; } if (do_record_received_data) { received_data_record.write(data.peek()); } if (!do_data) { logger->log(MK_LOG_DEBUG2, "emitter: no handler set; ignoring"); return; } do_data(data); } void emit_flush() override { logger->log(MK_LOG_DEBUG2, "emitter: emit 'flush' event"); if (close_pending) { logger->log(MK_LOG_DEBUG2, "emitter: already closed; ignoring"); return; } if (!do_flush) { logger->log(MK_LOG_DEBUG2, "emitter: no handler set; ignoring"); return; } do_flush(); } void emit_error(Error err) override { logger->log(MK_LOG_DEBUG2, "emitter: emit 'error' event " "(error = '%s')", err.explain().c_str()); if (close_pending) { logger->log(MK_LOG_DEBUG2, "emitter: already closed; ignoring"); return; } if (!do_error) { logger->log(MK_LOG_DEBUG2, "emitter: no handler set; ignoring"); return; } do_error(err); } void on_connect(std::function fn) override { logger->log(MK_LOG_DEBUG2, "emitter: %sregister 'connect' handler", (fn != nullptr) ? "" : "un"); do_connect = fn; } void on_data(std::function fn) override { logger->log(MK_LOG_DEBUG2, "emitter: %sregister 'data' handler", (fn != nullptr) ? "" : "un"); if (close_pending) { logger->log(MK_LOG_DEBUG2, "emitter: already closed; ignoring"); return; } if (fn) { start_reading(); } else { stop_reading(); } do_data = fn; } void on_flush(std::function fn) override { logger->log(MK_LOG_DEBUG2, "emitter: %sregister 'flush' handler", (fn != nullptr) ? "" : "un"); do_flush = fn; } void on_error(std::function fn) override { logger->log(MK_LOG_DEBUG2, "emitter: %sregister 'error' handler", (fn != nullptr) ? "" : "un"); do_error = fn; } void close(Callback<> cb) override; /* * TransportRecorder */ void record_received_data() override { do_record_received_data = true; } void dont_record_received_data() override { do_record_received_data = false; } Buffer &received_data() override { return received_data_record; } void record_sent_data() override { do_record_sent_data = true; } void dont_record_sent_data() override { do_record_sent_data = false; } Buffer &sent_data() override { return sent_data_record; } /* * TransportWriter */ void write(const void *p, size_t n) override { logger->log(MK_LOG_DEBUG2, "emitter: send opaque data"); if (p == nullptr) { throw std::runtime_error("null pointer"); } write(Buffer(p, n)); } void write(std::string s) override { logger->log(MK_LOG_DEBUG2, "emitter: send string"); write(Buffer(s)); } void write(Buffer data) override { logger->log(MK_LOG_DEBUG2, "emitter: send buffer"); if (do_record_sent_data) { sent_data_record.write(data.peek()); } output_buff << data; if (close_pending) { logger->log(MK_LOG_DEBUG2, "emitter: already closed; ignoring"); return; } start_writing(); } /* * TransportSocks5 */ std::string socks5_address() override { return ""; } std::string socks5_port() override { return ""; } /* * TransportPollable */ void set_timeout(double timeo) override { if (close_pending) { return; } adjust_timeout(timeo); } void clear_timeout() override { set_timeout(-1); } // Protected methods of TransportPollable: not implemented /* * TransportConnectable */ double connect_time() override { return saved_connect_time; } void set_connect_time_(double x) override { saved_connect_time = x; } std::vector connect_errors() override { return saved_connect_errors; } void set_connect_errors_(std::vector x) override { saved_connect_errors = x; } dns::ResolveHostnameResult dns_result() override { return saved_dns_result; } void set_dns_result_(dns::ResolveHostnameResult x) override { saved_dns_result = x; } Endpoint sockname() override { return {}; } Endpoint peername() override { return {}; } protected: // TODO: it would probably better to have accessors Var reactor = Reactor::global(); Var logger = Logger::global(); Buffer output_buff; private: Delegate<> do_connect; Delegate do_data; Delegate<> do_flush; Delegate do_error; bool do_record_received_data = false; Buffer received_data_record; bool do_record_sent_data = false; Buffer sent_data_record; Callback<> close_cb; bool close_pending = false; double saved_connect_time = 0.0; std::vector saved_connect_errors; dns::ResolveHostnameResult saved_dns_result; }; class Emitter : public EmitterBase { public: Emitter(Var reactor, Var logger) : EmitterBase(reactor, logger) {} ~Emitter() override; protected: void adjust_timeout(double timeo) override { logger->log(MK_LOG_DEBUG2, "emitter: adjust_timeout %f", timeo); } void shutdown() override {} void start_reading() override {} void stop_reading() override {} void start_writing() override {} }; } // namespace net } // namespace mk #endif measurement-kit-0.7.1/include/private/net/evbuffer.hpp000066400000000000000000000013211315356162600230360ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NET_EVBUFFER_HPP #define PRIVATE_NET_EVBUFFER_HPP #include "private/common/mock.hpp" #include "private/common/mock.hpp" #include #include namespace mk { namespace net { template Var make_shared_evbuffer() { evbuffer *p = evbuffer_new(); if (p == nullptr) { throw std::bad_alloc(); } return Var(p, [](evbuffer *x) { evbuffer_free(x); }); } } // namespace net } // namespace mk #endif measurement-kit-0.7.1/include/private/net/libssl.hpp000066400000000000000000000301761315356162600225340ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software under the BSD license. See AUTHORS // and LICENSE for more information on the copying conditions. #ifndef PRIVATE_NET_LIBSSL_HPP #define PRIVATE_NET_LIBSSL_HPP // ## libssl /*- _ _ _ _ | (_) |__ ___ ___| | | | | '_ \/ __/ __| | | | | |_) \__ \__ \ | |_|_|_.__/|___/___/_| */ /// \file private/net/libssl.hpp /// \brief Code related to libssl (openssl or libressl). #include "private/common/mock.hpp" #include "private/ext/tls_internal.h" #include "private/net/builtin_ca_bundle.hpp" #include #include #include #include #include #include #include #include #include #include namespace mk { namespace net { namespace libssl { /// Initialize the SSL library static inline void libssl_init_once(Var logger) { locked_global([logger]() { static bool initialized = false; if (!initialized) { logger->debug("initializing SSL library"); SSL_library_init(); ERR_load_crypto_strings(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); initialized = true; } }); } /*! \brief Wrapper for SSL context (`SSL_CTX *`). This class wraps `SSL_CTX *` providing RAII destructor and allowing to create a `SSL *` from the managed `SSL_CTX *` object. */ class Context : public NonCopyable, public NonMovable { public: /* Implementation notes -------------------- 1. libssl uses reference counting[1], meaning that the `SSL_CTX *` will be alive as long as there's a `SSL *` using it. 2. this class does not take any measure to prevent access from multiple threads even though it is not generally wise to assume that OpenSSL will do what you expect on a MT environment [2]. The policy for managing `Context`s in a MT environment should instead be enforced by the `Cache` implementation (below). 3. since it manages a C pointer, this class MUST be non-copyable and non-movable to prevent multiple-free bugs. Links ----- .. [1] https://wiki.openssl.org/index.php/Manual:SSL_CTX_free(3) .. [2] https://github.com/openssl/openssl/issues/2165 */ /*! \brief Creates a `SSL *` from the wrapped `SSL_CTX *`. \param hostname Hostname for which to create the `SSL *`. This would be the hostname for which you want to use SNI. \param logger The logger to use to emit log messages. \return An error on failure (the returned object will evaluate to false in a boolean context) and a `SSL *` on success. */ template ErrorOr get_client_ssl(std::string hostname, Var logger) { assert(ctx_ != nullptr); SSL *ssl = SSL_new(ctx_); if (ssl == nullptr) { logger->warn("ssl: SSL_new failed"); return SslNewError(); } SSL_set_tlsext_host_name(ssl, hostname.c_str()); return ssl; } /// Destructor. ~Context() { assert(ctx_ != nullptr); SSL_CTX_free(ctx_); } /*! \brief Factory that creates a shared `SSL_CTX *` wrapper. \param ca_bundle_path Path to the CA bundle to be used to verify the servers we're connecting to. If it is empty and we're linking with libressl, we will use the builtin CA bundle that is shipped along with measurement-kit. Otherwise, we will fail. \param logger Logger for printing log messages. \return An error on failure (the returned object will evaluate to false in a boolean context) or a `Var` shared pointer wrapping a Context instance on success. */ template = 0x2010400fL) , MK_MOCK(SSL_CTX_load_verify_mem) #endif > static ErrorOr> make(std::string ca_bundle_path, Var logger) { // Implementation note: we need to initialize libssl early otherwise // most of the functions of the library will not work properly. libssl_init_once(logger); logger->debug("ssl: creating SSL_CTX with bundle: '%s'", ca_bundle_path.c_str()); SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method()); if (ctx == nullptr) { logger->warn("ssl: failed to create SSL_CTX"); return SslCtxNewError(); } /* * Implementation note: * * We use SSLv23_client_method() because it is the most general method * that applications SHOULD use according to the manual[1] and we * disable by default deprecated protocols. We will enable them * in the OONI's web_connectivity test so to measure more websites. * * [1] https://wiki.openssl.org/index.php/Manual:SSL_CTX_new(3) */ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); if (ca_bundle_path != "") { if (!SSL_CTX_load_verify_locations(ctx, ca_bundle_path.c_str(), nullptr)) { logger->warn("ssl: failed to load verify location"); SSL_CTX_free(ctx); return SslCtxLoadVerifyLocationsError(); } } else { #if (defined LIBRESSL_VERSION_NUMBER && LIBRESSL_VERSION_NUMBER >= 0x2010400fL) std::vector bundle = builtin_ca_bundle(); logger->debug("ssl: using builtin libressl's ca bundle"); if (!SSL_CTX_load_verify_mem(ctx, bundle.data(), bundle.size())) { logger->warn("ssl: failed to load default ca bundle"); SSL_CTX_free(ctx); return SslCtxLoadVerifyMemError(); } #else SSL_CTX_free(ctx); return MissingCaBundlePathError(); #endif } SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, nullptr); Var context{new Context}; context->ctx_ = ctx; return context; } private: Context() {} SSL_CTX *ctx_ = nullptr; }; /*! \brief Thread-safe cache for constructing `SSL *` objects. \remark Unless you need low-level control, you SHOULD really use this API for creating an `SSL *` when connecting to an host. */ template class Cache { public: /* Implementation notes -------------------- 1. both on mobile and on desktop devices we should generally use just a single `SSL_CTX *`, either setup for using the bundled CA bundle (for mobile devices) or using a system-wide CA (desktop). However, for flexibility, we have allowed for many `SSL_CTX *`. To avoid the cache potentially becoming too large (perhaps also because of bugs) we have set a large hard limit on the maximum number of `SSL_CTX *` that we keep open concurrently. 2. since assuming OpenSSL will correctly behave in a MT environment seem to be an over-assumption (see above for links), I decided to stay on the safe side an make the cache thread local. After #1297 is merged, this means that every "big" task (i.e. a test, orchestration, etc) will use its own thread local cache. Overall, this choice is a bit more defensive than needed, perhaps, but I do also see some advantages in not keeping `SSL_CTX *` - and hence all related caching - alive "forever". So I think it's okay. */ /// Return thread local instance of the cache. static Cache &thread_local_instance() { static thread_local Cache instance; return instance; } /// Inline wrapper for Context::make, for testability static inline ErrorOr> mkctx(std::string ca_bundle_path, Var logger) { return Context::make(ca_bundle_path, logger); } /*! \brief Factory to construct an `SSL *`. \param ca_bundle_path The CA bundle path to use. This should be set using the `net/ca_bundle_path` configuration variable. \param hostname Hostname for which you want to do SSL and which will be used in the SNI extension. \param logger Logger used to log messages. \return Error on failure (the returned object will be false when evaluated in a boolean context) or `SSL *` on success. \remark This factory gives you the ownership of the returned `SSL *` object and it is your responsibility to dispose of it when done. In practice, when using libevent, you will typically pass the `SSL *` to a bufferevent that will own it. \remark This operation is thread safe by definition since the cache is created using thread-local storage. */ template ErrorOr get_client_ssl(std::string ca_bundle_path, std::string hostname, Var logger) { /* Implementation note: `SSL_CTX *` are reference counted and they will be alive as long as there is an `SSL *` using them. As such, we do not need to worry about `all_.clear()` causing `SSL_CTX_free` to be called on the `SSL_CTX *` we indirectly manage, because the usage count semantic will keep us safe from premature frees. See above for a specific link re: refcounting. */ if (all_.size() >= max_cache_size) { logger->warn("ssl: hit hard limit of maximum cached SSL_CTX"); all_.clear(); } if (all_.count(ca_bundle_path) == 0) { ErrorOr> maybe_context = mkctx(ca_bundle_path, logger); if (!maybe_context) { return maybe_context.as_error(); } logger->debug("ssl: track ctx for: '%s'", ca_bundle_path.c_str()); all_[ca_bundle_path] = *maybe_context; } Var context = all_[ca_bundle_path]; return context->get_client_ssl(hostname, logger); } /// Return number of cached SSL_CTX size_t size() const { return all_.size(); } /// Constructor Cache() {} private: std::map> all_; }; /*! \brief Verify SSL peer. \param hostname Expected SNI hostname. \param ssl Pointer to SSL struct. \param logger Logger used for logging. \return NoError() on success, an error on failure. */ template Error verify_peer(std::string hostname, SSL *ssl, Var logger) { assert(ssl != nullptr); logger->debug("SSL version: %s", SSL_get_version(ssl)); long verify_err = SSL_get_verify_result(ssl); if (verify_err != X509_V_OK) { logger->warn("ssl: got an invalid certificate"); return SslInvalidCertificateError( X509_verify_cert_error_string(verify_err)); } X509 *server_cert = SSL_get_peer_certificate(ssl); if (server_cert == nullptr) { logger->warn("ssl: got no certificate"); return SslNoCertificateError(); } auto match = 0; auto err = tls_check_name(nullptr, server_cert, hostname.c_str(), &match); X509_free(server_cert); // Make sure we don't leak memory if (err != 0) { logger->warn("ssl: got invalid hostname"); return SslInvalidHostnameError(); } if (!match) { logger->warn("ssl: name not present in server certificate"); return SslMissingHostnameError(); } return NoError(); } /// Enable SSLv2 and SSLv3 for the selected connection static inline void enable_v23(SSL *ssl) { SSL_clear_options(ssl, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); } } // namespace libssl } // namespace net } // namespace mk #endif measurement-kit-0.7.1/include/private/net/socks5.hpp000066400000000000000000000041101315356162600224400ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NET_SOCKS5_HPP #define PRIVATE_NET_SOCKS5_HPP #include "../net/emitter.hpp" #include namespace mk { namespace net { /* * TODO: now that events are not emitted after close, we can safely * refactor this as a factory function, because we do not need to * worry about whether the `on_connect` callback has invoked `close` * before emitting `DATA` with extra data that we may have read. */ class Socks5 : public Emitter { public: // Constructor that attaches to already existing transport Socks5(Var, Settings, Var, Var); void set_timeout(double timeout) override { conn->set_timeout(timeout); } void clear_timeout() override { conn->clear_timeout(); } protected: void adjust_timeout(double) override { /* NOTHING */ } void start_writing() override { conn->write(output_buff); } public: void close(std::function callback) override { isclosed = true; conn->close(callback); } std::string socks5_address() override { return proxy_address; } std::string socks5_port() override { return proxy_port; } protected: void socks5_connect_(); Settings settings; Var conn; Buffer buffer; bool isclosed = false; std::string proxy_address; std::string proxy_port; }; Buffer socks5_format_auth_request(Var = Logger::global()); ErrorOr socks5_parse_auth_response(Buffer &, Var = Logger::global()); ErrorOr socks5_format_connect_request(Settings, Var = Logger::global()); ErrorOr socks5_parse_connect_response(Buffer &, Var = Logger::global()); void socks5_connect(std::string address, int port, Settings settings, std::function)> callback, Var reactor = Reactor::global(), Var logger = Logger::global()); } // namespace net } // namespace mk #endif measurement-kit-0.7.1/include/private/net/utils.hpp000066400000000000000000000022501315356162600223740ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NET_UTILS_HPP #define PRIVATE_NET_UTILS_HPP #include struct sockaddr_storage; namespace mk { namespace net { int storage_init( sockaddr_storage *storage, socklen_t *length, const char *family, const char *address, const char *port, Var logger ); int storage_init( sockaddr_storage *storage, socklen_t *length, int family, const char *address, const char *port, Var logger ); int storage_init( sockaddr_storage *storage, socklen_t *length, int family, const char *address, int port, Var logger ); socket_t socket_create( int domain, int type, int protocol, Var logger ); std::string unreverse_ipv6(std::string s); std::string unreverse_ipv4(std::string s); Error disable_nagle(socket_t); Error map_errno(int); } // namespace net } // namespace mk #endif measurement-kit-0.7.1/include/private/nettests/000077500000000000000000000000001315356162600216075ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/nettests/runnable.hpp000066400000000000000000000060421315356162600241300ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NETTESTS_RUNNABLE_HPP #define PRIVATE_NETTESTS_RUNNABLE_HPP #include #include #include #include #include namespace mk { namespace nettests { class Runnable : public NonCopyable, public NonMovable { public: void begin(Callback); void end(Callback); virtual ~Runnable(); Var logger = Logger::make(); Var reactor; /* Left unspecified on purpose */ Settings options; std::list input_filepaths; std::deque inputs; std::string output_filepath; Delegate entry_cb; Delegate<> begin_cb; std::list> end_cbs; std::list> destroy_cbs; bool needs_input = false; bool use_bouncer = true; std::map test_helpers_data; std::string test_name = "ooni_test"; std::string test_version = "0.0.1"; std::string probe_ip = "127.0.0.1"; std::string probe_asn = "AS0"; std::string probe_cc = "ZZ"; std::string resolver_ip = "127.0.0.1"; protected: // Functions that derived classes SHOULD override virtual void setup(std::string); virtual void teardown(std::string); virtual void main(std::string, Settings, Callback>); virtual void fixup_entry(report::Entry &); // Functions that derived classes should access std::list test_helpers_option_names(); std::list test_helpers_bouncer_names(); private: report::Report report; tm test_start_time; double beginning = 0.0; void run_next_measurement(size_t, Callback, size_t, Var); void query_bouncer(Callback); void geoip_lookup(Callback<>); void open_report(Callback); std::string generate_output_filepath(); }; #define MK_DECLARE_RUNNABLE(_name_) \ class _name_ : public Runnable { \ public: \ void main(std::string, Settings, \ Callback>) override; \ } MK_DECLARE_RUNNABLE(DashRunnable); MK_DECLARE_RUNNABLE(DnsInjectionRunnable); MK_DECLARE_RUNNABLE(HttpHeaderFieldManipulationRunnable); MK_DECLARE_RUNNABLE(HttpInvalidRequestLineRunnable); MK_DECLARE_RUNNABLE(MeekFrontedRequestsRunnable); MK_DECLARE_RUNNABLE(MultiNdtRunnable); MK_DECLARE_RUNNABLE(NdtRunnable); MK_DECLARE_RUNNABLE(TcpConnectRunnable); // Separate definition because it contains extra methods class WebConnectivityRunnable : public Runnable { public: void main(std::string, Settings, Callback>) override; void fixup_entry(report::Entry &) override; }; } // namespace nettests } // namespace mk #endif measurement-kit-0.7.1/include/private/nettests/runner.hpp000066400000000000000000000011771315356162600236370ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NETTESTS_RUNNER_HPP #define PRIVATE_NETTESTS_RUNNER_HPP #include "private/common/async_runner.hpp" #include namespace mk { namespace nettests { class Runnable; class Runner : public HasGlobalFactory { public: void start_test(Var test, Callback> func); void stop(); bool empty(); private: AsyncRunner impl_; }; } // namespace nettests } // namespace mk #endif measurement-kit-0.7.1/include/private/nettests/utils.hpp000066400000000000000000000047341315356162600234700ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NETTESTS_UTILS_HPP #define PRIVATE_NETTESTS_UTILS_HPP #include #include namespace mk { namespace nettests { /** * @brief Generates the list of entries to be tested. * * @param input The input deque containing input. Note that it may already * contain input that has been manually specified by the user. * * @param needs_input If this value is false, the function returns just a * single, empty entry; otherwise, the function reads and returns as entries * all lines of the files provided as argument. * * @param input_filepaths When input is required, files to read; a missing * or non-readable file is not considered fatal and a warning will be * printed in such case, using the logger. * * @param probe_cc Country code of the probe: if a file path contains the * "${probe_cc}" string, this is expanded to the country code in lower case. * * @param options If the boolean "randomize_input" option is true, this * function randomizes the list of entries before returning it. * * @param logger Used to print log messages. * * @param on_open_error In case it is not possible to open a file, and * the function is not `nullptr`, the file name that failed is passed to * this function. * * @param on_io_error In case reading a file fails with I/O error, and * the function is not `nullptr`, the file name that failed is passed to * this function. * * @returns one of the following errors: * * - NoError if everything was okay * * - MissingRequiredInputFileError if needs_input is true and no input * file is passed through the input_filepaths argument * * - CannotReadAnyInputFileError if needs_input is true and the list of * entries to be tested is empty after processing all input files * * - the error returned when trying to convert to boolean the value of * "randomize_input" setting (e.g. ValueError) */ Error process_input_filepaths( std::deque &input, const bool &needs_input, const std::list &input_filepaths, const std::string &probe_cc, const Settings &options, Var logger, std::function on_open_error, std::function on_io_error ); } // namespace nettests } // namespace mk #endif measurement-kit-0.7.1/include/private/nettests/utils_impl.hpp000066400000000000000000000075701315356162600245120ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NETTESTS_UTILS_IMPL_HPP #define PRIVATE_NETTESTS_UTILS_IMPL_HPP #include "private/common/mock.hpp" #include "../nettests/utils.hpp" #include #include #include namespace mk { namespace nettests { static Var open_file_(const std::string &path) { return Var{new std::ifstream{path}}; } static bool readline_(std::istream &input, std::string &line) { return static_cast(std::getline(input, line)); } static void randomize_input_(std::deque &inputs) { // See http://en.cppreference.com/w/cpp/algorithm/shuffle std::random_device rd; std::mt19937 g(rd()); std::shuffle(inputs.begin(), inputs.end(), g); } template Error process_input_filepaths_impl(std::deque &inputs, const bool &needs_input, const std::list &input_filepaths, const std::string &probe_cc, const Settings &options, Var logger, std::function on_open_error, std::function on_io_error) { if (needs_input) { if (input_filepaths.size() <= 0 && inputs.size() == 0) { logger->warn("at least an input file is required"); return ooni::MissingRequiredInputFileError(); } /* * Note: in general the snippet below is not * so good because it does not work for UTF-8 * and the like but here we are converting * country codes which are always ASCII. */ std::string probe_cc_lowercase = ""; for (auto c : probe_cc) { probe_cc_lowercase += std::tolower(c); } for (auto input_filepath : input_filepaths) { input_filepath = std::regex_replace(input_filepath, std::regex{R"(\$\{probe_cc\})"}, probe_cc_lowercase); Var input_generator = open_file_(input_filepath); if (!input_generator->good()) { logger->warn("cannot open input file"); if (!!on_open_error) { on_open_error(input_filepath); } continue; } std::string next_input; while ((readline_(*input_generator, next_input))) { inputs.push_back(next_input); } if (!input_generator->eof()) { logger->warn("I/O error reading input file"); if (!!on_io_error) { on_io_error(input_filepath); } continue; } } if (inputs.size() <= 0) { logger->warn("no specified input file could be read"); return ooni::CannotReadAnyInputFileError(); } ErrorOr shuffle = options.get_noexcept("randomize_input", true); if (!shuffle) { logger->warn("invalid 'randomize_input' option"); return shuffle.as_error(); } if (*shuffle) { randomize_input_(inputs); } } else { // Add empty string to call main just once. Due to the way in which // we work, we clear the input if it's not empty, otherwise input-less // tests are going to run more than once. if (inputs.size() != 0) { logger->warn("Manually passed input for a test that requires no " "input; fixing by clearing the input vector"); inputs.clear(); } inputs.push_back(""); } return NoError(); } } // namespace nettests } // namespace mk #endif measurement-kit-0.7.1/include/private/neubot/000077500000000000000000000000001315356162600212325ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/neubot/dash_impl.hpp000066400000000000000000000623131315356162600237100ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_NEUBOT_DASH_IMPL_HPP #define PRIVATE_NEUBOT_DASH_IMPL_HPP /* * Here we implement the measurement methodology described in "Measuring * DASH Streaming Performance from the End Users Perspective using Neubot", * by S. Basso, A. Servetti, E. Masala, J.C. De Martin. * * See: https://nexa.polito.it/publications/basso2014measuring * * Differences from the methodology outlined in the paper: * * 1. By default, we don't scale down significantly the speed after we * sense some queue in the network. That was meant to avoid clogging * the downlink for Neubot (a background tool), but for OONI we do * actually plan to run the test in the foreground. To re-enable the * old behavior, set the `fast_scale_down` option to non-zero. * * 2. By default, we don't use the vector of fixed rates but rather we * use as rate the speed computed in the previous set. This should * yield a more accurate streaming speed estimate. This different * behavior was suggested to me by Antonio Servetti sometime around * May '17. To re-enable the old behavior, you need to set the * `use_fixed_rates` option to non-zero. * * 3. As pointed out also by a comment in the code, our measurement of * the download speed starts when we send the request rather when we * receive the first byte of the response. I think this is not bad, * since it actually captures better the time to fetch the chunk that * one should play, as opposed to accurately estimating the speed. * * 4. We leave to zero the `delta_user_time` and `delta_sys_time`. We * may change this in the future, when we understand how to get them * portably. They were not so important for us anyway. * * 5. As pointed out also by a comment in the code, we don't consider * the overhead of protocols when computing the speed. As for point * three above, this allows to write a simpler implementation than * the one in Neubot and, as a byproduct, provides us with information * closer to know how much time it takes to get a playable chunk * than just measuring the raw speed (I think, when I wrote the test * for Neubot, I had too much bias towards measuring speed). * * 6. As pointed out by a comment in the code, when we don't use a fixed * vector or rates, the initial speed estimate is 3,000 kbit/s. This * initial value was chosen because Netflix recommends to have at least * that bandwidth to stream in SD quality. (Bandwidth is, of course, * different from the bitrate, but a number close to 3,000 kbit/s * seems anyway to be a reasonable starting point.) */ #include "private/common/json.hpp" #include "private/common/mock.hpp" #include "private/common/utils.hpp" #include #include #include #include #define DASH_INITIAL_RATE 3000 #define DASH_MAX_ITERATIONS 15 #define DASH_SECONDS 2 #define MAX_NEGOTIATIONS 512 namespace mk { namespace neubot { namespace dash { const std::vector &dash_rates(); // Implemented in dash.cpp static inline size_t select_lower_rate_index(int speed_kbit) { size_t rate_index = 0; while (dash_rates()[rate_index] < speed_kbit && rate_index < dash_rates().size()) { rate_index++; } if (rate_index > 0) { // Make sure we don't underflow rate_index -= 1; } assert(rate_index < dash_rates().size()); return rate_index; } class DashLoopCtx { public: std::string auth_token; Callback cb; int speed_kbit = -1; // Means: determine best initial value Var entry; int iteration = 1; Var logger; Var reactor; std::string real_address; Settings settings; Var txp; std::string uuid; }; template void run_loop_(Var ctx) { // TODO: We may want to move this parsing of options in the setup // phase of the test and store them inside `ctx`. ErrorOr fast_scale_down = ctx->settings.get_noexcept("fast_scale_down", false); if (!fast_scale_down) { ctx->logger->warn("dash: cannot parse `fast_scale_down' option"); ctx->cb(fast_scale_down.as_error()); return; } ErrorOr constant_bitrate = ctx->settings.get_noexcept("constant_bitrate", 0); if (!constant_bitrate || *constant_bitrate < 0) { ctx->logger->warn("dash: cannot parse `constant_bitrate' option"); ctx->cb(ValueError()); return; } ErrorOr use_fixed_rates = ctx->settings.get_noexcept("use_fixed_rates", false); if (!use_fixed_rates) { ctx->logger->warn("dash: cannot parse `use_fixed_rates' option"); ctx->cb(use_fixed_rates.as_error()); return; } ErrorOr elapsed_target = ctx->settings.get_noexcept("elapsed_target", DASH_SECONDS); if (!elapsed_target || *elapsed_target < 0) { ctx->logger->warn("dash: cannot parse `elapsed_target' option"); ctx->cb(ValueError()); return; } ErrorOr max_iterations = ctx->settings.get_noexcept("max_iteration", DASH_MAX_ITERATIONS); if (!max_iterations || *max_iterations < 0) { ctx->logger->warn("dash: cannot parse `max_iteration' option"); ctx->cb(ValueError()); return; } ErrorOr initial_rate = ctx->settings.get_noexcept("initial_rate", DASH_INITIAL_RATE); if (!initial_rate || *initial_rate < 0) { ctx->logger->warn("dash: cannot parse `initial_rate' option"); ctx->cb(ValueError()); return; } if (ctx->iteration > *max_iterations) { ctx->logger->debug("dash: completed all iterations"); try { std::vector rates; std::vector stalls; double frame_ready_time = 0.0; double play_time = 0.0; double connect_latency = 0.0; for (auto &e : (*ctx->entry)["receiver_data"]) { if (connect_latency == 0.0) { // It is always equal for all the records connect_latency = e["connect_time"]; } rates.push_back(e["rate"]); /* The first chunk is played when it arrives. To have smooth video, we'd like to play each subsequent chunk within `elapsed_target` seconds. So, the player has always something to play and the user sees the video. If a chunk arrives earlier than the play deadline, good because we can request the next chunk also earlier. That is, we increase buffer time for slow delivery. On the contrary, if a chunk arrives later than the play deadline, we need to stop playing. The max(stalls) is the delay we would have needed to add at the beginning to make sure we had no player stalls. */ double elapsed = e["elapsed"]; frame_ready_time += elapsed; double elapsed_target = e["elapsed_target"]; // Note: this says that the play time of the first frame is // when we receive it. Subsequent frames must be played after // `elapsed_target` seconds each to have smooth video. play_time += (play_time == 0) ? frame_ready_time : elapsed_target; double stall = frame_ready_time - play_time; stalls.push_back(stall); } (*ctx->entry)["simple"]["connect_latency"] = connect_latency; (*ctx->entry)["simple"]["median_bitrate"] = mk::median(rates); (*ctx->entry)["simple"]["min_playout_delay"] = (stalls.size() > 0) ? *std::max_element(stalls.begin(), stalls.end()) : 0.0; } catch (...) { ctx->logger->warn("dash: cannot save summary information"); } ctx->cb(NoError()); return; } if (ctx->speed_kbit < 0) { // Determine initial speed estimate. In legacy mode (i.e. when we use // a fixed vector of rates), we use the first entry. Otherwise, we use // as initial speed estimate 3000 kbit/s. This number is the minimum // speed recommended by Netflix to stream in SD quality, as of 13 July // 2017. I though this would be a good starting point. // // See: . ctx->speed_kbit = (*use_fixed_rates == true) ? dash_rates()[0] : *initial_rate; } /* * Select the rate that is lower than the latest measured speed and * compute the number of bytes to download such that downloading with * the selected rate takes `elapsed_target` (in theory). */ int rate_kbit = (*use_fixed_rates == true) ? dash_rates()[select_lower_rate_index(ctx->speed_kbit)] : (*constant_bitrate > 0) ? *constant_bitrate : ctx->speed_kbit; int count = ((rate_kbit * 1000) / 8) * (*elapsed_target); std::string path = "/dash/download/"; path += std::to_string(count); Settings settings = ctx->settings; /* Make a local copy */ settings["http/path"] = path; settings["http/method"] = "GET"; ctx->logger->debug("dash: requesting '%s'", path.c_str()); /* * Note: our accounting of time also includes the time to send the * request to the server (approximately one RTT). * * This is different from the original implementation of DASH that * is part of Neubot. */ double saved_time = mk::time_now(); http_request_send( ctx->txp, settings, { {"Authorization", ctx->auth_token}, }, "", [=](Error error, Var req) { if (error) { ctx->logger->warn("dash: request failed: %s", error.explain().c_str()); ctx->cb(error); return; } assert(!!req); http_request_recv_response( ctx->txp, [=](Error error, Var res) { if (error) { ctx->logger->warn( "dash: cannot receive response: %s", error.explain().c_str()); ctx->cb(error); return; } assert(!!res); if (res->status_code != 200) { ctx->logger->warn("dash: invalid response code: %s", error.explain().c_str()); ctx->cb(http::HttpRequestFailedError()); return; } res->request = req; auto length = res->body.length(); double time_elapsed = mk::time_now() - saved_time; if (time_elapsed <= 0) { // For robustness ctx->logger->warn("dash: negative time error"); ctx->cb(GenericError("negative_time_error")); return; } (*ctx->entry)["receiver_data"].push_back(report::Entry{ {"connect_time", ctx->txp->connect_time()}, {"constant_bitrate", *constant_bitrate != 0}, {"delta_user_time", 0.0}, {"delta_sys_time", 0.0}, {"elapsed", time_elapsed}, {"elapsed_target", *elapsed_target}, {"engine_name", "libmeasurement_kit"}, {"engine_version", MK_VERSION}, {"fast_scale_down", *fast_scale_down}, {"internal_address", ctx->txp->sockname().hostname}, {"iteration", ctx->iteration}, {"platform", mk_platform()}, {"rate", rate_kbit}, {"real_address", ctx->real_address}, /* * Note: here we're only concerned with the amount * of useful data we received (we ignore overhead) * * This is different from the original * implementation of DASH that is part of Neubot. */ {"received", length}, {"remote_address", ctx->txp->peername().hostname}, {"request_ticks", saved_time}, {"timestamp", llround(saved_time)}, {"use_fixed_rates", *use_fixed_rates}, {"uuid", ctx->uuid}, /* * This version indicates measurement-kit. */ {"version", "0.007000000"}}); double speed = length / time_elapsed; double s_k = (speed * 8) / 1000; std::stringstream ss; ss << "rate: " << rate_kbit << " kbit/s, speed: " << std::fixed << std::setprecision(2) << s_k << " kbit/s, elapsed: " << time_elapsed << " s"; ctx->logger->progress(ctx->iteration / (double)*max_iterations, ss.str().c_str()); if (*fast_scale_down == true && time_elapsed > *elapsed_target) { // If the rate is too high, scale it down double relerr = 1 - (time_elapsed / *elapsed_target); s_k *= relerr; if (s_k <= 0) { s_k = dash_rates()[0]; } } ctx->speed_kbit = s_k; ctx->iteration += 1; run_loop_(ctx); }, ctx->reactor, ctx->logger); }); } template void run_impl(std::string url, std::string auth_token, std::string real_address, Var entry, Settings settings, Var reactor, Var logger, Callback cb) { Var ctx = Var::make(); ctx->auth_token = auth_token; ctx->entry = entry; ctx->logger = logger; ctx->reactor = reactor; ctx->real_address = real_address; ctx->settings = settings; /* * From the Neubot point of view, it is for sure very very useful to save * and reuse the same UUID4. We can attempt to do that by asking the caller * to pass us the unique identifier to be used for this client. */ if (ctx->settings.find("uuid") == ctx->settings.end()) { ctx->logger->warn("You passed me no UUID, generating a random one"); ctx->uuid = mk::sole::uuid4().str(); } else { ctx->uuid = ctx->settings.at("uuid"); } settings["http/url"] = url; settings["http/method"] = "GET"; logger->info("Start dash test with: %s", url.c_str()); http_request_connect( settings, [=](Error error, Var txp) { if (error) { logger->warn("dash: cannot connect to server: %s", error.explain().c_str()); cb(error); return; } // Note: from now on, we own `txp` assert(!!txp); logger->info("Connected to server (3WHS RTT = %f s); starting " "the test", txp->connect_time()); ctx->txp = txp; ctx->cb = [=](Error error) { // Release the `txp` before continuing logger->info("Test complete; closing connection"); txp->close([=]() { cb(error); }); }; run_loop_(ctx); }, reactor, logger); } /* * TODO: this code currently is specifically tailored to the DASH test and * we should instead make it more general and able to work with all the tests * implemented by Neubot (probably using a Continuation). */ template void negotiate_loop_(Var entry, Var txp, Settings settings, Var reactor, Var logger, Callback callback, int iteration = 0, std::string auth_token = "") { report::Entry value = {{"dash_rates", dash_rates()}}; std::string body = value.dump(); settings["http/path"] = "/negotiate/dash"; settings["http/method"] = "POST"; if (iteration > MAX_NEGOTIATIONS) { logger->warn("neubot: too many negotiations"); callback(GenericError("too_many_negotiations"), "", ""); return; } http_request_sendrecv( txp, settings, { {"Content-Type", "application/json"}, {"Authorization", auth_token}, }, body, [=](Error error, Var res) { if (error) { logger->warn("neubot: negotiate failed: %s", error.explain().c_str()); callback(error, "", ""); return; } assert(!!res); if (res->status_code != 200) { logger->warn("neubot: negotiate failed on server side"); callback(http::HttpRequestFailedError(), "", ""); return; } std::string auth; int queue_pos = 0; std::string real_address; int unchoked = 0; error = json_parse_process_and_filter_errors( res->body, [&](nlohmann::json &respbody) { auth = respbody.at("authorization"); queue_pos = respbody.at("queue_pos"); real_address = respbody.at("real_address"); unchoked = respbody.at("unchoked"); }); if (error) { logger->warn("neubot: cannot parse negotiate response: %s", error.as_ooni_error().c_str()); callback(error, "", ""); return; } logger->debug("negotiation: unchoked=%d queue_pos=%d", unchoked, queue_pos); if (!unchoked) { negotiate_loop_(entry, txp, settings, reactor, logger, callback, iteration + 1, auth); return; } callback(NoError(), auth, real_address); }, reactor, logger); } template void collect_(Var txp, Var entry, std::string auth, Settings settings, Var reactor, Var logger, Callback cb) { std::string body = (*entry)["receiver_data"].dump(); logger->debug("Body sent to server: %s", body.c_str()); settings["http/method"] = "POST"; settings["http/path"] = "/collect/dash"; http_request_sendrecv( txp, settings, { {"Content-Type", "application/json"}, {"Authorization", auth}, }, body, [=](Error error, Var res) { if (error) { logger->warn("neubot: collect failed: %s", error.as_ooni_error().c_str()); cb(error); return; } assert(!!res); if (res->status_code != 200) { cb(http::HttpRequestFailedError()); return; } logger->debug("Response received from server: %s", res->body.c_str()); error = json_parse_process_and_filter_errors( res->body, [&](nlohmann::json &json) { (*entry)["sender_data"] = json; }); cb(error); }, reactor, logger); } template void negotiate_with_(std::string hostname, Var entry, Settings settings, Var reactor, Var logger, Callback cb) { logger->info("Negotiating with: %s", hostname.c_str()); std::stringstream ss; ss << "http://" << hostname << "/"; std::string url = ss.str(); settings["http/url"] = url; http_request_connect( settings, [=](Error error, Var txp) { if (error) { // Note: in this case we don't need to close the transport // because we get passed a dumb transport on error logger->warn("neubot: cannot connect to negotiate server: %s", error.explain().c_str()); cb(error); return; } // Note: from now on, we own the `txp` transport assert(!!txp); negotiate_loop_( entry, txp, settings, reactor, logger, [=](Error error, std::string auth_token, std::string real_address) { if (error) { logger->warn("neubot: negotiate failed: %s", error.explain().c_str()); txp->close([=]() { cb(error); }); return; } // TODO: generalize code, allow to run more tests run_impl(url, auth_token, real_address, entry, settings, reactor, logger, [=](Error error) { if (error) { logger->warn("neubot: test failed: %s", error.explain().c_str()); /* FALLTHROUGH */ } logger->info("Collecting results"); collect_( txp, entry, auth_token, settings, reactor, logger, [=](Error error) { // Dispose of the `txp` txp->close([=]() { cb(error); }); }); }); }); }, reactor, logger); } template void negotiate_impl(Var entry, Settings settings, Var reactor, Var logger, Callback cb) { if (settings.find("hostname") != settings.end()) { negotiate_with_(settings["hostname"], entry, settings, reactor, logger, cb); return; } logger->info("Discovering mlab server using mlabns"); mlabns_query("neubot", [=](Error error, mlabns::Reply reply) { if (error) { logger->warn("neubot: mlabns error: %s", error.explain().c_str()); cb(error); return; } negotiate_with_(reply.fqdn, entry, settings, reactor, logger, cb); }, settings, reactor, logger); } } // namespace dash } // namespace neubot } // namespace mk #endif measurement-kit-0.7.1/include/private/ooni/000077500000000000000000000000001315356162600207025ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/ooni/bouncer_impl.hpp000066400000000000000000000072071315356162600240770ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_OONI_BOUNCER_IMPL_HPP #define PRIVATE_OONI_BOUNCER_IMPL_HPP #include "private/common/json.hpp" #include "private/common/mock.hpp" #include "private/common/json.hpp" #include "private/common/mock.hpp" #include namespace mk { namespace ooni { namespace bouncer { static Error my_json_parse_process_and_filter_errors(const std::string &data, Callback callable) { return json_parse_process_and_filter_errors(data, callable); } template ErrorOr> create_impl(std::string data, Var logger) { Var reply{new BouncerReply}; Error err = my_json_parse_process_and_filter_errors(data, [&](auto j) { reply->response = j; if (reply->response.find("error") != reply->response.end()) { if (reply->response["error"] == "collector-not-found") { throw BouncerCollectorNotFoundError(); } if (reply->response["error"] == "invalid-request") { throw BouncerInvalidRequestError(); } // I assume that if we receive a json with the key "error" // then the json has an unknown schema and we should not // continue to process it throw BouncerGenericError(); } if (reply->response["net-tests"].empty()) { throw BouncerTestHelperNotFoundError(); } }); if (err) { logger->warn("bouncer parsing error: %s", err.explain().c_str()); return err; } return reply; } template void post_net_tests_impl(std::string base_bouncer_url, std::string test_name, std::string test_version, std::list helpers, Callback> cb, Settings settings, Var reactor, Var logger) { nlohmann::json request; nlohmann::json net_tests; net_tests["input-hashes"] = {}; net_tests["name"] = test_name; net_tests["test-helpers"] = helpers; net_tests["version"] = test_version; request["net-tests"][0] = net_tests; std::string bbu = base_bouncer_url + "/bouncer/net-tests"; std::string bm = "POST"; settings["http/url"] = bbu; settings["http/method"] = bm; logger->debug("%sing to '%s' data '%s'", bm.c_str(), bbu.c_str(), request.dump().c_str()); http_request(settings, {{"Content-Type", "application/json"}}, request.dump(), [=](Error error, Var resp) { if (error) { logger->warn("Bouncer error: %s", error.explain().c_str()); cb(error, nullptr); return; } logger->debug("Bouncer reply: %s", resp->body.c_str()); ErrorOr> reply( BouncerReply::create(resp->body, logger)); if (!reply) { cb(reply.as_error(), nullptr); return; } cb(NoError(), *reply); }, reactor, logger, nullptr, 0); } } // namespace bouncer } // namespace ooni } // namespace mk #endif measurement-kit-0.7.1/include/private/ooni/collector_client_impl.hpp000066400000000000000000000357211315356162600257700ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_OONI_COLLECTOR_CLIENT_IMPL_HPP #define PRIVATE_OONI_COLLECTOR_CLIENT_IMPL_HPP // This file implements the OONI collector client protocol // See #include "private/common/json.hpp" #include "private/common/mock.hpp" #include #include #include namespace mk { namespace ooni { namespace collector { using namespace mk::http; using namespace mk::net; using namespace mk::report; /* _ _ | |__ ___| |_ __ ___ _ __ ___ | '_ \ / _ \ | '_ \ / _ \ '__/ __| | | | | __/ | |_) | __/ | \__ \ |_| |_|\___|_| .__/ \___|_| |___/ |_| */ void post(Var transport, std::string url_extra, std::string body, Callback callback, Settings conf = {}, Var = Reactor::global(), Var = Logger::global()); template void post_impl(Var transport, std::string append_to_url, std::string body, Callback callback, Settings settings, Var reactor, Var logger) { std::string url = ""; Headers headers; if (settings.find("collector_base_url") == settings.end()) { callback(MissingCollectorBaseUrlError(), nullptr); return; } if (settings.find("collector_front_domain") != settings.end()) { mk::http::Url base_url = mk::http::parse_url(settings["collector_base_url"]); url = "https://"; url += settings["collector_front_domain"]; url += base_url.path; // XXX should we do more? headers["Host"] = base_url.address; // XXX this is confusing that it's called address } else { url = settings["collector_base_url"]; } url += append_to_url; settings["http/url"] = url; settings["http/method"] = "POST"; if (body != "") { headers["Content-Type"] = "application/json"; } logger->debug("POST %s '%s'...", url.c_str(), body.c_str()); http_request_sendrecv(transport, settings, headers, body, [=](Error err, Var response) { logger->debug("POST %s '%s'... %d", url.c_str(), body.c_str(), err.code); if (err) { callback(err, nullptr); return; } logger->debug("Response status code: %d", response->status_code); logger->debug("Response reason: %s", response->reason.c_str()); if (response->status_code / 100 != 2) { callback(HttpRequestFailedError(), nullptr); return; } // If response is empty, don't parse it if (response->body == "") { callback(NoError(), nullptr); return; } nlohmann::json reply; try { reply = nlohmann::json::parse(response->body); } catch (const std::invalid_argument &) { callback(JsonParseError(), nullptr); return; } callback(NoError(), reply); }, reactor, logger); } Error valid_entry(Entry entry); /* _ __ _ _ __ (_) / _` | '_ \| | | (_| | |_) | | \__,_| .__/|_| |_| */ template void connect_impl(Settings settings, Callback> callback, Var reactor, Var logger) { std::string url; if (settings.find("collector_base_url") == settings.end()) { callback(MissingCollectorBaseUrlError(), nullptr); return; } if (settings.find("collector_front_domain") != settings.end()) { mk::http::Url base_url = mk::http::parse_url(settings["collector_base_url"]); url = "https://"; url += settings["collector_front_domain"]; url += base_url.path; } else { url = settings["collector_base_url"]; } settings["http/url"] = url; http_request_connect(settings, callback, reactor, logger); } template void create_report_impl(Var transport, Entry entry, Callback callback, Settings settings, Var reactor, Var logger) { Entry request; Error err = valid_entry(entry); if (err != NoError()) { callback(err, ""); return; } request["software_name"] = entry["software_name"]; request["software_version"] = entry["software_version"]; request["probe_asn"] = entry["probe_asn"]; request["probe_cc"] = entry["probe_cc"]; request["test_name"] = entry["test_name"]; request["test_version"] = entry["test_version"]; request["test_start_time"] = entry["test_start_time"]; if (entry["input_hashes"] != nullptr) { request["input_hashes"] = entry["input_hashes"]; } else { request["input_hashes"] = Entry::array(); } request["data_format_version"] = entry["data_format_version"]; request["format"] = "json"; std::string body = request.dump(); collector_post(transport, "/report", body, [=](Error err, nlohmann::json reply) { if (err) { callback(err, ""); return; } std::string report_id; try { report_id = reply.at("report_id"); } catch (const std::domain_error &) { callback(JsonDomainError(), ""); return; } catch (const std::out_of_range &) { callback(JsonKeyError(), ""); return; } callback(NoError(), report_id); }, settings, reactor, logger); } template void connect_and_create_report_impl(report::Entry entry, Callback callback, Settings settings, Var reactor, Var logger) { collector_connect(settings, [=](Error error, Var txp) { if (error) { callback(error, ""); return; } collector_create_report(txp, entry, [=](Error error, std::string rid) { txp->close([=]() { callback(error, rid); }); }, settings, reactor, logger); }, reactor, logger); } template void update_report_impl(Var transport, std::string report_id, Entry entry, Callback callback, Settings settings, Var reactor, Var logger) { /* * If needed, overwrite the `report_id` field with what was * passed us by the server, which should be authoritative. * * Note that `entry` is passed by copy so changing it has no * effect outside of this function. * * This action must be performed in addition to `valid_entry()` * because that function does not check for report_id. * * We warn if `report_id` is not present because higher layers * should already have set the report-id's value. */ if (entry["report_id"] == nullptr) { logger->warn("collector: forcing report_id which was not set"); entry["report_id"] = report_id; } Error err = valid_entry(entry); if (err != NoError()) { callback(err); return; } Entry request{{"format", "json"}}; request["content"] = entry; std::string body = request.dump(); collector_post(transport, "/report/" + report_id, body, [=](Error err, nlohmann::json) { callback(err); }, settings, reactor, logger); } template void connect_and_update_report_impl(std::string report_id, report::Entry entry, Callback callback, Settings settings, Var reactor, Var logger) { collector_connect(settings, [=](Error error, Var txp) { if (error) { callback(error); return; } collector_update_report(txp, report_id, entry, [=](Error error) { txp->close([=]() { callback(error); }); }, settings, reactor, logger); }, reactor, logger); } template void close_report_impl(Var transport, std::string report_id, Callback callback, Settings settings, Var reactor, Var logger) { collector_post(transport, "/report/" + report_id + "/close", "", [=](Error err, nlohmann::json) { callback(err); }, settings, reactor, logger); } template void connect_and_close_report_impl(std::string report_id, Callback callback, Settings settings, Var reactor, Var logger) { collector_connect(settings, [=](Error error, Var txp) { if (error) { callback(error); return; } collector_close_report(txp, report_id, [=](Error error) { txp->close([=]() { callback(error); }); }, settings, reactor, logger); }, reactor, logger); } ErrorOr get_next_entry(Var file, Var logger); template void update_and_fetch_next_impl(Var file, Var txp, std::string report_id, int line, Entry entry, Callback callback, Settings settings, Var reactor, Var logger) { logger->info("adding entry report #%d...", line); collector_update_report( txp, report_id, entry, [=](Error err) { logger->info("adding entry report #%d... %d", line, err.code); if (err) { txp->close([=]() { callback(err); }); return; } // After #644 bug and fix, I prefer to always break explicit // recursion by using the call_soon() pattern logger->debug("scheduling read of next entry..."); reactor->call_soon([=]() { logger->debug("reading next entry"); ErrorOr entry = collector_get_next_entry(file, logger); if (!entry) { if (entry.as_error() != FileEofError()) { txp->close([=]() { callback(entry.as_error()); }); return; } close_report( txp, report_id, [=](Error err) { txp->close([=]() { callback(err); }); }, settings, reactor, logger); return; } update_and_fetch_next_impl( file, txp, report_id, line + 1, *entry, callback, settings, reactor, logger); }); }, settings, reactor, logger); } template void submit_report_impl(std::string filepath, std::string collector_base_url, std::string collector_front_domain, Callback callback, Settings settings, Var reactor, Var logger) { Var file(new std::ifstream(filepath)); if (!file->good()) { callback(CannotOpenReportError()); return; } ErrorOr entry = collector_get_next_entry(file, logger); if (!entry) { callback(entry.as_error()); return; } settings["collector_base_url"] = collector_base_url; if (collector_front_domain != "") { settings["collector_front_domain"] = collector_front_domain; } logger->info("connecting to collector %s...", collector_base_url.c_str()); collector_connect( settings, [=](Error err, Var txp) { logger->info("connecting to collector %s... %d", collector_base_url.c_str(), err.code); if (err) { callback(err); return; } logger->info("creating report..."); collector_create_report( txp, *entry, [=](Error err, std::string report_id) { logger->info("creating report... %d", err.code); if (err) { txp->close([=]() { callback(err); }); return; } update_and_fetch_next_impl(file, txp, report_id, 1, *entry, callback, settings, reactor, logger); }, settings, reactor, logger); }, reactor, logger); } } // namespace collector } // namespace mk } // namespace ooni #endif measurement-kit-0.7.1/include/private/ooni/constants.hpp000066400000000000000000000046261315356162600234370ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_OONI_CONSTANTS_HPP #define PRIVATE_OONI_CONSTANTS_HPP #include #include namespace mk { namespace ooni { namespace constants { // These are very common server headers that we don't consider when checking // between control and experiment. const std::set COMMON_SERVER_HEADERS = { "date", "content-type", "server", "cache-control", "vary", "set-cookie", "location", "expires", "x-powered-by", "content-encoding", "last-modified", "accept-ranges", "pragma", "x-frame-options", "etag", "x-content-type-options", "age", "via", "p3p", "x-xss-protection", "content-language", "cf-ray", "strict-transport-security", "link", "x-varnish" }; const http::Headers COMMON_CLIENT_HEADERS = { { "User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36" }, { "Accept-Language", "en-US;q=0.8,en;q=0.5" }, { "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" } }; const std::string MEEK_SERVER_RESPONSE = "I\xe2\x80\x99m just a happy little web server.\n"; static std::vector COMMON_USER_AGENTS = { "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7", "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3 1 2 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Mobile/7D11", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2) Gecko/20100115 Firefox/3.6", "Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.2) Gecko/20100115 Firefox/3.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2) Gecko/20100115 Firefox/3.6", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7", "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729))", }; } // namespace constants } // namespace ooni } // namespace mk #endif measurement-kit-0.7.1/include/private/ooni/http_header_field_manipulation.hpp000066400000000000000000000011111315356162600276170ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_HTTP_HEADER_FIELD_MANIPULATION_HPP #define PRIVATE_HTTP_HEADER_FIELD_MANIPULATION_HPP #include namespace mk { namespace ooni { void compare_headers_response(http::Headers headers, Var response, Var entry, Var logger); } // namespace ooni } // namespace mk #endif measurement-kit-0.7.1/include/private/ooni/orchestrate_impl.hpp000066400000000000000000000400151315356162600247570ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_OONI_ORCHESTRATE_IMPL_HPP #define PRIVATE_OONI_ORCHESTRATE_IMPL_HPP #include "private/common/async_runner.hpp" #include "private/common/fcompose.hpp" #include "private/common/json.hpp" #include "private/common/mock.hpp" #include "private/common/async_runner.hpp" #include "private/common/fcompose.hpp" #include "private/common/json.hpp" #include "private/common/mock.hpp" #include #include "../common/utils.hpp" #include "../ooni/utils.hpp" namespace mk { namespace ooni { namespace orchestrate { template void login(Auth &&auth, std::string registry_url, Settings settings, Var reactor, Var logger, Callback &&cb) { if (auth.username.empty() || auth.password.empty()) { logger->warn("orchestrator: missing username or password"); cb(MissingRequiredValueError(), std::move(auth)); return; }; nlohmann::json request{{"username", auth.username}, {"password", auth.password}}; logger->info("Logging you in with orchestrator"); logger->debug("orchestrator: sending login request: %s", request.dump().c_str()); /* * Important: do not pass `this` to the lambda closure. Rather make * sure everything we pass can be kept safe by the closure. */ http_request_json_object( "POST", registry_url + "/api/v1/login", request, {}, [ auth = std::move(auth), cb = std::move(cb), logger ](Error error, Var /*http_response*/, nlohmann::json json_response) mutable { if (error) { logger->warn("orchestrator: JSON API error: %s", error.explain().c_str()); cb(std::move(error), std::move(auth)); return; } logger->debug("orchestrator: processing login response"); error = json_process_and_filter_errors( json_response, [&](auto response) { if (response.find("error") != response.end()) { if (response["error"] == "wrong-username-password") { throw RegistryWrongUsernamePasswordError(); } if (response["error"] == "missing-username-password") { throw RegistryMissingUsernamePasswordError(); } // Note: this is basically an error case that we did // not anticipate when writing the code throw GenericError(); } auth.expiry_time = response["expire"]; auth.auth_token = response["token"]; auth.logged_in = true; logger->info("Logged in with orchestrator"); }); if (error) { logger->warn("orchestrator: json processing error: %s", error.explain().c_str()); } cb(std::move(error), std::move(auth)); }, settings, reactor, logger); } template void maybe_login(Auth &&auth, std::string registry_url, Settings settings, Var reactor, Var logger, Callback &&cb) { if (auth.is_valid(logger)) { logger->info("Auth token is valid, no need to login"); cb(NoError(), std::move(auth)); return; } login(std::move(auth), registry_url, settings, reactor, logger, std::move(cb)); } template void register_probe_(const ClientMetadata &m, std::string password, Var reactor, Callback &&cb) { Auth auth; auth.password = password; if (m.probe_cc.empty() || m.probe_asn.empty() || m.platform.empty() || m.software_name.empty() || m.software_version.empty() || m.supported_tests.empty()) { m.logger->warn("orchestrator: missing required value"); cb(MissingRequiredValueError(), std::move(auth)); return; } if ((m.platform == "ios" || m.platform == "android") && m.device_token.empty()) { m.logger->warn("orchestrator: you passed me an empty device token"); cb(MissingRequiredValueError(), std::move(auth)); return; } nlohmann::json request = m.as_json(); request["password"] = password; http_request_json_object( "POST", m.registry_url + "/api/v1/register", request, {}, [ cb = std::move(cb), logger = m.logger, auth = std::move(auth) ](Error error, Var /*resp*/, nlohmann::json json_response) mutable { if (error) { logger->warn("orchestrator: JSON API error: %s", error.as_ooni_error().c_str()); cb(std::move(error), std::move(auth)); return; } error = json_process_and_filter_errors( json_response, [&](auto jresp) { if (jresp.find("error") != jresp.end()) { if (jresp["error"] == "invalid request") { throw RegistryInvalidRequestError(); } // A case that we have not anticipated throw GenericError(); } auth.username = jresp["client_id"]; if (auth.username == "") { throw RegistryEmptyClientIdError(); } }); if (error) { logger->warn("orchestrator: JSON processing error: %s", error.explain().c_str()); } else { logger->info("Registered probe with orchestrator as: '%s'", auth.username.c_str()); } cb(std::move(error), std::move(auth)); }, m.settings, reactor, m.logger); } template void update_(const ClientMetadata &m, Auth &&auth, Var reactor, Callback &&cb) { std::string update_url = m.registry_url + "/api/v1/update/" + auth.username; nlohmann::json update_request = m.as_json(); maybe_login( std::move(auth), m.registry_url, m.settings, reactor, m.logger, [ update_url = std::move(update_url), update_request = std::move(update_request), cb = std::move(cb), settings = m.settings, reactor, logger = m.logger ](Error && err, Auth && auth) { if (err != NoError()) { // Note: error printed by maybe_login() cb(std::move(err), std::move(auth)); return; } // With GCC move inside lambda happens before setting headers, so // use a copy of the auth token to make sure we do not fail std::string auth_token = auth.auth_token; http_request_json_object( "PUT", update_url, update_request, {{"Authorization", "Bearer " + auth_token}}, [ cb = std::move(cb), logger, auth = std::move(auth) ]( Error err, Var /*resp*/, nlohmann::json json_response) mutable { if (err) { // Note: error printed by maybe_login() cb(std::move(err), std::move(auth)); return; } err = json_process_and_filter_errors( json_response, [&](auto jresp) { // XXX add better error handling if (jresp.find("error") != jresp.end()) { std::string s = jresp["error"]; logger->warn("orchestrator: update " "failed with \"%s\"", s.c_str()); throw RegistryInvalidRequestError(); } if (jresp.find("status") == jresp.end() || jresp["status"] != "ok") { throw RegistryInvalidRequestError(); } }); if (!err) { logger->info("Updated orchestrator about " "this probe state"); } cb(std::move(err), std::move(auth)); }, settings, reactor, logger); }); } template void do_find_location(const ClientMetadata &m, Var reactor, Callback &&cb) { ooni_ip_lookup( [ logger = m.logger, geoip_asn_path = m.geoip_asn_path, geoip_country_path = m.geoip_country_path, cb = std::move(cb) ](Error error, std::string ip) mutable { if (error) { cb(std::move(error), "", ""); return; } logger->debug("Probe IP is: %s", ip.c_str()); auto query_geoip = [&](const std::string &path, std::string &dest, const std::string &fallback, auto callable) { // Using local database to avoid thread safety issues ooni::GeoipDatabase db{path}; ErrorOr x = callable(db, ip, logger); if (!x) { logger->warn("geoip failed for '%s': %s", ip.c_str(), x.as_error().as_ooni_error().c_str()); dest = fallback; return; } logger->debug("IP %s maps to %s", ip.c_str(), x->c_str()); dest = *x; }; std::string probe_asn; std::string probe_cc; query_geoip(geoip_asn_path, probe_asn, "AS0", [](auto db, auto ip, auto logger) { return db.resolve_asn(ip, logger); }); query_geoip(geoip_country_path, probe_cc, "ZZ", [](auto db, auto ip, auto logger) { return db.resolve_country_code(ip, logger); }); cb(NoError(), std::move(probe_asn), std::move(probe_cc)); }, m.settings, reactor, m.logger); } class RegistryCtx { public: Auth auth; Var logger; ClientMetadata metadata; Var reactor; }; static inline void ctx_enter_(Auth &&auth, ClientMetadata &&meta, Var reactor, Callback> &&cb) { auto ctx = Var::make(); ctx->auth = std::move(auth); ctx->metadata = std::move(meta); ctx->reactor = reactor; ctx->logger = ctx->metadata.logger; cb(ctx); } template void ctx_register_(Error &&error, Var ctx, Callback> &&cb) { if (error) { cb(std::move(error), ctx); return; } auto p = ctx->auth.password.empty() ? Auth::make_password() : ctx->auth.password; ctx->logger->info("Registering this probe with the orchestrator registry"); register_probe_( ctx->metadata, p, ctx->reactor, [ cb = std::move(cb), ctx ](Error && err, Auth && auth) { ctx->auth = std::move(auth); cb(std::move(err), ctx); }); } template void ctx_retrieve_missing_meta_(Var ctx, Callback> &&cb) { if (ctx->metadata.platform == "") { ctx->metadata.platform = mk_platform(); } if (ctx->metadata.supported_tests.empty()) { ctx->metadata.supported_tests = {{"dns_injection"}, {"http_header_field_manipulation"}, {"http_invalid_request_line"}, {"meek_fronted_requests"}, {"ndt"}, {"tcp_connect"}, {"web_connectivity"}}; } if (ctx->metadata.probe_asn != "" && ctx->metadata.probe_cc != "") { ctx->logger->debug("No need to guess ASN and/or CC"); cb(NoError(), ctx); return; } ctx->logger->info("Looking up probe IP to guess ASN and/or CC"); do_find_location(ctx->metadata, ctx->reactor, [ cb = std::move(cb), ctx ](Error && error, std::string && asn, std::string && cc) mutable { ctx->metadata.probe_asn = std::move(asn); ctx->metadata.probe_cc = std::move(cc); cb(std::move(error), ctx); }); } template void ctx_update_(Error &&error, Var ctx, Callback> &&cb) { if (error) { cb(std::move(error), ctx); return; } update_( ctx->metadata, std::move(ctx->auth), ctx->reactor, [ cb = std::move(cb), ctx ](Error && error, Auth && auth) mutable { ctx->auth = std::move(auth); cb(std::move(error), ctx); }); } static inline void ctx_leave_(Error &&error, Var ctx, Callback &&cb) { cb(std::move(error), std::move(ctx->auth)); } template void do_register_probe(std::string &&password, const ClientMetadata &m, Var reactor, Callback &&cb) { // For uniformity we pass an `Auth` structure to `ctx_enter_` and we // retrieve the password from it in `ctx_register_` Auth auth; auth.password = std::move(password); mk::fcompose(mk::fcompose_policy_async(), ctx_enter_, ctx_retrieve_missing_meta_, ctx_register_, ctx_leave_)(std::move(auth), m, reactor, std::move(cb)); } template void do_update(Auth &&auth, const ClientMetadata &m, Var reactor, Callback &&cb) { mk::fcompose(mk::fcompose_policy_async(), ctx_enter_, ctx_retrieve_missing_meta_, ctx_update_, ctx_leave_)(std::move(auth), m, reactor, std::move(cb)); } } // namespace orchestrate } // namespace ooni } // namespace mk #endif measurement-kit-0.7.1/include/private/ooni/resources_impl.hpp000066400000000000000000000213701315356162600244510ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_OONI_RESOURCES_IMPL_HPP #define PRIVATE_OONI_RESOURCES_IMPL_HPP #include "private/common/mock.hpp" #include "private/common/parallel.hpp" #include "private/common/mock.hpp" #include "private/common/parallel.hpp" #include #include #include #include #include "../common/utils.hpp" namespace mk { namespace ooni { namespace resources { using namespace mk::http; static inline std::string get_base_url(const Settings &settings) { return settings.get( "ooni/resources_base_url", std::string{ "https://github.com/OpenObservatory/ooni-resources/releases/"}); } static inline void set_max_redirects(Settings &settings) { if (settings.find("http/max_redirects") == settings.end()) { // Note: 20 is what is used by web_connectivity and by browsers settings["http/max_redirects"] = 20; } } static inline std::string sanitize_version(const std::string &s) { return std::regex_replace(s, std::regex{R"xx([\ \t\r\n]+)xx"}, ""); } template void get_latest_release_impl(Callback callback, Settings settings, Var reactor, Var logger) { /* * Note: this code does not use GitHub's "latest" release feature because * upon creating a new release that is marked as latest but it does not * contain yet all the files that are part of the release. For this reason * we create a "latest" tag containing a "version" file that we only * update when all the files are uploaded (#robustness). I'm adding this * note here because I was initially confused by how this works. * * - Simone (2016-12-06) */ set_max_redirects(settings); auto url = get_base_url(settings) + "download/latest/version"; logger->info("Downloading latest version; please, be patient..."); http_get(url, [=](Error error, Var response) { if (error) { callback(error, ""); return; } if (response->status_code != 200) { callback(CannotGetResourcesVersionError(), ""); return; } std::string v = sanitize_version(response->body); logger->info("Latest resources version: %s", v.c_str()); callback(NoError(), v); }, {}, settings, reactor, logger, nullptr, 0); } template void get_manifest_as_json_impl( std::string latest, Callback callback, Settings settings, Var reactor, Var logger) { auto url = get_base_url(settings); url += "download/"; url += latest; url += "/manifest.json"; set_max_redirects(settings); logger->info("Downloading manifest; please, be patient..."); http_get(url, [=](Error error, Var response) { nlohmann::json result; if (error) { callback(error, result); return; } if (response->status_code != 200) { callback(CannotGetResourcesManifestError(), result); return; } try { result = nlohmann::json::parse(response->body); } catch (const std::invalid_argument &) { callback(JsonParseError(), result); return; } logger->info("Downloaded manifest"); callback(NoError(), result); }, {}, settings, reactor, logger, nullptr, 0); } static inline bool ostream_bad(const std::ostream &s) { return s.bad(); } static inline std::string sanitize_path(const std::string &s) { return std::regex_replace(s, std::regex{R"xx([/\\]+)xx"}, "."); } template void get_resources_for_country_impl(std::string latest, nlohmann::json manifest, std::string country, Callback cb, Settings settings, Var reactor, Var logger) { if (!manifest.is_object()) { reactor->call_soon([=]() { cb(JsonDomainError()); }); return; } if (manifest.find("resources") == manifest.end()) { reactor->call_soon([=]() { cb(JsonKeyError()); }); return; } set_max_redirects(settings); // TODO: do we need to cross validate latest? std::vector> input; /* * Important: MUST be entry and not &entry because we need a copy! */ for (auto entry : manifest["resources"]) { input.push_back([=](Callback cb) { if (!entry.is_object()) { cb(JsonDomainError()); return; } if (entry.find("country_code") == entry.end()) { cb(JsonKeyError()); return; } std::string cc = entry["country_code"]; if (country != cc and country != "ALL") { cb(NoError()); // Nothing to be done for this entry return; } if (entry.find("path") == entry.end()) { cb(JsonKeyError()); return; } auto url = get_base_url(settings) + "download/"; url += latest; url += "/"; std::string path = sanitize_path(entry["path"]); url += path; http_get(url, [=](Error error, Var response) { if (error) { cb(error); return; } if (response->status_code != 200) { cb(CannotGetResourceError()); return; } logger->info("Downloaded %s", path.c_str()); if (entry.find("sha256") == entry.end()) { cb(JsonKeyError()); return; } if (sha256_of(response->body) != entry["sha256"]) { cb(ResourceIntegrityError()); return; } logger->info("Verified %s", path.c_str()); /* * TODO: When we integrate code to properly manage * filepaths here we will need to make sure that we * are not writing into bad places. */ std::string dir = settings.get( "ooni/resources_destdir", std::string{"."} ); /* * See http://stackoverflow.com/questions/12971499 */ #if (defined _WIN32 || defined __CYGWIN__) dir += R"xx(\)xx"; #else dir += "/"; #endif std::ofstream ofile(dir + path); ofile << response->body; ofile.close(); /* * Note: bad() returns true if I/O fails. */ if (ostream_bad(ofile)) { cb(FileIoError()); return; } logger->info("Written %s", path.c_str()); cb(NoError()); }, {}, settings, reactor, logger, nullptr, 0); }); } logger->info("Downloading resources; please, be patient..."); mk::parallel(input, cb, 4); } template void get_resources_impl(std::string latest, std::string country, Callback callback, Settings settings, Var reactor, Var logger) { get_manifest_as_json(latest, [=](Error error, nlohmann::json manifest) { if (error) { callback(error); return; } get_resources_for_country( latest, manifest, country, callback, settings, reactor, logger); }, settings, reactor, logger); } } // namespace resources } // namespace mk } // namespace ooni #endif measurement-kit-0.7.1/include/private/ooni/utils.hpp000066400000000000000000000062231315356162600225560ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_OONI_UTILS_HPP #define PRIVATE_OONI_UTILS_HPP #include #include #include using json = nlohmann::json; namespace mk { namespace ooni { class GeoipDatabase { public: GeoipDatabase(std::string path) : path(path) {} ErrorOr resolve_country_code(std::string ip, Var = Logger::global()); ErrorOr resolve_country_name(std::string ip, Var = Logger::global()); ErrorOr resolve_city_name(std::string ip, Var = Logger::global()); ErrorOr resolve_asn(std::string ip, Var = Logger::global()); std::string path; private: ErrorOr with_open_database_do(std::function()> action, Var logger); Var db; }; class GeoipCache { public: static Var thread_local_instance(); Var get(std::string path, bool &did_open); Var get(std::string path) { bool did_open = false; return get(path, did_open); } // After you update resources you want to invalidate the cache // such that new databases are loaded on next query void invalidate() { instances.clear(); } ErrorOr resolve_country_code(std::string path, std::string ip, Var logger = Logger::global()) { logger->debug("resolve country code '%s' using '%s'", ip.c_str(), path.c_str()); return get(path)->resolve_country_code(ip, logger); } ErrorOr resolve_country_name(std::string path, std::string ip, Var logger = Logger::global()) { logger->debug("resolve country name '%s' using '%s'", ip.c_str(), path.c_str()); return get(path)->resolve_country_name(ip, logger); } ErrorOr resolve_city_name(std::string path, std::string ip, Var logger = Logger::global()) { logger->debug("resolve city code '%s' using '%s'", ip.c_str(), path.c_str()); return get(path)->resolve_city_name(ip, logger); } ErrorOr resolve_asn(std::string path, std::string ip, Var logger = Logger::global()) { logger->debug("resolve asn '%s' using '%s'", ip.c_str(), path.c_str()); return get(path)->resolve_asn(ip, logger); } // This means we cache up to 3 GeoIP database handles, based on filepath and // expire them in FIFO order. size_t max_size = 3; private: std::map> instances; }; std::string extract_html_title(std::string body); bool is_private_ipv4_addr(const std::string &ipv4_addr); std::string scrub( std::string orig, std::string real_probe_ip ); } // namespace ooni } // namespace mk #endif measurement-kit-0.7.1/include/private/ooni/utils_impl.hpp000066400000000000000000000047641315356162600236070ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef PRIVATE_OONI_UTILS_IMPL_HPP #define PRIVATE_OONI_UTILS_IMPL_HPP #include "private/common/encoding.hpp" #include "private/common/mock.hpp" #include "private/common/encoding.hpp" #include "private/common/mock.hpp" #include "../ooni/utils.hpp" using json = nlohmann::json; namespace mk { namespace ooni { template void ip_lookup_impl(Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()) { http_get("http://geoip.ubuntu.com/lookup", [=](Error err, Var response) { if (err) { callback(err, ""); return; } if (response->status_code != 200) { callback(HttpRequestError(), ""); return; } std::smatch m; std::regex regex("(.*)"); if (std::regex_search(response->body, m, regex) == false) { callback(RegexSearchError(), ""); return; } if (!net::is_ip_addr(m[1])) { callback(ValueError(), ""); return; } callback(NoError(), m[1]); }, {}, settings, reactor, logger, nullptr, 0); } template void resolver_lookup_impl(Callback callback, Settings settings = {}, Var reactor = Reactor::global(), Var logger = Logger::global()) { dns_query("IN", "A", "whoami.akamai.net", [=](Error error, Var message) { if (!error) { for (auto answer : message->answers) { if (answer.ipv4 != "") { logger->debug("ip address of resolver is %s", answer.ipv4.c_str()); callback(NoError(), answer.ipv4); return; } } } else { logger->debug("failed to lookup resolver ip address"); callback(error, ""); return; } }, settings, reactor, logger); } } // namespace ooni } // namespace mk #endif measurement-kit-0.7.1/include/private/portable/000077500000000000000000000000001315356162600215465ustar00rootroot00000000000000measurement-kit-0.7.1/include/private/portable/citrus_adapt.h000066400000000000000000000013401315356162600243770ustar00rootroot00000000000000/* * Public domain. */ #ifndef SRC_LIBMEASUREMENT_KIT_PORTABLE_CITRUS_ADAPT_H #define SRC_LIBMEASUREMENT_KIT_PORTABLE_CITRUS_ADAPT_H #include #ifndef __restrict # define __restrict /* nothing */ #endif /* * Note: this is to edit the names of the symbols such that the compiled * library only contains symbol names starting with `mk_`. */ #define _citrus_utf8_ctype_mbrtowc mk_utf8_mbrtowc #define _citrus_utf8_ctype_mbsinit mk_utf8_mbsinit #define _citrus_utf8_ctype_mbsnrtowcs mk_utf8_mbsnrtowcs #define _citrus_utf8_ctype_wcrtomb mk_utf8_wcrtomb #define _citrus_utf8_ctype_wcsnrtombs mk_utf8_wcsnrtombs #include "../portable/citrus_ctype.h" struct _utf8_state { wchar_t ch; int want; wchar_t lbound; }; #endif measurement-kit-0.7.1/include/private/portable/citrus_ctype.h000066400000000000000000000047051315356162600244420ustar00rootroot00000000000000/* $OpenBSD: citrus_ctype.h,v 1.5 2016/09/05 09:47:02 schwarze Exp $ */ /*- * Copyright (c)2002 Citrus Project, * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #ifndef _CITRUS_CTYPE_H_ #define _CITRUS_CTYPE_H_ #define _CITRUS_UTF8_MB_CUR_MAX 4 #ifdef __cplusplus extern "C" { #endif size_t _citrus_none_ctype_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t); size_t _citrus_none_ctype_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict, size_t, size_t); size_t _citrus_none_ctype_wcrtomb(char * __restrict, wchar_t); size_t _citrus_none_ctype_wcsnrtombs(char * __restrict, const wchar_t ** __restrict, size_t, size_t); size_t _citrus_utf8_ctype_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); int _citrus_utf8_ctype_mbsinit(const mbstate_t * __restrict); size_t _citrus_utf8_ctype_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict, size_t, size_t, mbstate_t * __restrict); size_t _citrus_utf8_ctype_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); size_t _citrus_utf8_ctype_wcsnrtombs(char * __restrict, const wchar_t ** __restrict, size_t, size_t, mbstate_t * __restrict); #ifdef __cplusplus } #endif #endif measurement-kit-0.7.1/m4/000077500000000000000000000000001315356162600151615ustar00rootroot00000000000000measurement-kit-0.7.1/m4/.gitignore000066400000000000000000000000001315356162600171370ustar00rootroot00000000000000measurement-kit-0.7.1/measurement_kit.podspec000066400000000000000000000013401315356162600214120ustar00rootroot00000000000000Pod::Spec.new do |s| s.name = "measurement_kit" s.version = "0.7.1" s.summary = "Portable network measurement library" s.author = "Simone Basso", "Arturo Filastò", "Davide Allavena", "Carmine D'Amico", "Leonid Evdokimov", "Antonio Langiu", "Lorenzo Primiterra", "Alessandro Quaranta" s.homepage = "https://github.com/measurement-kit" s.license = { :type => "BSD" } s.source = { :git => "https://github.com/measurement-kit/measurement-kit.git", :tag => "v#{s.version}" } s.prepare_command = <<-CMD ./build/ios/library CMD s.platform = :ios, "9.0" s.vendored_framework = "build/ios/Frameworks/*.framework" end measurement-kit-0.7.1/mkdocs.yml000066400000000000000000000000741315356162600166450ustar00rootroot00000000000000site_name: Measurement Kit theme: readthedocs docs_dir: doc measurement-kit-0.7.1/script/000077500000000000000000000000001315356162600161455ustar00rootroot00000000000000measurement-kit-0.7.1/script/pretty_report.py000077500000000000000000000002671315356162600214510ustar00rootroot00000000000000#!/usr/bin/env python import json, sys for line in open(sys.argv[1], "rb"): json.dump(json.loads(line.strip()), sys.stdout, indent=4, sort_keys=True) sys.stdout.write("\n\n") measurement-kit-0.7.1/src/000077500000000000000000000000001315356162600154305ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/000077500000000000000000000000001315356162600213135ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/common/000077500000000000000000000000001315356162600226035ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/common/encoding.cpp000066400000000000000000000026261315356162600251030ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/portable/citrus_adapt.h" #include "private/common/encoding_base64_impl.hpp" #include "private/common/encoding.hpp" #include #include namespace mk { Error is_valid_utf8_string(const std::string &s) { _utf8_state state = {}; size_t r = 1; for (char c : s) { r = mk_utf8_mbrtowc(nullptr, &c, 1, (mbstate_t *)&state); if (r == (size_t)-2) { // We're in the middle of a multibyte sequence continue; } if (r == (size_t)-1) { // The sequence is invalid return IllegalSequenceError(); } if (r == 0) { // We were not expecting a L'\0' at this point return UnexpectedNullByteError(); } /* * Because we parse each character independently, mbrtowc() should * tell us that we have consumed one character after each call. */ assert(r == 1); } assert(r == (size_t)-2 || r == 1); if (r == (size_t)-2) { return IncompleteUtf8SequenceError(); } return NoError(); } std::string base64_encode(std::string s) { return base64_encode_impl((const uint8_t *)s.data(), s.size()); } } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/common/logger.cpp000066400000000000000000000136041315356162600245720ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/common/json.hpp" #include #include #include namespace mk { /*static*/ Var Logger::make() { return Var(new Logger); } Logger::Logger() { consumer_ = [](uint32_t level, const char *s) { std::string message; if ((level & MK_LOG_EVENT) != 0) { Error err = json_parse_and_process( s, [&](auto j) { message = j.dump(4); }); if (err) { fprintf(stderr, "warning: logger cannot parse json message\n"); return; } s = message.c_str(); /* FALLTHROUGH */ } uint32_t verbosity = (level & MK_LOG_VERBOSITY_MASK); if (verbosity <= MK_LOG_WARNING) { fprintf(stderr, "[!] %s\n", s); } else if (verbosity == MK_LOG_INFO) { fprintf(stderr, "%s\n", s); } else { fprintf(stderr, "[D] %s\n", s); } }; } void Logger::logv(uint32_t level, const char *fmt, va_list ap) { if (!consumer_ and !ofile_) { return; } std::lock_guard lock(mutex_); int res = vsnprintf(buffer_, sizeof(buffer_), fmt, ap); // Once we know that res is non-negative we make it unsigned, // which allows the compiler to promote the smaller of res and // sizeof (buffer) to the correct size if needed. if (res < 0) { res = snprintf(buffer_, sizeof(buffer_), "logger: cannot format message with level %d " "and format string '%s' (vsnprintf() returned: %d)", level, fmt, res); if (res < 0 || (unsigned int)res >= sizeof(buffer_)) { static const char eb[] = "logger: cannot format message"; static_assert(sizeof (buffer_) >= sizeof (eb), "buffer_ too short"); memcpy(buffer_, eb, sizeof (eb)); // FALLTHROUGH } level = MK_LOG_WARNING; } else if ((unsigned int)res >= sizeof(buffer_)) { static_assert(sizeof(buffer_) >= 4, "buffer_ too short"); buffer_[sizeof (buffer_) - 1] = '\0'; buffer_[sizeof (buffer_) - 2] = '.'; buffer_[sizeof (buffer_) - 3] = '.'; buffer_[sizeof (buffer_) - 4] = '.'; } else { /* NOTHING */ ; } // Since v0.4 we dispatch the MK_LOG_EVENT event to the proper handler // if set, otherwise we fallthrough passing it to consumer_. if (event_handler_ and (level & MK_LOG_EVENT) != 0) { try { event_handler_(buffer_); } catch (const std::exception &) { /* Suppress */ ; } return; } if (consumer_) { try { consumer_(level, buffer_); } catch (const std::exception &) { /* Suppress */ ; } } if (ofile_) { *ofile_ << buffer_ << "\n"; // TODO: suppose here write fails... what do we want to do? } } #define XX(_logger_, _level_) \ do { \ uint32_t real_level = (_level_) & MK_LOG_VERBOSITY_MASK; \ if (real_level <= _logger_->get_verbosity()) { \ va_list ap; \ va_start(ap, fmt); \ _logger_->logv(_level_, fmt, ap); \ va_end(ap); \ } \ } while (0) void Logger::log(uint32_t level, const char *fmt, ...) { XX(this, level); } void Logger::warn(const char *fmt, ...) { XX(this, MK_LOG_WARNING); } void Logger::info(const char *fmt, ...) { XX(this, MK_LOG_INFO); } void Logger::debug(const char *fmt, ...) { XX(this, MK_LOG_DEBUG); } void Logger::on_eof(Delegate<> f) { eof_handlers_.push_back(f); } void Logger::on_event(Delegate f) { event_handler_ = f; } void log(uint32_t level, const char *fmt, ...) { XX(Logger::global(), level); } void warn(const char *fmt, ...) { XX(Logger::global(), MK_LOG_WARNING); } void info(const char *fmt, ...) { XX(Logger::global(), MK_LOG_INFO); } void debug(const char *fmt, ...) { XX(Logger::global(), MK_LOG_DEBUG); } #undef XX void Logger::increase_verbosity() { if (verbosity_ < MK_LOG_VERBOSITY_MASK) { ++verbosity_; } } void Logger::on_progress(Delegate fn) { progress_handler_ = fn; } void Logger::set_logfile(std::string path) { ofile_.reset(new std::ofstream(path)); // TODO: what to do if we cannot open the logfile? return error? } void Logger::progress(double prog, const char *s) { if (progress_handler_) { prog = prog * progress_scale_ + progress_offset_; try { progress_handler_(prog, s); } catch (const std::exception &) { /* Suppress */ ; } } } void Logger::progress_relative(double prog, const char *s) { if (progress_handler_) { progress_relative_ += prog * progress_scale_; try { progress_handler_(progress_offset_ + progress_relative_, s); } catch (const std::exception &) { /* Suppress */ ; } } } void Logger::set_progress_offset(double offset) { progress_offset_ = offset; progress_relative_ = 0.0; } void Logger::set_progress_scale(double scale) { progress_scale_ = scale; } Logger::~Logger() { for (auto f : eof_handlers_) { try { f(); } catch (const std::exception &) { /* Suppress */ ; } } } } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/common/parallel.cpp000066400000000000000000000044311315356162600251050ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include "private/common/parallel.hpp" namespace mk { static void run( size_t idx, std::vector> input, Callback cb, Var overall, Var completed, size_t parallelism) { if (idx < input.size()) { input[idx]([=](Error error) { // XXX: code not thread safe, to make thread safe we could // share a mutex or use call_later() to serialize if (error and *overall == NoError()) { static const Error template_error = ParallelOperationError(); overall->code = template_error.code; overall->reason = template_error.reason; // FALLTHROUGH } overall->child_errors[idx] = Var(new Error(error)); *completed += 1; if (*completed == input.size()) { cb(*overall); return; } if (*completed > input.size()) { // Use exception, not assert, so it cannot be disabled using // compiler flags and we always make this check throw std::runtime_error("unexpected *complete value"); } run(idx + parallelism, input, cb, overall, completed, parallelism); }); } } void parallel(std::vector> input, Callback cb, size_t parallelism) { Var overall(new Error(NoError())); if (input.size() <= 0) { cb(*overall); return; } overall->child_errors.resize(input.size(), nullptr); Var completed(new size_t(0)); if (parallelism <= 0) { parallelism = input.size(); } /* * Possible improvement: use an atomic shared integer as opposed to * using a counter to speed up the parallel process at the end, when * some "threads" could terminate earlier than others. * * Enhancement suggested by @AntonioLangiu. */ for (size_t idx = 0; idx < parallelism; ++idx) { run(idx, input, cb, overall, completed, parallelism); } } } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/common/platform.cpp000066400000000000000000000014351315356162600251360ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include /* * Guess the platform in which we are. * * See: * */ #if defined __ANDROID__ # define MK_PLATFORM "android" #elif defined __linux__ # define MK_PLATFORM "linux" #elif defined _WIN32 # define MK_PLATFORM "windows" #elif defined __APPLE__ # include # if TARGET_OS_IPHONE # define MK_PLATFORM "ios" # else # define MK_PLATFORM "macos" # endif #else # define MK_PLATFORM "unknown" #endif const char *mk_platform() { return MK_PLATFORM; } measurement-kit-0.7.1/src/libmeasurement_kit/common/reactor.cpp000066400000000000000000000022131315356162600247440ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/libevent/poller.hpp" namespace mk { /*static*/ Var Reactor::make() { return locked_global([]() { return Var{new libevent::Poller}; }); } Reactor::~Reactor() {} void Reactor::run_with_initial_event(Callback<> &&cb) { call_soon(std::move(cb)); loop(); } /*static*/ Var Reactor::global() { return locked_global([]() { static Var singleton = make(); return singleton; }); } void call_soon(Callback<> &&callback, Var reactor) { reactor->call_soon(std::move(callback)); } void call_later(double delta, Callback<> &&callback, Var reactor) { reactor->call_later(delta, std::move(callback)); } void loop_with_initial_event(Callback<> &&callback, Var reactor) { reactor->run_with_initial_event(std::move(callback)); } void loop(Var reactor) { reactor->run(); } void break_loop(Var reactor) { reactor->stop(); } } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/common/utils.cpp000066400000000000000000000131721315356162600244530ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include #include #include #include #include #include "private/common/utils_impl.hpp" namespace mk { void timeval_now(timeval *tv) { *tv = {}; if (gettimeofday(tv, nullptr) != 0) { throw std::runtime_error("gettimeofday()"); } } double time_now() { timeval tv; timeval_now(&tv); double result = tv.tv_sec + tv.tv_usec / (double)1000000.0; return result; } void utc_time_now(struct tm *utc) { time_t tv = {}; tv = time(nullptr); gmtime_r(&tv, utc); } Error parse_iso8601_utc(std::string ts, std::tm *tmb) { *tmb = {}; // "portable programs should initialize the structure" std::istringstream ss(ts); ss >> std::get_time(tmb, "%Y-%m-%dT%H:%M:%SZ"); if (ss.fail()) { return ValueError(); } return NoError(); } ErrorOr timestamp(const struct tm *t) { char result[30]; if (strftime(result, sizeof(result), "%Y-%m-%d %H:%M:%S", t) == 0) { return ValueError(); } return std::string(result); } timeval *timeval_init(timeval *tv, double delta) { if (delta < 0) { return nullptr; } tv->tv_sec = (time_t)floor(delta); tv->tv_usec = (suseconds_t)((delta - floor(delta)) * 1000000); return tv; } // See std::string random_within_charset(const std::string charset, size_t length) { if (charset.size() < 1) { throw ValueError(); } auto randchar = [&charset]() { int rand = 0; evutil_secure_rng_get_bytes(&rand, sizeof (rand)); return charset[rand % charset.size()]; }; std::string str(length, 0); std::generate_n(str.begin(), length, randchar); return str; } std::string random_printable(size_t length) { static const std::string ascii = " !\"#$%&\'()*+,-./" // before numbers "0123456789" // numbers ":;<=>?@" // after numbers "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // uppercase "[\\]^_`" // between upper and lower "abcdefghijklmnopqrstuvwxyz" // lowercase "{|}~" // final ; return random_within_charset(ascii, length); } std::string random_str(size_t length) { static const std::string alnum = "0123456789" // numbers "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // uppercase "abcdefghijklmnopqrstuvwxyz" // lowercase ; return random_within_charset(alnum, length); } std::string random_str_uppercase(size_t length) { static const std::string num_upper = "0123456789" // numbers "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // uppercase ; return random_within_charset(num_upper, length); } void dump_settings(Settings &s, std::string prefix, Var logger) { logger->debug("%s: {", prefix.c_str()); for (auto pair : s) { logger->debug("%s: %s => %s", prefix.c_str(), pair.first.c_str(), pair.second.c_str()); } logger->debug("%s: }", prefix.c_str()); } // Adapted from double percentile(std::vector v, double percent) { if (v.size() <= 0) { throw std::runtime_error("zero length vector"); } std::sort(v.begin(), v.end()); auto pivot = (v.size() - 1) * percent; auto pivot_floor = floor(pivot); auto pivot_ceil = ceil(pivot); if (pivot_floor == pivot_ceil) { return v[int(pivot)]; } auto val0 = v[int(pivot_floor)] * (pivot_ceil - pivot); auto val1 = v[int(pivot_ceil)] * (pivot - pivot_floor); return val0 + val1; } // See: std::string sha256_of(std::string input) { unsigned char hash[SHA256_DIGEST_LENGTH]; constexpr size_t hash_size = sizeof(hash) / sizeof(hash[0]); SHA256_CTX ctx; SHA256_Init(&ctx); SHA256_Update(&ctx, input.data(), input.size()); SHA256_Final(hash, &ctx); std::stringstream ss; for (size_t i = 0; i < hash_size; i++) { ss << std::hex << std::setw(2) << std::setfill('0') << (unsigned)hash[i]; } return ss.str(); } ErrorOr> slurpv(std::string path) { return slurpv_impl(path); } ErrorOr slurp(std::string path) { ErrorOr> v = slurpv_impl(path); if (!v) { return v.as_error(); } std::string s{v->begin(), v->end()}; /* Note that here we make a copy */ return s; } Error overwrite_file(std::string path, std::string content) { return overwrite_file_impl(path, content); } bool startswith(std::string s, std::string p) { return s.find(p) == 0; } /*- * 0 1 2 3 4 5 6 * s: |f|o|o|b|a|r| * p: |b|a|r| * 0 1 2 3 * * s.size() - p.size() = 3 */ bool endswith(std::string s, std::string p) { return s.size() >= p.size() ? s.rfind(p) == (s.size() - p.size()) : false; } std::string random_choice(std::vector inputs) { std::random_device rd; std::mt19937 g(rd()); std::shuffle(inputs.begin(), inputs.end(), g); return inputs[0]; } std::string randomly_capitalize(std::string input) { std::random_device rd; std::mt19937 g(rd()); for (auto &c: input) { if (g() % 2 == 0) { c = toupper(c); } else { c = tolower(c); } } return input; } } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/common/version.cpp000066400000000000000000000010251315356162600247720ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include #include const char *mk_version() { return MK_VERSION; } const char *mk_version_full() { return MK_VERSION_FULL; } const char *mk_openssl_version() { return OPENSSL_VERSION_TEXT; } const char *mk_libevent_version() { return LIBEVENT_VERSION; } measurement-kit-0.7.1/src/libmeasurement_kit/common/worker.cpp000066400000000000000000000051101315356162600246150ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/common/worker.hpp" #include #include #include namespace mk { size_t Worker::parallelism() { return locked(*mutex_, [this]() { return parallelism_; }); } void Worker::set_parallelism(size_t new_value) { locked(*mutex_, [this, &new_value]() { parallelism_ = new_value; }); } void Worker::run_in_background_thread(Callback<> &&func) { locked(*mutex_, [this, func = std::move(func)]() { /* * Move function such that the running-in-background thread * has unique ownership and controls its lifecycle. */ queue_->push_back(std::move(func)); /* * The following two assertions guarantee that we're not * doing mistakes in the future when refactoring. */ assert(*active_ >= 0); static_assert(std::is_same::value, "The type of *active_ has changed"); if ((unsigned short)*active_ >= parallelism_) { // Cast clearly safe return; } /* * Note: we want `mutex`, `queue`, etc. to be safe as long as the * thread manipulates them, regardless of `this`'s destiny. */ auto task = [mutex = mutex_, queue = queue_, active = active_]() { for (;;) { Callback<> func = locked(*mutex, [&queue, &active]() { /* * Initialize inside the lock such that there is only * one critical section in which we could be */ if (queue->size() <= 0) { --(*active); return Callback<>{}; } auto front = queue->front(); queue->pop_front(); return front; }); if (!func) { break; } try { func(); } catch (const std::exception &exc) { mk::warn("worker thread: unhandled exception: %s", exc.what()); /* SUPPRESS */; } } }; std::thread{task}.detach(); ++(*active_); }); } short Worker::concurrency() { return locked(*mutex_, [this]() { return *active_; }); } } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/dns/000077500000000000000000000000001315356162600220775ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/dns/query.cpp000066400000000000000000000065161315356162600237600ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/libevent/dns.hpp" #include "private/dns/system_resolver.hpp" namespace mk { namespace dns { void query( QueryClass dns_class, QueryType dns_type, std::string name, Callback> cb, Settings settings, Var reactor, Var logger) { std::string engine = settings.get("dns/engine", std::string("system")); logger->log(MK_LOG_DEBUG2, "dns: engine: %s", engine.c_str()); if (engine == "libevent") { libevent::query(dns_class, dns_type, name, cb, settings, reactor, logger); } else if (engine == "system") { system_resolver(dns_class, dns_type, name, reactor, logger, cb); } else { reactor->call_soon([cb]() { cb(InvalidDnsEngine(), nullptr); }); } } void resolve_hostname(std::string hostname, Callback cb, Settings settings, Var reactor, Var logger) { logger->debug("resolve_hostname: %s", hostname.c_str()); sockaddr_storage storage; Var result(new ResolveHostnameResult); // If address is a valid IPv4 address, connect directly memset(&storage, 0, sizeof storage); if (inet_pton(PF_INET, hostname.c_str(), &storage) == 1) { logger->debug("resolve_hostname: is valid ipv4"); result->addresses.push_back(hostname); result->inet_pton_ipv4 = true; cb(*result); return; } // If address is a valid IPv6 address, connect directly memset(&storage, 0, sizeof storage); if (inet_pton(PF_INET6, hostname.c_str(), &storage) == 1) { logger->debug("resolve_hostname: is valid ipv6"); result->addresses.push_back(hostname); result->inet_pton_ipv6 = true; cb(*result); return; } logger->debug("resolve_hostname: ipv4..."); dns::query("IN", "A", hostname, [=](Error err, Var resp) { logger->debug("resolve_hostname: ipv4... done"); result->ipv4_err = err; if (!err) { result->ipv4_reply = *resp; for (dns::Answer answer : resp->answers) { result->addresses.push_back(answer.ipv4); } } logger->debug("resolve_hostname: ipv6..."); dns::query( "IN", "AAAA", hostname, [=](Error err, Var resp) { logger->debug("resolve_hostname: ipv6... done"); result->ipv6_err = err; if (!err) { result->ipv6_reply = *resp; for (dns::Answer answer : resp->answers) { result->addresses.push_back(answer.ipv6); } } cb(*result); }, settings, reactor, logger); }, settings, reactor, logger); } } // namespace dns } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/dns/query_class.cpp000066400000000000000000000012061315356162600251340ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include namespace mk { namespace dns { #define XX(_name) \ if (s == #_name) { \ return MK_DNS_CLASS_##_name; \ } QueryClassId query_class_ids_(std::string s) { MK_DNS_CLASS_IDS return MK_DNS_CLASS_INVALID; } #undef XX } // namespace dns } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/dns/query_type.cpp000066400000000000000000000012011315356162600250030ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include namespace mk { namespace dns { #define XX(_name) \ if (s == #_name) { \ return MK_DNS_TYPE_##_name; \ } QueryTypeId query_type_ids_(std::string s) { MK_DNS_TYPE_IDS return MK_DNS_TYPE_INVALID; } #undef XX } // namespace dns } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ext/000077500000000000000000000000001315356162600221135ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/ext/http_parser.c000066400000000000000000002137111315356162600246170ustar00rootroot00000000000000/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev * * Additional changes are licensed under the same terms as NGINX and * copyright Joyent, Inc. and other Node contributors. All rights reserved. * * 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. */ #include "private/ext/http_parser.h" #include #include #include #include #include #include #ifndef ULLONG_MAX # define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ #endif #ifndef MIN # define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef ARRAY_SIZE # define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #endif #ifndef BIT_AT # define BIT_AT(a, i) \ (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \ (1 << ((unsigned int) (i) & 7)))) #endif #ifndef ELEM_AT # define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v)) #endif #define SET_ERRNO(e) \ do { \ parser->http_errno = (e); \ } while(0) #define CURRENT_STATE() p_state #define UPDATE_STATE(V) p_state = (enum state) (V); #define RETURN(V) \ do { \ parser->state = CURRENT_STATE(); \ return (V); \ } while (0); #define REEXECUTE() \ goto reexecute; \ #ifdef __GNUC__ # define LIKELY(X) __builtin_expect(!!(X), 1) # define UNLIKELY(X) __builtin_expect(!!(X), 0) #else # define LIKELY(X) (X) # define UNLIKELY(X) (X) #endif /* Run the notify callback FOR, returning ER if it fails */ #define CALLBACK_NOTIFY_(FOR, ER) \ do { \ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ \ if (LIKELY(settings->on_##FOR)) { \ parser->state = CURRENT_STATE(); \ if (UNLIKELY(0 != settings->on_##FOR(parser))) { \ SET_ERRNO(HPE_CB_##FOR); \ } \ UPDATE_STATE(parser->state); \ \ /* We either errored above or got paused; get out */ \ if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ return (ER); \ } \ } \ } while (0) /* Run the notify callback FOR and consume the current byte */ #define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1) /* Run the notify callback FOR and don't consume the current byte */ #define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data) /* Run data callback FOR with LEN bytes, returning ER if it fails */ #define CALLBACK_DATA_(FOR, LEN, ER) \ do { \ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ \ if (FOR##_mark) { \ if (LIKELY(settings->on_##FOR)) { \ parser->state = CURRENT_STATE(); \ if (UNLIKELY(0 != \ settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \ SET_ERRNO(HPE_CB_##FOR); \ } \ UPDATE_STATE(parser->state); \ \ /* We either errored above or got paused; get out */ \ if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ return (ER); \ } \ } \ FOR##_mark = NULL; \ } \ } while (0) /* Run the data callback FOR and consume the current byte */ #define CALLBACK_DATA(FOR) \ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) /* Run the data callback FOR and don't consume the current byte */ #define CALLBACK_DATA_NOADVANCE(FOR) \ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data) /* Set the mark FOR; non-destructive if mark is already set */ #define MARK(FOR) \ do { \ if (!FOR##_mark) { \ FOR##_mark = p; \ } \ } while (0) /* Don't allow the total size of the HTTP headers (including the status * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect * embedders against denial-of-service attacks where the attacker feeds * us a never-ending header that the embedder keeps buffering. * * This check is arguably the responsibility of embedders but we're doing * it on the embedder's behalf because most won't bother and this way we * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger * than any reasonable request or response so this should never affect * day-to-day operation. */ #define COUNT_HEADER_SIZE(V) \ do { \ parser->nread += (V); \ if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \ SET_ERRNO(HPE_HEADER_OVERFLOW); \ goto error; \ } \ } while (0) #define PROXY_CONNECTION "proxy-connection" #define CONNECTION "connection" #define CONTENT_LENGTH "content-length" #define TRANSFER_ENCODING "transfer-encoding" #define UPGRADE "upgrade" #define CHUNKED "chunked" #define KEEP_ALIVE "keep-alive" #define CLOSE "close" static const char *method_strings[] = { #define XX(num, name, string) #string, HTTP_METHOD_MAP(XX) #undef XX }; /* Tokens as defined by rfc 2616. Also lowercases them. * token = 1* * separators = "(" | ")" | "<" | ">" | "@" * | "," | ";" | ":" | "\" | <"> * | "/" | "[" | "]" | "?" | "=" * | "{" | "}" | SP | HT */ static const char tokens[256] = { /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ 0, 0, 0, 0, 0, 0, 0, 0, /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ 0, 0, 0, 0, 0, 0, 0, 0, /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ 0, 0, 0, 0, 0, 0, 0, 0, /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ 0, 0, 0, 0, 0, 0, 0, 0, /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ 0, '!', 0, '#', '$', '%', '&', '\'', /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ 0, 0, '*', '+', 0, '-', '.', 0, /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ '0', '1', '2', '3', '4', '5', '6', '7', /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ '8', '9', 0, 0, 0, 0, 0, 0, /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ 'x', 'y', 'z', 0, 0, 0, '^', '_', /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ 'x', 'y', 'z', 0, '|', 0, '~', 0 }; static const int8_t unhex[256] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; #if HTTP_PARSER_STRICT # define T(v) 0 #else # define T(v) v #endif static const uint8_t normal_url_char[32] = { /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0, /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128, /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, }; #undef T enum state { s_dead = 1 /* important that this is > 0 */ , s_start_req_or_res , s_res_or_resp_H , s_start_res , s_res_H , s_res_HT , s_res_HTT , s_res_HTTP , s_res_first_http_major , s_res_http_major , s_res_first_http_minor , s_res_http_minor , s_res_first_status_code , s_res_status_code , s_res_status_start , s_res_status , s_res_line_almost_done , s_start_req , s_req_method , s_req_spaces_before_url , s_req_schema , s_req_schema_slash , s_req_schema_slash_slash , s_req_server_start , s_req_server , s_req_server_with_at , s_req_path , s_req_query_string_start , s_req_query_string , s_req_fragment_start , s_req_fragment , s_req_http_start , s_req_http_H , s_req_http_HT , s_req_http_HTT , s_req_http_HTTP , s_req_first_http_major , s_req_http_major , s_req_first_http_minor , s_req_http_minor , s_req_line_almost_done , s_header_field_start , s_header_field , s_header_value_discard_ws , s_header_value_discard_ws_almost_done , s_header_value_discard_lws , s_header_value_start , s_header_value , s_header_value_lws , s_header_almost_done , s_chunk_size_start , s_chunk_size , s_chunk_parameters , s_chunk_size_almost_done , s_headers_almost_done , s_headers_done /* Important: 's_headers_done' must be the last 'header' state. All * states beyond this must be 'body' states. It is used for overflow * checking. See the PARSING_HEADER() macro. */ , s_chunk_data , s_chunk_data_almost_done , s_chunk_data_done , s_body_identity , s_body_identity_eof , s_message_done }; #define PARSING_HEADER(state) (state <= s_headers_done) enum header_states { h_general = 0 , h_C , h_CO , h_CON , h_matching_connection , h_matching_proxy_connection , h_matching_content_length , h_matching_transfer_encoding , h_matching_upgrade , h_connection , h_content_length , h_transfer_encoding , h_upgrade , h_matching_transfer_encoding_chunked , h_matching_connection_token_start , h_matching_connection_keep_alive , h_matching_connection_close , h_matching_connection_upgrade , h_matching_connection_token , h_transfer_encoding_chunked , h_connection_keep_alive , h_connection_close , h_connection_upgrade }; enum http_host_state { s_http_host_dead = 1 , s_http_userinfo_start , s_http_userinfo , s_http_host_start , s_http_host_v6_start , s_http_host , s_http_host_v6 , s_http_host_v6_end , s_http_host_v6_zone_start , s_http_host_v6_zone , s_http_host_port_start , s_http_host_port }; /* Macros for character classes; depends on strict-mode */ #define CR '\r' #define LF '\n' #define LOWER(c) (unsigned char)(c | 0x20) #define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') #define IS_NUM(c) ((c) >= '0' && (c) <= '9') #define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) #define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f')) #define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \ (c) == ')') #define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \ (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ (c) == '$' || (c) == ',') #define STRICT_TOKEN(c) (tokens[(unsigned char)c]) #if HTTP_PARSER_STRICT #define TOKEN(c) (tokens[(unsigned char)c]) #define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c)) #define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') #else #define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c]) #define IS_URL_CHAR(c) \ (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) #define IS_HOST_CHAR(c) \ (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') #endif /** * Verify that a char is a valid visible (printable) US-ASCII * character or %x80-FF **/ #define IS_HEADER_CHAR(ch) \ (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127)) #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) #if HTTP_PARSER_STRICT # define STRICT_CHECK(cond) \ do { \ if (cond) { \ SET_ERRNO(HPE_STRICT); \ goto error; \ } \ } while (0) # define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead) #else # define STRICT_CHECK(cond) # define NEW_MESSAGE() start_state #endif /* Map errno values to strings for human-readable output */ #define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, static struct { const char *name; const char *description; } http_strerror_tab[] = { HTTP_ERRNO_MAP(HTTP_STRERROR_GEN) }; #undef HTTP_STRERROR_GEN int http_message_needs_eof(const http_parser *parser); /* Our URL parser. * * This is designed to be shared by http_parser_execute() for URL validation, * hence it has a state transition + byte-for-byte interface. In addition, it * is meant to be embedded in http_parser_parse_url(), which does the dirty * work of turning state transitions URL components for its API. * * This function should only be invoked with non-space characters. It is * assumed that the caller cares about (and can detect) the transition between * URL and non-URL states by looking for these. */ static enum state parse_url_char(enum state s, const char ch) { if (ch == ' ' || ch == '\r' || ch == '\n') { return s_dead; } #if HTTP_PARSER_STRICT if (ch == '\t' || ch == '\f') { return s_dead; } #endif switch (s) { case s_req_spaces_before_url: /* Proxied requests are followed by scheme of an absolute URI (alpha). * All methods except CONNECT are followed by '/' or '*'. */ if (ch == '/' || ch == '*') { return s_req_path; } if (IS_ALPHA(ch)) { return s_req_schema; } break; case s_req_schema: if (IS_ALPHA(ch)) { return s; } if (ch == ':') { return s_req_schema_slash; } break; case s_req_schema_slash: if (ch == '/') { return s_req_schema_slash_slash; } break; case s_req_schema_slash_slash: if (ch == '/') { return s_req_server_start; } break; case s_req_server_with_at: if (ch == '@') { return s_dead; } /* FALLTHROUGH */ case s_req_server_start: case s_req_server: if (ch == '/') { return s_req_path; } if (ch == '?') { return s_req_query_string_start; } if (ch == '@') { return s_req_server_with_at; } if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') { return s_req_server; } break; case s_req_path: if (IS_URL_CHAR(ch)) { return s; } switch (ch) { case '?': return s_req_query_string_start; case '#': return s_req_fragment_start; } break; case s_req_query_string_start: case s_req_query_string: if (IS_URL_CHAR(ch)) { return s_req_query_string; } switch (ch) { case '?': /* allow extra '?' in query string */ return s_req_query_string; case '#': return s_req_fragment_start; } break; case s_req_fragment_start: if (IS_URL_CHAR(ch)) { return s_req_fragment; } switch (ch) { case '?': return s_req_fragment; case '#': return s; } break; case s_req_fragment: if (IS_URL_CHAR(ch)) { return s; } switch (ch) { case '?': case '#': return s; } break; default: break; } /* We should never fall out of the switch above unless there's an error */ return s_dead; } size_t http_parser_execute (http_parser *parser, const http_parser_settings *settings, const char *data, size_t len) { char c, ch; int8_t unhex_val; const char *p = data; const char *header_field_mark = 0; const char *header_value_mark = 0; const char *url_mark = 0; const char *body_mark = 0; const char *status_mark = 0; enum state p_state = (enum state) parser->state; const unsigned int lenient = parser->lenient_http_headers; /* We're in an error state. Don't bother doing anything. */ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { return 0; } if (len == 0) { switch (CURRENT_STATE()) { case s_body_identity_eof: /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if * we got paused. */ CALLBACK_NOTIFY_NOADVANCE(message_complete); return 0; case s_dead: case s_start_req_or_res: case s_start_res: case s_start_req: return 0; default: SET_ERRNO(HPE_INVALID_EOF_STATE); return 1; } } if (CURRENT_STATE() == s_header_field) header_field_mark = data; if (CURRENT_STATE() == s_header_value) header_value_mark = data; switch (CURRENT_STATE()) { case s_req_path: case s_req_schema: case s_req_schema_slash: case s_req_schema_slash_slash: case s_req_server_start: case s_req_server: case s_req_server_with_at: case s_req_query_string_start: case s_req_query_string: case s_req_fragment_start: case s_req_fragment: url_mark = data; break; case s_res_status: status_mark = data; break; default: break; } for (p=data; p != data + len; p++) { ch = *p; if (PARSING_HEADER(CURRENT_STATE())) COUNT_HEADER_SIZE(1); reexecute: switch (CURRENT_STATE()) { case s_dead: /* this state is used after a 'Connection: close' message * the parser will error out if it reads another message */ if (LIKELY(ch == CR || ch == LF)) break; SET_ERRNO(HPE_CLOSED_CONNECTION); goto error; case s_start_req_or_res: { if (ch == CR || ch == LF) break; parser->flags = 0; parser->content_length = ULLONG_MAX; if (ch == 'H') { UPDATE_STATE(s_res_or_resp_H); CALLBACK_NOTIFY(message_begin); } else { parser->type = HTTP_REQUEST; UPDATE_STATE(s_start_req); REEXECUTE(); } break; } case s_res_or_resp_H: if (ch == 'T') { parser->type = HTTP_RESPONSE; UPDATE_STATE(s_res_HT); } else { if (UNLIKELY(ch != 'E')) { SET_ERRNO(HPE_INVALID_CONSTANT); goto error; } parser->type = HTTP_REQUEST; parser->method = HTTP_HEAD; parser->index = 2; UPDATE_STATE(s_req_method); } break; case s_start_res: { parser->flags = 0; parser->content_length = ULLONG_MAX; switch (ch) { case 'H': UPDATE_STATE(s_res_H); break; case CR: case LF: break; default: SET_ERRNO(HPE_INVALID_CONSTANT); goto error; } CALLBACK_NOTIFY(message_begin); break; } case s_res_H: STRICT_CHECK(ch != 'T'); UPDATE_STATE(s_res_HT); break; case s_res_HT: STRICT_CHECK(ch != 'T'); UPDATE_STATE(s_res_HTT); break; case s_res_HTT: STRICT_CHECK(ch != 'P'); UPDATE_STATE(s_res_HTTP); break; case s_res_HTTP: STRICT_CHECK(ch != '/'); UPDATE_STATE(s_res_first_http_major); break; case s_res_first_http_major: if (UNLIKELY(ch < '0' || ch > '9')) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_major = ch - '0'; UPDATE_STATE(s_res_http_major); break; /* major HTTP version or dot */ case s_res_http_major: { if (ch == '.') { UPDATE_STATE(s_res_first_http_minor); break; } if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_major *= 10; parser->http_major += ch - '0'; if (UNLIKELY(parser->http_major > 999)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } break; } /* first digit of minor HTTP version */ case s_res_first_http_minor: if (UNLIKELY(!IS_NUM(ch))) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_minor = ch - '0'; UPDATE_STATE(s_res_http_minor); break; /* minor HTTP version or end of request line */ case s_res_http_minor: { if (ch == ' ') { UPDATE_STATE(s_res_first_status_code); break; } if (UNLIKELY(!IS_NUM(ch))) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_minor *= 10; parser->http_minor += ch - '0'; if (UNLIKELY(parser->http_minor > 999)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } break; } case s_res_first_status_code: { if (!IS_NUM(ch)) { if (ch == ' ') { break; } SET_ERRNO(HPE_INVALID_STATUS); goto error; } parser->status_code = ch - '0'; UPDATE_STATE(s_res_status_code); break; } case s_res_status_code: { if (!IS_NUM(ch)) { switch (ch) { case ' ': UPDATE_STATE(s_res_status_start); break; case CR: UPDATE_STATE(s_res_line_almost_done); break; case LF: UPDATE_STATE(s_header_field_start); break; default: SET_ERRNO(HPE_INVALID_STATUS); goto error; } break; } parser->status_code *= 10; parser->status_code += ch - '0'; if (UNLIKELY(parser->status_code > 999)) { SET_ERRNO(HPE_INVALID_STATUS); goto error; } break; } case s_res_status_start: { if (ch == CR) { UPDATE_STATE(s_res_line_almost_done); break; } if (ch == LF) { UPDATE_STATE(s_header_field_start); break; } MARK(status); UPDATE_STATE(s_res_status); parser->index = 0; break; } case s_res_status: if (ch == CR) { UPDATE_STATE(s_res_line_almost_done); CALLBACK_DATA(status); break; } if (ch == LF) { UPDATE_STATE(s_header_field_start); CALLBACK_DATA(status); break; } break; case s_res_line_almost_done: STRICT_CHECK(ch != LF); UPDATE_STATE(s_header_field_start); break; case s_start_req: { if (ch == CR || ch == LF) break; parser->flags = 0; parser->content_length = ULLONG_MAX; if (UNLIKELY(!IS_ALPHA(ch))) { SET_ERRNO(HPE_INVALID_METHOD); goto error; } parser->method = (enum http_method) 0; parser->index = 1; switch (ch) { case 'A': parser->method = HTTP_ACL; break; case 'B': parser->method = HTTP_BIND; break; case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break; case 'D': parser->method = HTTP_DELETE; break; case 'G': parser->method = HTTP_GET; break; case 'H': parser->method = HTTP_HEAD; break; case 'L': parser->method = HTTP_LOCK; /* or LINK */ break; case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break; case 'N': parser->method = HTTP_NOTIFY; break; case 'O': parser->method = HTTP_OPTIONS; break; case 'P': parser->method = HTTP_POST; /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ break; case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break; case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break; case 'T': parser->method = HTTP_TRACE; break; case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break; default: SET_ERRNO(HPE_INVALID_METHOD); goto error; } UPDATE_STATE(s_req_method); CALLBACK_NOTIFY(message_begin); break; } case s_req_method: { const char *matcher; if (UNLIKELY(ch == '\0')) { SET_ERRNO(HPE_INVALID_METHOD); goto error; } matcher = method_strings[parser->method]; if (ch == ' ' && matcher[parser->index] == '\0') { UPDATE_STATE(s_req_spaces_before_url); } else if (ch == matcher[parser->index]) { ; /* nada */ } else if (IS_ALPHA(ch)) { switch (parser->method << 16 | parser->index << 8 | ch) { #define XX(meth, pos, ch, new_meth) \ case (HTTP_##meth << 16 | pos << 8 | ch): \ parser->method = HTTP_##new_meth; break; XX(POST, 1, 'U', PUT) XX(POST, 1, 'A', PATCH) XX(CONNECT, 1, 'H', CHECKOUT) XX(CONNECT, 2, 'P', COPY) XX(MKCOL, 1, 'O', MOVE) XX(MKCOL, 1, 'E', MERGE) XX(MKCOL, 2, 'A', MKACTIVITY) XX(MKCOL, 3, 'A', MKCALENDAR) XX(SUBSCRIBE, 1, 'E', SEARCH) XX(REPORT, 2, 'B', REBIND) XX(POST, 1, 'R', PROPFIND) XX(PROPFIND, 4, 'P', PROPPATCH) XX(PUT, 2, 'R', PURGE) XX(LOCK, 1, 'I', LINK) XX(UNLOCK, 2, 'S', UNSUBSCRIBE) XX(UNLOCK, 2, 'B', UNBIND) XX(UNLOCK, 3, 'I', UNLINK) #undef XX default: SET_ERRNO(HPE_INVALID_METHOD); goto error; } } else if (ch == '-' && parser->index == 1 && parser->method == HTTP_MKCOL) { parser->method = HTTP_MSEARCH; } else { SET_ERRNO(HPE_INVALID_METHOD); goto error; } ++parser->index; break; } case s_req_spaces_before_url: { if (ch == ' ') break; MARK(url); if (parser->method == HTTP_CONNECT) { UPDATE_STATE(s_req_server_start); } UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); if (UNLIKELY(CURRENT_STATE() == s_dead)) { SET_ERRNO(HPE_INVALID_URL); goto error; } break; } case s_req_schema: case s_req_schema_slash: case s_req_schema_slash_slash: case s_req_server_start: { switch (ch) { /* No whitespace allowed here */ case ' ': case CR: case LF: SET_ERRNO(HPE_INVALID_URL); goto error; default: UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); if (UNLIKELY(CURRENT_STATE() == s_dead)) { SET_ERRNO(HPE_INVALID_URL); goto error; } } break; } case s_req_server: case s_req_server_with_at: case s_req_path: case s_req_query_string_start: case s_req_query_string: case s_req_fragment_start: case s_req_fragment: { switch (ch) { case ' ': UPDATE_STATE(s_req_http_start); CALLBACK_DATA(url); break; case CR: case LF: parser->http_major = 0; parser->http_minor = 9; UPDATE_STATE((ch == CR) ? s_req_line_almost_done : s_header_field_start); CALLBACK_DATA(url); break; default: UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); if (UNLIKELY(CURRENT_STATE() == s_dead)) { SET_ERRNO(HPE_INVALID_URL); goto error; } } break; } case s_req_http_start: switch (ch) { case 'H': UPDATE_STATE(s_req_http_H); break; case ' ': break; default: SET_ERRNO(HPE_INVALID_CONSTANT); goto error; } break; case s_req_http_H: STRICT_CHECK(ch != 'T'); UPDATE_STATE(s_req_http_HT); break; case s_req_http_HT: STRICT_CHECK(ch != 'T'); UPDATE_STATE(s_req_http_HTT); break; case s_req_http_HTT: STRICT_CHECK(ch != 'P'); UPDATE_STATE(s_req_http_HTTP); break; case s_req_http_HTTP: STRICT_CHECK(ch != '/'); UPDATE_STATE(s_req_first_http_major); break; /* first digit of major HTTP version */ case s_req_first_http_major: if (UNLIKELY(ch < '1' || ch > '9')) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_major = ch - '0'; UPDATE_STATE(s_req_http_major); break; /* major HTTP version or dot */ case s_req_http_major: { if (ch == '.') { UPDATE_STATE(s_req_first_http_minor); break; } if (UNLIKELY(!IS_NUM(ch))) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_major *= 10; parser->http_major += ch - '0'; if (UNLIKELY(parser->http_major > 999)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } break; } /* first digit of minor HTTP version */ case s_req_first_http_minor: if (UNLIKELY(!IS_NUM(ch))) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_minor = ch - '0'; UPDATE_STATE(s_req_http_minor); break; /* minor HTTP version or end of request line */ case s_req_http_minor: { if (ch == CR) { UPDATE_STATE(s_req_line_almost_done); break; } if (ch == LF) { UPDATE_STATE(s_header_field_start); break; } /* XXX allow spaces after digit? */ if (UNLIKELY(!IS_NUM(ch))) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_minor *= 10; parser->http_minor += ch - '0'; if (UNLIKELY(parser->http_minor > 999)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } break; } /* end of request line */ case s_req_line_almost_done: { if (UNLIKELY(ch != LF)) { SET_ERRNO(HPE_LF_EXPECTED); goto error; } UPDATE_STATE(s_header_field_start); break; } case s_header_field_start: { if (ch == CR) { UPDATE_STATE(s_headers_almost_done); break; } if (ch == LF) { /* they might be just sending \n instead of \r\n so this would be * the second \n to denote the end of headers*/ UPDATE_STATE(s_headers_almost_done); REEXECUTE(); } c = TOKEN(ch); if (UNLIKELY(!c)) { SET_ERRNO(HPE_INVALID_HEADER_TOKEN); goto error; } MARK(header_field); parser->index = 0; UPDATE_STATE(s_header_field); switch (c) { case 'c': parser->header_state = h_C; break; case 'p': parser->header_state = h_matching_proxy_connection; break; case 't': parser->header_state = h_matching_transfer_encoding; break; case 'u': parser->header_state = h_matching_upgrade; break; default: parser->header_state = h_general; break; } break; } case s_header_field: { const char* start = p; for (; p != data + len; p++) { ch = *p; c = TOKEN(ch); if (!c) break; switch (parser->header_state) { case h_general: break; case h_C: parser->index++; parser->header_state = (c == 'o' ? h_CO : h_general); break; case h_CO: parser->index++; parser->header_state = (c == 'n' ? h_CON : h_general); break; case h_CON: parser->index++; switch (c) { case 'n': parser->header_state = h_matching_connection; break; case 't': parser->header_state = h_matching_content_length; break; default: parser->header_state = h_general; break; } break; /* connection */ case h_matching_connection: parser->index++; if (parser->index > sizeof(CONNECTION)-1 || c != CONNECTION[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(CONNECTION)-2) { parser->header_state = h_connection; } break; /* proxy-connection */ case h_matching_proxy_connection: parser->index++; if (parser->index > sizeof(PROXY_CONNECTION)-1 || c != PROXY_CONNECTION[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(PROXY_CONNECTION)-2) { parser->header_state = h_connection; } break; /* content-length */ case h_matching_content_length: parser->index++; if (parser->index > sizeof(CONTENT_LENGTH)-1 || c != CONTENT_LENGTH[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { parser->header_state = h_content_length; } break; /* transfer-encoding */ case h_matching_transfer_encoding: parser->index++; if (parser->index > sizeof(TRANSFER_ENCODING)-1 || c != TRANSFER_ENCODING[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) { parser->header_state = h_transfer_encoding; } break; /* upgrade */ case h_matching_upgrade: parser->index++; if (parser->index > sizeof(UPGRADE)-1 || c != UPGRADE[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(UPGRADE)-2) { parser->header_state = h_upgrade; } break; case h_connection: case h_content_length: case h_transfer_encoding: case h_upgrade: if (ch != ' ') parser->header_state = h_general; break; default: assert(0 && "Unknown header_state"); break; } } COUNT_HEADER_SIZE(p - start); if (p == data + len) { --p; break; } if (ch == ':') { UPDATE_STATE(s_header_value_discard_ws); CALLBACK_DATA(header_field); break; } SET_ERRNO(HPE_INVALID_HEADER_TOKEN); goto error; } case s_header_value_discard_ws: if (ch == ' ' || ch == '\t') break; if (ch == CR) { UPDATE_STATE(s_header_value_discard_ws_almost_done); break; } if (ch == LF) { UPDATE_STATE(s_header_value_discard_lws); break; } /* FALLTHROUGH */ case s_header_value_start: { MARK(header_value); UPDATE_STATE(s_header_value); parser->index = 0; c = LOWER(ch); switch (parser->header_state) { case h_upgrade: parser->flags |= F_UPGRADE; parser->header_state = h_general; break; case h_transfer_encoding: /* looking for 'Transfer-Encoding: chunked' */ if ('c' == c) { parser->header_state = h_matching_transfer_encoding_chunked; } else { parser->header_state = h_general; } break; case h_content_length: if (UNLIKELY(!IS_NUM(ch))) { SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } if (parser->flags & F_CONTENTLENGTH) { SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); goto error; } parser->flags |= F_CONTENTLENGTH; parser->content_length = ch - '0'; break; case h_connection: /* looking for 'Connection: keep-alive' */ if (c == 'k') { parser->header_state = h_matching_connection_keep_alive; /* looking for 'Connection: close' */ } else if (c == 'c') { parser->header_state = h_matching_connection_close; } else if (c == 'u') { parser->header_state = h_matching_connection_upgrade; } else { parser->header_state = h_matching_connection_token; } break; /* Multi-value `Connection` header */ case h_matching_connection_token_start: break; default: parser->header_state = h_general; break; } break; } case s_header_value: { const char* start = p; enum header_states h_state = (enum header_states) parser->header_state; for (; p != data + len; p++) { ch = *p; if (ch == CR) { UPDATE_STATE(s_header_almost_done); parser->header_state = h_state; CALLBACK_DATA(header_value); break; } if (ch == LF) { UPDATE_STATE(s_header_almost_done); COUNT_HEADER_SIZE(p - start); parser->header_state = h_state; CALLBACK_DATA_NOADVANCE(header_value); REEXECUTE(); } if (!lenient && !IS_HEADER_CHAR(ch)) { SET_ERRNO(HPE_INVALID_HEADER_TOKEN); goto error; } c = LOWER(ch); switch (h_state) { case h_general: { const char* p_cr; const char* p_lf; size_t limit = data + len - p; limit = MIN(limit, HTTP_MAX_HEADER_SIZE); p_cr = (const char*) memchr(p, CR, limit); p_lf = (const char*) memchr(p, LF, limit); if (p_cr != NULL) { if (p_lf != NULL && p_cr >= p_lf) p = p_lf; else p = p_cr; } else if (UNLIKELY(p_lf != NULL)) { p = p_lf; } else { p = data + len; } --p; break; } case h_connection: case h_transfer_encoding: assert(0 && "Shouldn't get here."); break; case h_content_length: { uint64_t t; if (ch == ' ') break; if (UNLIKELY(!IS_NUM(ch))) { SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); parser->header_state = h_state; goto error; } t = parser->content_length; t *= 10; t += ch - '0'; /* Overflow? Test against a conservative limit for simplicity. */ if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) { SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); parser->header_state = h_state; goto error; } parser->content_length = t; break; } /* Transfer-Encoding: chunked */ case h_matching_transfer_encoding_chunked: parser->index++; if (parser->index > sizeof(CHUNKED)-1 || c != CHUNKED[parser->index]) { h_state = h_general; } else if (parser->index == sizeof(CHUNKED)-2) { h_state = h_transfer_encoding_chunked; } break; case h_matching_connection_token_start: /* looking for 'Connection: keep-alive' */ if (c == 'k') { h_state = h_matching_connection_keep_alive; /* looking for 'Connection: close' */ } else if (c == 'c') { h_state = h_matching_connection_close; } else if (c == 'u') { h_state = h_matching_connection_upgrade; } else if (STRICT_TOKEN(c)) { h_state = h_matching_connection_token; } else if (c == ' ' || c == '\t') { /* Skip lws */ } else { h_state = h_general; } break; /* looking for 'Connection: keep-alive' */ case h_matching_connection_keep_alive: parser->index++; if (parser->index > sizeof(KEEP_ALIVE)-1 || c != KEEP_ALIVE[parser->index]) { h_state = h_matching_connection_token; } else if (parser->index == sizeof(KEEP_ALIVE)-2) { h_state = h_connection_keep_alive; } break; /* looking for 'Connection: close' */ case h_matching_connection_close: parser->index++; if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { h_state = h_matching_connection_token; } else if (parser->index == sizeof(CLOSE)-2) { h_state = h_connection_close; } break; /* looking for 'Connection: upgrade' */ case h_matching_connection_upgrade: parser->index++; if (parser->index > sizeof(UPGRADE) - 1 || c != UPGRADE[parser->index]) { h_state = h_matching_connection_token; } else if (parser->index == sizeof(UPGRADE)-2) { h_state = h_connection_upgrade; } break; case h_matching_connection_token: if (ch == ',') { h_state = h_matching_connection_token_start; parser->index = 0; } break; case h_transfer_encoding_chunked: if (ch != ' ') h_state = h_general; break; case h_connection_keep_alive: case h_connection_close: case h_connection_upgrade: if (ch == ',') { if (h_state == h_connection_keep_alive) { parser->flags |= F_CONNECTION_KEEP_ALIVE; } else if (h_state == h_connection_close) { parser->flags |= F_CONNECTION_CLOSE; } else if (h_state == h_connection_upgrade) { parser->flags |= F_CONNECTION_UPGRADE; } h_state = h_matching_connection_token_start; parser->index = 0; } else if (ch != ' ') { h_state = h_matching_connection_token; } break; default: UPDATE_STATE(s_header_value); h_state = h_general; break; } } parser->header_state = h_state; COUNT_HEADER_SIZE(p - start); if (p == data + len) --p; break; } case s_header_almost_done: { if (UNLIKELY(ch != LF)) { SET_ERRNO(HPE_LF_EXPECTED); goto error; } UPDATE_STATE(s_header_value_lws); break; } case s_header_value_lws: { if (ch == ' ' || ch == '\t') { UPDATE_STATE(s_header_value_start); REEXECUTE(); } /* finished the header */ switch (parser->header_state) { case h_connection_keep_alive: parser->flags |= F_CONNECTION_KEEP_ALIVE; break; case h_connection_close: parser->flags |= F_CONNECTION_CLOSE; break; case h_transfer_encoding_chunked: parser->flags |= F_CHUNKED; break; case h_connection_upgrade: parser->flags |= F_CONNECTION_UPGRADE; break; default: break; } UPDATE_STATE(s_header_field_start); REEXECUTE(); } case s_header_value_discard_ws_almost_done: { STRICT_CHECK(ch != LF); UPDATE_STATE(s_header_value_discard_lws); break; } case s_header_value_discard_lws: { if (ch == ' ' || ch == '\t') { UPDATE_STATE(s_header_value_discard_ws); break; } else { switch (parser->header_state) { case h_connection_keep_alive: parser->flags |= F_CONNECTION_KEEP_ALIVE; break; case h_connection_close: parser->flags |= F_CONNECTION_CLOSE; break; case h_connection_upgrade: parser->flags |= F_CONNECTION_UPGRADE; break; case h_transfer_encoding_chunked: parser->flags |= F_CHUNKED; break; default: break; } /* header value was empty */ MARK(header_value); UPDATE_STATE(s_header_field_start); CALLBACK_DATA_NOADVANCE(header_value); REEXECUTE(); } } case s_headers_almost_done: { STRICT_CHECK(ch != LF); if (parser->flags & F_TRAILING) { /* End of a chunked request */ UPDATE_STATE(s_message_done); CALLBACK_NOTIFY_NOADVANCE(chunk_complete); REEXECUTE(); } /* Cannot use chunked encoding and a content-length header together per the HTTP specification. */ if ((parser->flags & F_CHUNKED) && (parser->flags & F_CONTENTLENGTH)) { SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); goto error; } UPDATE_STATE(s_headers_done); /* Set this here so that on_headers_complete() callbacks can see it */ if ((parser->flags & F_UPGRADE) && (parser->flags & F_CONNECTION_UPGRADE)) { /* For responses, "Upgrade: foo" and "Connection: upgrade" are * mandatory only when it is a 101 Switching Protocols response, * otherwise it is purely informational, to announce support. */ parser->upgrade = (parser->type == HTTP_REQUEST || parser->status_code == 101); } else { parser->upgrade = (parser->method == HTTP_CONNECT); } /* Here we call the headers_complete callback. This is somewhat * different than other callbacks because if the user returns 1, we * will interpret that as saying that this message has no body. This * is needed for the annoying case of recieving a response to a HEAD * request. * * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so * we have to simulate it by handling a change in errno below. */ if (settings->on_headers_complete) { switch (settings->on_headers_complete(parser)) { case 0: break; case 2: parser->upgrade = 1; case 1: parser->flags |= F_SKIPBODY; break; default: SET_ERRNO(HPE_CB_headers_complete); RETURN(p - data); /* Error */ } } if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { RETURN(p - data); } REEXECUTE(); } case s_headers_done: { int hasBody; STRICT_CHECK(ch != LF); parser->nread = 0; hasBody = parser->flags & F_CHUNKED || (parser->content_length > 0 && parser->content_length != ULLONG_MAX); if (parser->upgrade && (parser->method == HTTP_CONNECT || (parser->flags & F_SKIPBODY) || !hasBody)) { /* Exit, the rest of the message is in a different protocol. */ UPDATE_STATE(NEW_MESSAGE()); CALLBACK_NOTIFY(message_complete); RETURN((p - data) + 1); } if (parser->flags & F_SKIPBODY) { UPDATE_STATE(NEW_MESSAGE()); CALLBACK_NOTIFY(message_complete); } else if (parser->flags & F_CHUNKED) { /* chunked encoding - ignore Content-Length header */ UPDATE_STATE(s_chunk_size_start); } else { if (parser->content_length == 0) { /* Content-Length header given but zero: Content-Length: 0\r\n */ UPDATE_STATE(NEW_MESSAGE()); CALLBACK_NOTIFY(message_complete); } else if (parser->content_length != ULLONG_MAX) { /* Content-Length header given and non-zero */ UPDATE_STATE(s_body_identity); } else { if (!http_message_needs_eof(parser)) { /* Assume content-length 0 - read the next */ UPDATE_STATE(NEW_MESSAGE()); CALLBACK_NOTIFY(message_complete); } else { /* Read body until EOF */ UPDATE_STATE(s_body_identity_eof); } } } break; } case s_body_identity: { uint64_t to_read = MIN(parser->content_length, (uint64_t) ((data + len) - p)); assert(parser->content_length != 0 && parser->content_length != ULLONG_MAX); /* The difference between advancing content_length and p is because * the latter will automaticaly advance on the next loop iteration. * Further, if content_length ends up at 0, we want to see the last * byte again for our message complete callback. */ MARK(body); parser->content_length -= to_read; p += to_read - 1; if (parser->content_length == 0) { UPDATE_STATE(s_message_done); /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte. * * The alternative to doing this is to wait for the next byte to * trigger the data callback, just as in every other case. The * problem with this is that this makes it difficult for the test * harness to distinguish between complete-on-EOF and * complete-on-length. It's not clear that this distinction is * important for applications, but let's keep it for now. */ CALLBACK_DATA_(body, p - body_mark + 1, p - data); REEXECUTE(); } break; } /* read until EOF */ case s_body_identity_eof: MARK(body); p = data + len - 1; break; case s_message_done: UPDATE_STATE(NEW_MESSAGE()); CALLBACK_NOTIFY(message_complete); if (parser->upgrade) { /* Exit, the rest of the message is in a different protocol. */ RETURN((p - data) + 1); } break; case s_chunk_size_start: { assert(parser->nread == 1); assert(parser->flags & F_CHUNKED); unhex_val = unhex[(unsigned char)ch]; if (UNLIKELY(unhex_val == -1)) { SET_ERRNO(HPE_INVALID_CHUNK_SIZE); goto error; } parser->content_length = unhex_val; UPDATE_STATE(s_chunk_size); break; } case s_chunk_size: { uint64_t t; assert(parser->flags & F_CHUNKED); if (ch == CR) { UPDATE_STATE(s_chunk_size_almost_done); break; } unhex_val = unhex[(unsigned char)ch]; if (unhex_val == -1) { if (ch == ';' || ch == ' ') { UPDATE_STATE(s_chunk_parameters); break; } SET_ERRNO(HPE_INVALID_CHUNK_SIZE); goto error; } t = parser->content_length; t *= 16; t += unhex_val; /* Overflow? Test against a conservative limit for simplicity. */ if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) { SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } parser->content_length = t; break; } case s_chunk_parameters: { assert(parser->flags & F_CHUNKED); /* just ignore this shit. TODO check for overflow */ if (ch == CR) { UPDATE_STATE(s_chunk_size_almost_done); break; } break; } case s_chunk_size_almost_done: { assert(parser->flags & F_CHUNKED); STRICT_CHECK(ch != LF); parser->nread = 0; if (parser->content_length == 0) { parser->flags |= F_TRAILING; UPDATE_STATE(s_header_field_start); } else { UPDATE_STATE(s_chunk_data); } CALLBACK_NOTIFY(chunk_header); break; } case s_chunk_data: { uint64_t to_read = MIN(parser->content_length, (uint64_t) ((data + len) - p)); assert(parser->flags & F_CHUNKED); assert(parser->content_length != 0 && parser->content_length != ULLONG_MAX); /* See the explanation in s_body_identity for why the content * length and data pointers are managed this way. */ MARK(body); parser->content_length -= to_read; p += to_read - 1; if (parser->content_length == 0) { UPDATE_STATE(s_chunk_data_almost_done); } break; } case s_chunk_data_almost_done: assert(parser->flags & F_CHUNKED); assert(parser->content_length == 0); STRICT_CHECK(ch != CR); UPDATE_STATE(s_chunk_data_done); CALLBACK_DATA(body); break; case s_chunk_data_done: assert(parser->flags & F_CHUNKED); STRICT_CHECK(ch != LF); parser->nread = 0; UPDATE_STATE(s_chunk_size_start); CALLBACK_NOTIFY(chunk_complete); break; default: assert(0 && "unhandled state"); SET_ERRNO(HPE_INVALID_INTERNAL_STATE); goto error; } } /* Run callbacks for any marks that we have leftover after we ran our of * bytes. There should be at most one of these set, so it's OK to invoke * them in series (unset marks will not result in callbacks). * * We use the NOADVANCE() variety of callbacks here because 'p' has already * overflowed 'data' and this allows us to correct for the off-by-one that * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p' * value that's in-bounds). */ assert(((header_field_mark ? 1 : 0) + (header_value_mark ? 1 : 0) + (url_mark ? 1 : 0) + (body_mark ? 1 : 0) + (status_mark ? 1 : 0)) <= 1); CALLBACK_DATA_NOADVANCE(header_field); CALLBACK_DATA_NOADVANCE(header_value); CALLBACK_DATA_NOADVANCE(url); CALLBACK_DATA_NOADVANCE(body); CALLBACK_DATA_NOADVANCE(status); RETURN(len); error: if (HTTP_PARSER_ERRNO(parser) == HPE_OK) { SET_ERRNO(HPE_UNKNOWN); } RETURN(p - data); } /* Does the parser need to see an EOF to find the end of the message? */ int http_message_needs_eof (const http_parser *parser) { if (parser->type == HTTP_REQUEST) { return 0; } /* See RFC 2616 section 4.4 */ if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ parser->status_code == 204 || /* No Content */ parser->status_code == 304 || /* Not Modified */ parser->flags & F_SKIPBODY) { /* response to a HEAD request */ return 0; } if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) { return 0; } return 1; } int http_should_keep_alive (const http_parser *parser) { if (parser->http_major > 0 && parser->http_minor > 0) { /* HTTP/1.1 */ if (parser->flags & F_CONNECTION_CLOSE) { return 0; } } else { /* HTTP/1.0 or earlier */ if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) { return 0; } } return !http_message_needs_eof(parser); } const char * http_method_str (enum http_method m) { return ELEM_AT(method_strings, m, ""); } void http_parser_init (http_parser *parser, enum http_parser_type t) { void *data = parser->data; /* preserve application data */ memset(parser, 0, sizeof(*parser)); parser->data = data; parser->type = t; parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res)); parser->http_errno = HPE_OK; } void http_parser_settings_init(http_parser_settings *settings) { memset(settings, 0, sizeof(*settings)); } const char * http_errno_name(enum http_errno err) { assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); return http_strerror_tab[err].name; } const char * http_errno_description(enum http_errno err) { assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); return http_strerror_tab[err].description; } static enum http_host_state http_parse_host_char(enum http_host_state s, const char ch) { switch(s) { case s_http_userinfo: case s_http_userinfo_start: if (ch == '@') { return s_http_host_start; } if (IS_USERINFO_CHAR(ch)) { return s_http_userinfo; } break; case s_http_host_start: if (ch == '[') { return s_http_host_v6_start; } if (IS_HOST_CHAR(ch)) { return s_http_host; } break; case s_http_host: if (IS_HOST_CHAR(ch)) { return s_http_host; } /* FALLTHROUGH */ case s_http_host_v6_end: if (ch == ':') { return s_http_host_port_start; } break; case s_http_host_v6: if (ch == ']') { return s_http_host_v6_end; } /* FALLTHROUGH */ case s_http_host_v6_start: if (IS_HEX(ch) || ch == ':' || ch == '.') { return s_http_host_v6; } if (s == s_http_host_v6 && ch == '%') { return s_http_host_v6_zone_start; } break; case s_http_host_v6_zone: if (ch == ']') { return s_http_host_v6_end; } /* FALLTHROUGH */ case s_http_host_v6_zone_start: /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */ if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' || ch == '~') { return s_http_host_v6_zone; } break; case s_http_host_port: case s_http_host_port_start: if (IS_NUM(ch)) { return s_http_host_port; } break; default: break; } return s_http_host_dead; } static int http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { enum http_host_state s; const char *p; size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len; assert(u->field_set & (1 << UF_HOST)); u->field_data[UF_HOST].len = 0; s = found_at ? s_http_userinfo_start : s_http_host_start; for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) { enum http_host_state new_s = http_parse_host_char(s, *p); if (new_s == s_http_host_dead) { return 1; } switch(new_s) { case s_http_host: if (s != s_http_host) { u->field_data[UF_HOST].off = p - buf; } u->field_data[UF_HOST].len++; break; case s_http_host_v6: if (s != s_http_host_v6) { u->field_data[UF_HOST].off = p - buf; } u->field_data[UF_HOST].len++; break; case s_http_host_v6_zone_start: case s_http_host_v6_zone: u->field_data[UF_HOST].len++; break; case s_http_host_port: if (s != s_http_host_port) { u->field_data[UF_PORT].off = p - buf; u->field_data[UF_PORT].len = 0; u->field_set |= (1 << UF_PORT); } u->field_data[UF_PORT].len++; break; case s_http_userinfo: if (s != s_http_userinfo) { u->field_data[UF_USERINFO].off = p - buf ; u->field_data[UF_USERINFO].len = 0; u->field_set |= (1 << UF_USERINFO); } u->field_data[UF_USERINFO].len++; break; default: break; } s = new_s; } /* Make sure we don't end somewhere unexpected */ switch (s) { case s_http_host_start: case s_http_host_v6_start: case s_http_host_v6: case s_http_host_v6_zone_start: case s_http_host_v6_zone: case s_http_host_port_start: case s_http_userinfo: case s_http_userinfo_start: return 1; default: break; } return 0; } void http_parser_url_init(struct http_parser_url *u) { memset(u, 0, sizeof(*u)); } int http_parser_parse_url(const char *buf, size_t buflen, int is_connect, struct http_parser_url *u) { enum state s; const char *p; enum http_parser_url_fields uf, old_uf; int found_at = 0; u->port = u->field_set = 0; s = is_connect ? s_req_server_start : s_req_spaces_before_url; old_uf = UF_MAX; for (p = buf; p < buf + buflen; p++) { s = parse_url_char(s, *p); /* Figure out the next field that we're operating on */ switch (s) { case s_dead: return 1; /* Skip delimeters */ case s_req_schema_slash: case s_req_schema_slash_slash: case s_req_server_start: case s_req_query_string_start: case s_req_fragment_start: continue; case s_req_schema: uf = UF_SCHEMA; break; case s_req_server_with_at: found_at = 1; /* FALLTROUGH */ case s_req_server: uf = UF_HOST; break; case s_req_path: uf = UF_PATH; break; case s_req_query_string: uf = UF_QUERY; break; case s_req_fragment: uf = UF_FRAGMENT; break; default: assert(!"Unexpected state"); return 1; } /* Nothing's changed; soldier on */ if (uf == old_uf) { u->field_data[uf].len++; continue; } u->field_data[uf].off = p - buf; u->field_data[uf].len = 1; u->field_set |= (1 << uf); old_uf = uf; } /* host must be present if there is a schema */ /* parsing http:///toto will fail */ if ((u->field_set & (1 << UF_SCHEMA)) && (u->field_set & (1 << UF_HOST)) == 0) { return 1; } if (u->field_set & (1 << UF_HOST)) { if (http_parse_host(buf, u, found_at) != 0) { return 1; } } /* CONNECT requests can only contain "hostname:port" */ if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) { return 1; } if (u->field_set & (1 << UF_PORT)) { /* Don't bother with endp; we've already validated the string */ unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10); /* Ports have a max value of 2^16 */ if (v > 0xffff) { return 1; } u->port = (uint16_t) v; } return 0; } void http_parser_pause(http_parser *parser, int paused) { /* Users should only be pausing/unpausing a parser that is not in an error * state. In non-debug builds, there's not much that we can do about this * other than ignore it. */ if (HTTP_PARSER_ERRNO(parser) == HPE_OK || HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) { SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK); } else { assert(0 && "Attempting to pause parser in error state"); } } int http_body_is_final(const struct http_parser *parser) { return parser->state == s_message_done; } unsigned long http_parser_version(void) { return HTTP_PARSER_VERSION_MAJOR * 0x10000 | HTTP_PARSER_VERSION_MINOR * 0x00100 | HTTP_PARSER_VERSION_PATCH * 0x00001; } measurement-kit-0.7.1/src/libmeasurement_kit/ext/sole.cpp000066400000000000000000000036211315356162600235630ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. // ============================================================= // Derivative work of r-lyeh/sole@c61c49f10d. // See NOTICE for original license. #include #include #include #include namespace mk { namespace sole { std::string uuid::str() { std::stringstream ss; ss << std::hex << std::nouppercase << std::setfill('0'); uint32_t a = (ab >> 32); uint32_t b = (ab & 0xFFFFFFFF); uint32_t c = (cd >> 32); uint32_t d = (cd & 0xFFFFFFFF); ss << std::setw(8) << (a) << '-'; ss << std::setw(4) << (b >> 16) << '-'; ss << std::setw(4) << (b & 0xFFFF) << '-'; ss << std::setw(4) << (c >> 16) << '-'; ss << std::setw(4) << (c & 0xFFFF); ss << std::setw(8) << d; return ss.str(); } uuid uuid4() { std::random_device rd; std::uniform_int_distribution dist(0, (uint64_t)(~0)); uuid my; my.ab = dist(rd); my.cd = dist(rd); /* The version 4 UUID is meant for generating UUIDs from truly-random or pseudo-random numbers. The algorithm is as follows: o Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the 4-bit version number from Section 4.1.3. o Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively. o Set all the other bits to randomly (or pseudo-randomly) chosen values. See . */ my.ab = (my.ab & 0xFFFFFFFFFFFF0FFFULL) | 0x0000000000004000ULL; my.cd = (my.cd & 0x3FFFFFFFFFFFFFFFULL) | 0x8000000000000000ULL; return my; } } // namespace sole } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ext/tls_verify.c000066400000000000000000000160061315356162600244500ustar00rootroot00000000000000/* $OpenBSD: tls_verify.c,v 1.19 2017/04/10 17:11:13 jsing Exp $ */ /* * Part of measurement-kit . * Measurement-kit is free software under the BSD license. See AUTHORS * and LICENSE for more information on the copying conditions. * ===================================================================== * Based on LibreSSL's tls_verify.c with small local modifications. * * Portions Copyright (c) 2014 Jeremie Courreges-Anglas * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include "private/ext/tls_internal.h" static int tls_match_name(const char *cert_name, const char *name) { const char *cert_domain, *domain, *next_dot; if (strcasecmp(cert_name, name) == 0) return 0; /* Wildcard match? */ if (cert_name[0] == '*') { /* * Valid wildcards: * - "*.domain.tld" * - "*.sub.domain.tld" * - etc. * Reject "*.tld". * No attempt to prevent the use of eg. "*.co.uk". */ cert_domain = &cert_name[1]; /* Disallow "*" */ if (cert_domain[0] == '\0') return -1; /* Disallow "*foo" */ if (cert_domain[0] != '.') return -1; /* Disallow "*.." */ if (cert_domain[1] == '.') return -1; next_dot = strchr(&cert_domain[1], '.'); /* Disallow "*.bar" */ if (next_dot == NULL) return -1; /* Disallow "*.bar.." */ if (next_dot[1] == '.') return -1; domain = strchr(name, '.'); /* No wildcard match against a name with no host part. */ if (name[0] == '.') return -1; /* No wildcard match against a name with no domain part. */ if (domain == NULL || strlen(domain) == 1) return -1; if (strcasecmp(cert_domain, domain) == 0) return 0; } return -1; } /* * See RFC 5280 section 4.2.1.6 for SubjectAltName details. * alt_match is set to 1 if a matching alternate name is found. * alt_exists is set to 1 if any known alternate name exists in the certificate. */ static int tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, int *alt_match, int *alt_exists) { STACK_OF(GENERAL_NAME) *altname_stack = NULL; union tls_addr addrbuf; int addrlen, type; int count, i; int rv = 0; *alt_match = 0; *alt_exists = 0; altname_stack = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); if (altname_stack == NULL) return 0; if (inet_pton(AF_INET, name, &addrbuf) == 1) { type = GEN_IPADD; addrlen = 4; } else if (inet_pton(AF_INET6, name, &addrbuf) == 1) { type = GEN_IPADD; addrlen = 16; } else { type = GEN_DNS; addrlen = 0; } count = sk_GENERAL_NAME_num(altname_stack); for (i = 0; i < count; i++) { GENERAL_NAME *altname; altname = sk_GENERAL_NAME_value(altname_stack, i); if (altname->type == GEN_DNS || altname->type == GEN_IPADD) *alt_exists = 1; if (altname->type != type) continue; if (type == GEN_DNS) { unsigned char *data; int format, len; format = ASN1_STRING_type(altname->d.dNSName); if (format == V_ASN1_IA5STRING) { data = ASN1_STRING_data(altname->d.dNSName); len = ASN1_STRING_length(altname->d.dNSName); if (len < 0 || (size_t)len != strlen((char *)data)) { tls_set_errorx(ctx, "error verifying name '%s': " "NUL byte in subjectAltName, " "probably a malicious certificate", name); rv = -1; break; } /* * Per RFC 5280 section 4.2.1.6: * " " is a legal domain name, but that * dNSName must be rejected. */ if (strcmp((char *)data, " ") == 0) { tls_set_errorx(ctx, "error verifying name '%s': " "a dNSName of \" \" must not be " "used", name); rv = -1; break; } if (tls_match_name((char *)data, name) == 0) { *alt_match = 1; break; } } else { #ifdef DEBUG fprintf(stdout, "%s: unhandled subjectAltName " "dNSName encoding (%d)\n", getprogname(), format); #endif } } else if (type == GEN_IPADD) { unsigned char *data; int datalen; datalen = ASN1_STRING_length(altname->d.iPAddress); data = ASN1_STRING_data(altname->d.iPAddress); if (datalen < 0) { tls_set_errorx(ctx, "Unexpected negative length for an " "IP address: %d", datalen); rv = -1; break; } /* * Per RFC 5280 section 4.2.1.6: * IPv4 must use 4 octets and IPv6 must use 16 octets. */ if (datalen == addrlen && memcmp(data, &addrbuf, addrlen) == 0) { *alt_match = 1; break; } } } sk_GENERAL_NAME_pop_free(altname_stack, GENERAL_NAME_free); return rv; } static int tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, int *cn_match) { X509_NAME *subject_name; char *common_name = NULL; union tls_addr addrbuf; int common_name_len; int rv = 0; *cn_match = 0; subject_name = X509_get_subject_name(cert); if (subject_name == NULL) goto out; common_name_len = X509_NAME_get_text_by_NID(subject_name, NID_commonName, NULL, 0); if (common_name_len < 0) goto out; common_name = calloc(common_name_len + 1, 1); if (common_name == NULL) goto out; X509_NAME_get_text_by_NID(subject_name, NID_commonName, common_name, common_name_len + 1); /* NUL bytes in CN? */ if (common_name_len < 0 || (size_t)common_name_len != strlen(common_name)) { tls_set_errorx(ctx, "error verifying name '%s': " "NUL byte in Common Name field, " "probably a malicious certificate", name); rv = -1; goto out; } /* * We don't want to attempt wildcard matching against IP addresses, * so perform a simple comparison here. */ if (inet_pton(AF_INET, name, &addrbuf) == 1 || inet_pton(AF_INET6, name, &addrbuf) == 1) { if (strcmp(common_name, name) == 0) *cn_match = 1; goto out; } if (tls_match_name(common_name, name) == 0) *cn_match = 1; out: free(common_name); return rv; } int tls_check_name(struct tls *ctx, X509 *cert, const char *name, int *match) { int alt_exists; *match = 0; if (tls_check_subject_altname(ctx, cert, name, match, &alt_exists) == -1) return -1; /* * As per RFC 6125 section 6.4.4, if any known alternate name existed * in the certificate, we do not attempt to match on the CN. */ if (*match || alt_exists) return 0; return tls_check_common_name(ctx, cert, name, match); } measurement-kit-0.7.1/src/libmeasurement_kit/http/000077500000000000000000000000001315356162600222725ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/http/parse_url.cpp000066400000000000000000000046751315356162600250060ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ext/http_parser.h" #include namespace mk { namespace http { Url parse_url(std::string url) { Url retval; http_parser_url url_parser; http_parser_url_init(&url_parser); if (http_parser_parse_url(url.data(), url.size(), 0, &url_parser) != 0) { throw UrlParserError(); } if ((url_parser.field_set & (1 << UF_SCHEMA)) == 0) { throw MissingUrlSchemaError(); } if ((url_parser.field_set & (1 << UF_HOST)) == 0) { throw MissingUrlHostError(); } retval.schema = url.substr(url_parser.field_data[UF_SCHEMA].off, url_parser.field_data[UF_SCHEMA].len); retval.address = url.substr(url_parser.field_data[UF_HOST].off, url_parser.field_data[UF_HOST].len); if ((url_parser.field_set & (1 << UF_PORT)) != 0) { retval.port = url_parser.port; } else if (retval.schema == "https") { retval.port = 443; } else { retval.port = 80; /* redundant; but I want to cover all cases */ } if ((url_parser.field_set & (1 << UF_PATH)) != 0) { retval.path = url.substr(url_parser.field_data[UF_PATH].off, url_parser.field_data[UF_PATH].len); } else { retval.path = "/"; } retval.pathquery = retval.path; if ((url_parser.field_set & (1 << UF_QUERY)) != 0) { retval.query = url.substr(url_parser.field_data[UF_QUERY].off, url_parser.field_data[UF_QUERY].len); retval.pathquery += "?" + retval.query; } return retval; } ErrorOr parse_url_noexcept(std::string url) { try { return parse_url(url); } catch (Error &error) { return error; } } std::string Url::str() { std::stringstream sst; sst << schema; sst << "://"; if (net::is_ipv6_addr(address)) { sst << "["; } sst << address; if (net::is_ipv6_addr(address)) { sst << "]"; } if ((schema == "http" and port != 80) or (schema == "https" and port != 443)) { sst << ":"; sst << port; } if (pathquery != "") { sst << pathquery; } else { sst << "/"; } return sst.str(); } } // namespace http } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/http/request.cpp000066400000000000000000000305711315356162600244740ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/http/request_impl.hpp" #include "private/common/utils.hpp" namespace mk { namespace http { using namespace mk::net; /* _ ___| | __ _ ___ ___ / __| |/ _` / __/ __| | (__| | (_| \__ \__ \ \___|_|\__,_|___/___/ */ /*static*/ ErrorOr> Request::make(Settings settings, Headers headers, std::string body) { Var request(new Request); Error error = request->init(settings, headers, body); // Note: the following cannot be simplified using short circuit // evaluation because two different types are returned if (error) { return error; } return request; } Error Request::init(Settings settings, Headers hdrs, std::string bd) { headers = hdrs; body = bd; // TODO: the following check and the URL parsing are duplicated also // in the code that connect()s; we should not duplicate code if (settings.find("http/url") == settings.end()) { return MissingUrlError(); } ErrorOr maybe_url = parse_url_noexcept(settings.at("http/url")); if (!maybe_url) { return maybe_url.as_error(); } url = *maybe_url; protocol = settings.get("http/http_version", std::string("HTTP/1.1")); method = settings.get("http/method", std::string("GET")); // XXX should we really distinguish between path and query here? url_path = settings.get("http/path", std::string("")); if (url_path != "" && url_path[0] != '/') { url_path = "/" + url_path; } return NoError(); } void Request::serialize(net::Buffer &buff, Var logger) { buff << method << " "; if (url_path != "") { buff << url_path; } else { buff << url.pathquery; } buff << " " << protocol << "\r\n"; for (auto kv : headers) { buff << kv.first << ": " << kv.second << "\r\n"; } // if the host: header is passed explicitly, // don't construct it again here. if (headers.find("host") == headers.end()) { buff << "Host: " << url.address; if ((url.schema == "http" and url.port != 80) or (url.schema == "https" and url.port != 443)) { buff << ":"; buff << std::to_string(url.port); } buff << "\r\n"; } if (body != "") { buff << "Content-Length: " << std::to_string(body.length()) << "\r\n"; } buff << "\r\n"; for (auto s: mk::split(buff.peek(), "\r\n")) { logger->debug("> %s", s.c_str()); } if (body != "") { buff << body; } } /* _ _ | | ___ __ _(_) ___ | |/ _ \ / _` | |/ __| | | (_) | (_| | | (__ |_|\___/ \__, |_|\___| |___/ */ void request_connect(Settings settings, Callback> txp, Var reactor, Var logger) { request_connect_impl(settings, txp, reactor, logger); } void request_send(Var txp, Settings settings, Headers headers, std::string body, Callback> callback) { request_maybe_send(Request::make(settings, headers, body), txp, callback); } void request_maybe_send(ErrorOr> request, Var txp, Callback> callback) { if (!request) { callback(request.as_error(), nullptr); return; } Buffer buff; (*request)->serialize(buff); net::write(txp, buff, [=](Error err) { callback(err, *request); }); } void request_recv_response(Var txp, Callback> cb, Var reactor, Var logger) { Var parser(new ResponseParserNg); Var response(new Response); Var prevent_emit(new bool(false)); Var valid_response(new bool(false)); // Note: any parser error at this point is an exception catched by the // connection code and routed to the error handler function below txp->on_data([=](Buffer data) { parser->feed(data); }); parser->on_response([=](Response r) { *response = r; *valid_response = true; }); // TODO: here we should honour the `ignore_body` setting parser->on_body([=](std::string s) { response->body += s; }); // TODO: we should improve the parser such that the transport forwards the // "error" event to it and then the parser does the right thing, so that the // code becomes less "twisted" here. // // XXX actually trying to do that could make things worse as we have // seen in #690; we should refactor this code with care. parser->on_end([=]() { if (*prevent_emit == true) { return; } txp->emit_error(NoError()); }); txp->on_error([=](Error err) { logger->debug("Received error %s on connection", err.as_ooni_error().c_str()); if (err == EofError() && *valid_response == true) { // Calling parser->on_eof() could trigger parser->on_end() and // we don't want this function to call ->emit_error() *prevent_emit = true; // Assume there was no error. The parser will tell us if that // is true (it was in final state) or false. err = NoError(); try { logger->debug("Now passing EOF to parser"); parser->eof(); } catch (Error &second_error) { logger->warn("Parsing error at EOF: %d", second_error.code); err = second_error; // FALLTHRU } } logger->debug("Now reacting to delivered error %d", err.code); txp->on_error(nullptr); txp->on_data(nullptr); reactor->call_soon([=]() { logger->log(MK_LOG_DEBUG2, "request_recv_response: end of closure"); cb(err, response); }); }); } void request_sendrecv(Var txp, Settings settings, Headers headers, std::string body, Callback> callback, Var reactor, Var logger) { request_maybe_sendrecv(Request::make(settings, headers, body), txp, callback, reactor, logger); } void request_maybe_sendrecv(ErrorOr> request, Var txp, Callback> callback, Var reactor, Var logger) { request_maybe_send(request, txp, [=](Error error, Var request) { if (error) { Var response{new Response}; response->request = request; callback(error, response); return; } request_recv_response(txp, [=](Error error, Var response) { if (error) { callback(error, response); return; } response->request = request; callback(error, response); }, reactor, logger); }); } ErrorOr redirect(const Url &orig_url, const std::string &location) { std::stringstream ss; /* * Note: RFC 1808 Sect. 2.2 is clear that "//" * MUST be treated differently than "/". */ if (mk::startswith(location, "//")) { ss << orig_url.schema << ":" << location; } else if (mk::startswith(location, "/")) { Url new_url = orig_url; new_url.pathquery = location; ss << new_url.str(); } else if (mk::startswith(location, "http://") || mk::startswith(location, "https://")) { ss << location; } else { /* * Assume it's a relative redirect. I seem to recall this should * not happen, but it really looks like it happens. */ Url new_url = orig_url; if (!mk::endswith(new_url.path, "/")) { new_url.path += "/"; } /* * Note: clearing the query because a new query may be included in * location and keeping also the old query would break things. */ new_url.path += location; new_url.query = ""; // TODO: can we make `pathquery` a property? new_url.pathquery = new_url.path; ss << new_url.str(); } return parse_url_noexcept(ss.str()); } void request(Settings settings, Headers headers, std::string body, Callback> callback, Var reactor, Var logger, Var previous, int num_redirs) { dump_settings(settings, "http::request", logger); ErrorOr max_redirects = settings.get_noexcept( "http/max_redirects", 0 ); if (!max_redirects) { callback(InvalidMaxRedirectsError(max_redirects.as_error()), nullptr); return; } request_connect( settings, [=](Error err, Var txp) { if (err) { callback(err, nullptr); return; } request_sendrecv( txp, settings, headers, body, [=](Error error, Var response) { txp->close([=]() { if (error) { callback(error, response); return; } response->previous = previous; if (response->status_code / 100 == 3 and *max_redirects > 0) { logger->debug("following redirect..."); std::string loc = response->headers["Location"]; if (loc == "") { callback(EmptyLocationError(), response); return; } ErrorOr url = redirect( response->request->url, loc ); if (!url) { callback(InvalidRedirectUrlError( url.as_error()), response); return; } Settings new_settings = settings; new_settings["http/url"] = url->str(); logger->debug("redir url: %s", url->str().c_str()); if (num_redirs >= *max_redirects) { callback(TooManyRedirectsError(), response); return; } reactor->call_soon([=]() { request(new_settings, headers, body, callback, reactor, logger, response, num_redirs + 1); }); return; } callback(NoError(), response); }); }, reactor, logger); }, reactor, logger); } bool HeadersComparator::operator() ( const std::string &l, const std::string &r) const { return strcasecmp(l.c_str(), r.c_str()) < 0; } void request_json_string( std::string method, std::string url, std::string data, http::Headers headers, Callback, nlohmann::json> cb, Settings settings, Var reactor, Var logger) { request_json_string_impl(method, url, data, headers, cb, settings, reactor, logger); } void request_json_no_body( std::string method, std::string url, http::Headers headers, Callback, nlohmann::json> cb, Settings settings, Var reactor, Var logger) { request_json_string(method, url, "", headers, cb, settings, reactor, logger); } void request_json_object( std::string method, std::string url, nlohmann::json jdata, http::Headers headers, Callback, nlohmann::json> cb, Settings settings, Var reactor, Var logger) { request_json_string(method, url, jdata.dump(), headers, cb, settings, reactor, logger); } } // namespace http } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/http/response_parser.cpp000066400000000000000000000036421315356162600262150ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/http/response_parser.hpp" #include "private/ext/http_parser.h" #include #include extern "C" { using namespace mk::http; static int cb_message_begin(http_parser *p) { return static_cast(p->data)->do_message_begin_(); } static int cb_status(http_parser *p, const char *s, size_t n) { return static_cast(p->data)->do_status_(s, n); } static int cb_header_field(http_parser *p, const char *s, size_t n) { return static_cast(p->data)->do_header_field_(s, n); } static int cb_header_value(http_parser *p, const char *s, size_t n) { return static_cast(p->data)->do_header_value_(s, n); } static int cb_headers_complete(http_parser *p) { return static_cast(p->data)->do_headers_complete_(); } static int cb_body(http_parser *p, const char *s, size_t n) { return static_cast(p->data)->do_body_(s, n); } static int cb_message_complete(http_parser *p) { return static_cast(p->data)->do_message_complete_(); } } // extern "C" namespace mk { namespace http { ResponseParserNg::ResponseParserNg(Var logger) { logger_ = logger; http_parser_settings_init(&settings_); settings_.on_message_begin = cb_message_begin; settings_.on_status = cb_status; settings_.on_header_field = cb_header_field; settings_.on_header_value = cb_header_value; settings_.on_headers_complete = cb_headers_complete; settings_.on_body = cb_body; settings_.on_message_complete = cb_message_complete; http_parser_init(&parser_, HTTP_RESPONSE); parser_.data = this; /* Which makes this object non-movable */ } } // namespace http } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/libevent/000077500000000000000000000000001315356162600231235ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/libevent/connection.cpp000066400000000000000000000076711315356162600260010ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/libevent/connection.hpp" #include "private/net/utils.hpp" #include #include #include #include #include #include #include extern "C" { static void handle_libevent_read(bufferevent *, void *opaque) { static_cast(opaque)->handle_read_(); } static void handle_libevent_write(bufferevent *, void *opaque) { static_cast(opaque)->handle_write_(); } static void handle_libevent_event(bufferevent *, short what, void *opaque) { static_cast(opaque)->handle_event_(what); } } // extern "C" namespace mk { namespace libevent { using namespace mk::net; void Connection::handle_read_() { Buffer buff(bufferevent_get_input(bev)); try { emit_data(buff); } catch (Error &error) { emit_error(error); return; } if (suppressed_eof) { suppressed_eof = false; logger->debug("Deliver previously suppressed EOF"); emit_error(EofError()); return; } } void Connection::handle_write_() { try { emit_flush(); } catch (Error &error) { emit_error(error); } } static std::string map_bufferevent_event(short what) { std::stringstream ss; ss << ((what & BEV_EVENT_EOF) ? "Z" : "z") << ((what & BEV_EVENT_TIMEOUT) ? "T" : "t") << ((what & BEV_EVENT_ERROR) ? "F" : "f") << ((what & BEV_EVENT_READING) ? "R" : "r") << ((what & BEV_EVENT_WRITING) ? "W" : "w"); return ss.str(); } void Connection::handle_event_(short what) { logger->debug("connection: got bufferevent event: %s", map_bufferevent_event(what).c_str()); if ((what & BEV_EVENT_EOF) != 0) { auto input = bufferevent_get_input(bev); if (evbuffer_get_length(input) > 0) { logger->debug("Suppress EOF with data lingering in input buffer"); suppressed_eof = true; return; } emit_error(EofError()); return; } if ((what & BEV_EVENT_TIMEOUT) != 0) { emit_error(TimeoutError()); return; } Error sys_error = net::map_errno(errno); if (sys_error == NoError()) { unsigned long openssl_error; char buff[128]; while ((openssl_error = bufferevent_get_openssl_error(bev)) != 0) { if (sys_error == NoError()) { sys_error = SslError(); } ERR_error_string_n(openssl_error, buff, sizeof(buff)); sys_error.add_child_error(SslError(buff)); } if (sys_error != SslError()) { /* * This is the case of the SSL dirty shutdown. The connection * was not closed cleanly from the other end and in theory this * could also be the effect of an attack. */ logger->warn("libevent has detected an SSL dirty shutdown"); sys_error = SslDirtyShutdownError(); } } logger->warn("Got error: %s", sys_error.as_ooni_error().c_str()); emit_error(sys_error); } Connection::Connection(bufferevent *buffev, Var reactor, Var logger) : EmitterBase(reactor, logger) { this->bev = buffev; // The following makes this non copyable and non movable. bufferevent_setcb(this->bev, handle_libevent_read, handle_libevent_write, handle_libevent_event, this); } void Connection::shutdown() { if (shutdown_called) { return; // Just for extra safety } shutdown_called = true; bufferevent_setcb(bev, nullptr, nullptr, nullptr, nullptr); reactor->call_soon([=]() { this->self = nullptr; }); } } // namespace libevent } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/libevent/dns.cpp000066400000000000000000000015451315356162600244200ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/libevent/dns_impl.hpp" namespace mk { namespace libevent { extern "C" { void handle_resolve(int code, char type, int count, int ttl, void *addresses, void *opaque) { auto context = static_cast(opaque); dns_callback(code, type, count, ttl, addresses, context); } } void query( dns::QueryClass dns_class, dns::QueryType dns_type, std::string name, Callback> cb, Settings settings, Var reactor, Var logger) { query_impl(dns_class, dns_type, name, cb, settings, reactor, logger); } } // namespace libevent } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/libevent/dns_error.cpp000066400000000000000000000046561315356162600256370ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/libevent/dns.hpp" #include namespace mk { namespace libevent { using namespace mk::dns; Error dns_error(int code) { Error err; // // Here we map evdns error codes to specific Errors. // // We start with errors specified in RFC 1035 (see also event2/dns.h). // if (code == DNS_ERR_NONE) { err = NoError(); } else if (code == DNS_ERR_FORMAT) { // The name server was unable to interpret the query err = FormatError(); } else if (code == DNS_ERR_SERVERFAILED) { // The name server was unable to process this query due to a // problem with the name server err = ServerFailedError(); } else if (code == DNS_ERR_NOTEXIST) { // The domain name does not exist err = NotExistError(); } else if (code == DNS_ERR_NOTIMPL) { // The name server does not support the requested kind of query err = dns::NotImplementedError(); } else if (code == DNS_ERR_REFUSED) { // The name server refuses to perform the specified operation // for policy reasons err = RefusedError(); // // The following are evdns specific errors // } else if (code == DNS_ERR_TRUNCATED) { // The reply was truncated or ill-formatted err = TruncatedError(); } else if (code == DNS_ERR_UNKNOWN) { // An unknown error occurred err = UnknownError(); } else if (code == DNS_ERR_TIMEOUT) { // Communication with the server timed out err = TimeoutError(); } else if (code == DNS_ERR_SHUTDOWN) { // The request was canceled because the DNS subsystem was shut down. err = ShutdownError(); } else if (code == DNS_ERR_CANCEL) { // The request was canceled via a call to evdns_cancel_request err = CancelError(); } else if (code == DNS_ERR_NODATA) { // There were no answers and no error condition in the DNS packet. // This can happen when you ask for an address that exists, but // a record type that doesn't. err = NoDataError(); } else { // Safery net - should really not happen err = GenericError(); } return err; } } // namespace libevent } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/libevent/listen.cpp000066400000000000000000000007741315356162600251350ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/libevent/listen.hpp" using namespace mk; using namespace mk::libevent; extern "C" { void mk_listener_cb( evconnlistener *, evutil_socket_t s, sockaddr *, int, void *o) { (*static_cast(o))(s); // Note: persistent callback, would be stupid to `delete` it! } } // extern "C" measurement-kit-0.7.1/src/libmeasurement_kit/libevent/poller.cpp000066400000000000000000000045321315356162600251300ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/libevent/poller_impl.hpp" #include #include // Using `extern "C"` for C callbacks is recommended by C++ FAQs. // See . extern "C" { void mk_call_later_cb(evutil_socket_t, short, void *p) { auto cbp = static_cast *>(p); (*cbp)(); delete cbp; } void mk_loop_periodic_cb(evutil_socket_t, short, void *ptr) { mk::libevent::Poller *poller = static_cast(ptr); poller->handle_periodic_(); } void mk_pollfd_cb(evutil_socket_t, short evflags, void *p) { auto cbp = static_cast *>(p); mk::Error err = mk::NoError(); short flags = 0; assert((evflags & (EV_TIMEOUT|EV_READ|EV_WRITE)) != 0); if ((evflags & EV_TIMEOUT) != 0) { err = mk::net::TimeoutError(); } if ((evflags & EV_READ) != 0) { flags |= MK_POLLIN; } if ((evflags & EV_WRITE) != 0) { flags |= MK_POLLOUT; } (*cbp)(err, flags); delete cbp; } } // extern "C" namespace mk { namespace libevent { Poller::Poller() { base_ = poller_alloc_evbase(); } Poller::~Poller() {} event_base *Poller::get_event_base() { return base_.get(); } void Poller::call_soon(Callback<> &&cb) { call_later(0.0, std::move(cb)); } void Poller::call_later(double timeo, Callback<> &&cb) { poller_call_later(base_, timeo, std::move(cb)); } void Poller::run() { poller_loop(base_, this); } void Poller::loop_once() { poller_loop_once(base_); } void Poller::stop() { poller_break_loop(base_); } void Poller::pollfd( socket_t sockfd, short events, double timeout, Callback &&callback) { poller_pollfd(base_, sockfd, events, std::move(callback), timeout); } void Poller::handle_periodic_() { if (periodic_cb_) { // Protection against the callback calling on_periodic_() // TODO: check whether this is needed (delegate should cope with that) auto fn = periodic_cb_; fn(this); } } void Poller::on_periodic_(Callback cb) { periodic_cb_ = cb; } } // namespace libevent } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/mlabns/000077500000000000000000000000001315356162600225675ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/mlabns/mlabns.cpp000066400000000000000000000010421315356162600245440ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/mlabns/mlabns_impl.hpp" namespace mk { namespace mlabns { ErrorOr as_query(Settings &settings); void query(std::string tool, Callback callback, Settings settings, Var reactor, Var logger) { query_impl(tool, callback, settings, reactor, logger); } } // namespace mlabns } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ndt/000077500000000000000000000000001315356162600221005ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/ndt/messages.cpp000066400000000000000000000051351315356162600244170ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ndt/messages_impl.hpp" namespace mk { namespace ndt { namespace messages { void read_ll(Var ctx, mk::Callback callback, Var reactor) { read_ll_impl(ctx, callback, reactor); } void read_json(Var ctx, Callback callback, Var reactor) { read_json_impl(ctx, callback, reactor); } void read_msg(Var ctx, Callback cb, Var reactor) { read_msg_impl(ctx, cb, reactor); } ErrorOr format_msg_extended_login(unsigned char tests) { return format_any(MSG_EXTENDED_LOGIN, json{ {"msg", MSG_NDT_VERSION}, {"tests", lexical_cast((int)tests)}, }); } ErrorOr format_test_msg(std::string s) { return format_any(TEST_MSG, json{ {"msg", s}, }); } ErrorOr format_msg_waiting() { return format_any(MSG_WAITING, json{ {"msg", ""}, }); } void write(Var ctx, Buffer buff, Callback cb) { std::string s = buff.peek(); ctx->logger->debug("> [%zu]: (%d) %s", s.length(), s.c_str()[0], s.substr(3).c_str()); net::write(ctx->txp, buff, cb); } void write_noasync(Var ctx, Buffer buff) { std::string s = buff.peek(); ctx->logger->debug("> [%zu]: (%d) %s", s.length(), s.c_str()[0], s.substr(3).c_str()); ctx->txp->write(buff); } Error add_to_report(Var entry, std::string key, std::string item) { std::list list = split(item, ":"); if (list.size() != 2) { return GenericError(); /* XXX use more specific error */ } // XXX: We should make sure that we remove leading and trailing whitespaces std::string variable = list.front(); std::string value = list.back(); ErrorOr as_long = lexical_cast_noexcept(value); if (!!as_long) { (*entry)[key][variable] = *as_long; return NoError(); } ErrorOr as_double = lexical_cast_noexcept(value); if (!!as_double) { (*entry)[key][variable] = *as_double; return NoError(); } (*entry)[key][variable] = value; return NoError(); } } // namespace messages } // namespace ndt } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ndt/protocol.cpp000066400000000000000000000026241315356162600244510ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ndt/protocol_impl.hpp" namespace mk { namespace ndt { namespace protocol { void connect(Var ctx, Callback callback) { connect_impl(ctx, callback); } void send_extended_login(Var ctx, Callback callback) { send_extended_login_impl(ctx, callback); } void recv_and_ignore_kickoff(Var ctx, Callback callback) { recv_and_ignore_kickoff_impl(ctx, callback); } void wait_in_queue(Var ctx, Callback callback) { wait_in_queue_impl(ctx, callback); } void recv_version(Var ctx, Callback callback) { recv_version_impl(ctx, callback); } void recv_tests_id(Var ctx, Callback callback) { recv_tests_id_impl(ctx, callback); } void run_tests(Var ctx, Callback callback) { run_tests_impl(ctx, callback); } void recv_results_and_logout(Var ctx, Callback callback) { recv_results_and_logout_impl(ctx, callback); } void wait_close(Var ctx, Callback callback) { wait_close_impl(ctx, callback); } void disconnect_and_callback(Var ctx, Error err) { disconnect_and_callback_impl(ctx, err); } } // namespace protocol } // namespace ndt } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ndt/run.cpp000066400000000000000000000021771315356162600234170ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ndt/run_impl.hpp" namespace mk { namespace ndt { void run_with_specific_server(Var entry, std::string address, int port, Callback callback, Settings settings, Var reactor, Var logger) { run_with_specific_server_impl< protocol::connect, protocol::send_extended_login, protocol::recv_and_ignore_kickoff, protocol::wait_in_queue, protocol::recv_version, protocol::recv_tests_id, protocol::run_tests, protocol::recv_results_and_logout, protocol::wait_close, protocol::disconnect_and_callback>(entry, address, port, callback, settings, reactor, logger); } void run(Var entry, Callback callback, Settings settings, Var reactor, Var logger) { run_impl(entry, callback, settings, reactor, logger); } } // namespace mk } // namespace ndt measurement-kit-0.7.1/src/libmeasurement_kit/ndt/test_c2s.cpp000066400000000000000000000014031315356162600243300ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ndt/test_c2s_impl.hpp" namespace mk { namespace ndt { namespace test_c2s { void coroutine(Var e, std::string address, int port, double runtime, Callback> cb, double timeout, Settings settings, Var reactor, Var logger) { coroutine_impl(e, address, port, runtime, cb, timeout, settings, reactor, logger); } void run(Var ctx, Callback callback) { run_impl(ctx, callback); } } // namespace test_c2s } // namespace ndt } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ndt/test_meta.cpp000066400000000000000000000006501315356162600245720ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ndt/test_meta_impl.hpp" namespace mk { namespace ndt { namespace test_meta { void run(Var ctx, Callback callback) { run_impl(ctx, callback); } } // namespace test_meta } // namespace mk } // namespace ndt measurement-kit-0.7.1/src/libmeasurement_kit/ndt/test_s2c.cpp000066400000000000000000000017211315356162600243330ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ndt/test_s2c_impl.hpp" namespace mk { namespace ndt { namespace test_s2c { using namespace mk::report; void coroutine(Var report_entry, std::string address, Params params, Callback> cb, double timeout, Settings settings, Var reactor, Var logger) { coroutine_impl(report_entry, address, params, cb, timeout, settings, reactor, logger); } void finalizing_test(Var ctx, Var cur_entry, Callback callback) { finalizing_test_impl(ctx, cur_entry, callback); } void run(Var ctx, Callback callback) { run_impl(ctx, callback); } } // namespace test_s2c } // namespace ndt } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ndt/utils.cpp000066400000000000000000000154761315356162600237610ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ndt/utils.hpp" namespace mk { namespace ndt { namespace utils { /* * Note: in the following function and other functions below we're going to * take advantage of the fact that `Entry` is a JSON type, thus we are going * to return, e.g., `nullptr` to indicate error and otherwise a double. * * This behavior is correct C++ because the constructor of `Entry` can take * in input any valid JSON (`null`, numbers, strings, lists, objects). */ report::Entry compute_ping(report::Entry &test_s2c, Var logger) { try { // Note: do static cast to make sure it's convertible to a double return static_cast(test_s2c["web100_data"]["MinRTT"]); } catch (const std::exception &w) { logger->warn("Cannot access Web100 data: %s", w.what()); /* Fallthrough to next method of computing RTT */ } std::vector rtts; try { // XXX Needed to add temp variable because otherwise it did not compile std::vector temp = test_s2c["connect_times"]; rtts = temp; } catch (const std::exception &) { logger->warn("Cannot access connect times"); /* Fallthrough to the following check that will fail */ ; } if (rtts.size() <= 0) { logger->warn("Did not find any reliable way to compute RTT"); return nullptr; /* We cannot compute the RTT */ } double sum = 0.0; for (auto &rtt: rtts) { sum += rtt * 1000.0 /* To milliseconds! */; } return sum / rtts.size(); /* Division by zero excluded above */ } report::Entry compute_speed(report::Entry &sender_or_receiver_data, const char *speed_type, Var logger) { /* * This algorithm computes the speed in a way that is similar to the one * implemented by OOKLA, as documented here: * * http://www.ookla.com/support/a21110547/what-is-the-test-flow-and-methodology-for-the-speedtest */ try { std::vector speeds; for (auto &x: sender_or_receiver_data) { speeds.push_back(x[1]); } std::sort(speeds.begin(), speeds.end()); std::vector good_speeds( // Note: going beyond vector limits would raise // a std::length_error exception speeds.begin() + 6, speeds.end() - 2 ); double sum = 0.0; for (auto &x : good_speeds) { sum += x; }; if (good_speeds.size() <= 0) { logger->warn("The vector of good speeds is empty"); return nullptr; } return sum / good_speeds.size(); } catch (const std::exception &x) { logger->warn("Cannot compute %s speed", speed_type); // FALLTHROUGH } return nullptr; } report::Entry compute_simple_stats(report::Entry &entry, Var logger) { report::Entry test_s2c; report::Entry test_c2s; report::Entry simple_stats; try { /* * XXX The following code assumes there is just one entry, which is * really what usually happens. But there are ways to run the test * and have multiple S2C entries (e.g., pass both `-T download` and * `-T download_ext` to `./measurement_kit`). */ if (entry["test_s2c"].size() <= 0) { throw std::runtime_error("missing entry"); } test_s2c = entry["test_s2c"][0]; simple_stats["download"] = compute_speed(test_s2c["receiver_data"], "download", logger); simple_stats["ping"] = compute_ping(test_s2c, logger); } catch (const std::exception &x) { logger->warn("cannot access entry[\"test_s2c\"][0]: %s", x.what()); /* Cannot compute this stat */ } try { /* * As of v0.4.0, we cannot have more than one entry here. */ if (entry["test_c2s"].size() <= 0) { throw std::runtime_error("missing entry"); } test_c2s = entry["test_c2s"][0]; simple_stats["upload"] = compute_speed(test_c2s["sender_data"], "upload", logger); } catch (const std::exception &x) { logger->warn("cannot access entry[\"test_c2s\"][0]: %s", x.what()); /* Cannot compute this stat */ } return simple_stats; } report::Entry compute_advanced_stats(report::Entry &entry, Var) { /* * Typically we have just one entry. But see above comment. */ report::Entry test_s2c = entry["test_s2c"][0]; report::Entry advanced_stats; // See: https://github.com/ndt-project/ndt/wiki/NDTTestMethodology#computed-variables double SndLimTimeRwin = test_s2c["web100_data"]["SndLimTimeRwin"]; double SndLimTimeCwnd = test_s2c["web100_data"]["SndLimTimeCwnd"]; double SndLimTimeSender = test_s2c["web100_data"]["SndLimTimeSender"]; double TotalTestTime = SndLimTimeRwin + SndLimTimeCwnd + SndLimTimeSender; double CongestionSignals = test_s2c["web100_data"]["CongestionSignals"]; double PktsOut = test_s2c["web100_data"]["PktsOut"]; double PacketLoss = 0.0; if (PktsOut > 0.0) { PacketLoss = CongestionSignals / PktsOut; } double DupAcksIn = test_s2c["web100_data"]["DupAcksIn"]; double AckPktsIn = test_s2c["web100_data"]["AckPktsIn"]; double OutOfOrder = 0.0; if (AckPktsIn > 0.0) { OutOfOrder = DupAcksIn / AckPktsIn; } double SumRTT = test_s2c["web100_data"]["SumRTT"]; double CountRTT = test_s2c["web100_data"]["CountRTT"]; double AvgRTT = 0.0; if (CountRTT > 0.0) { AvgRTT = SumRTT / CountRTT; } double CongestionLimited = 0.0; if (TotalTestTime > 0.0) { CongestionLimited = SndLimTimeCwnd / TotalTestTime; } double ReceiverLimited = 0.0; if (TotalTestTime > 0.0) { ReceiverLimited = SndLimTimeRwin / TotalTestTime; } double SenderLimited = 0.0; if (TotalTestTime > 0.0) { SenderLimited = SndLimTimeSender / TotalTestTime; } advanced_stats["avg_rtt"] = AvgRTT; advanced_stats["mss"] = test_s2c["web100_data"]["CurMSS"]; advanced_stats["max_rtt"] = test_s2c["web100_data"]["MaxRTT"]; advanced_stats["min_rtt"] = test_s2c["web100_data"]["MinRTT"]; advanced_stats["timeouts"] = test_s2c["web100_data"]["Timeouts"]; advanced_stats["out_of_order"] = OutOfOrder; advanced_stats["packet_loss"] = PacketLoss; // These are not used in ooni's UI advanced_stats["congestion_limited"] = CongestionLimited; advanced_stats["fast_retran"] = test_s2c["web100_data"]["FastRetran"]; advanced_stats["receiver_limited"] = ReceiverLimited; advanced_stats["sender_limited"] = SenderLimited; return advanced_stats; } } // namespace utils } // namespace ndt } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/net/000077500000000000000000000000001315356162600221015ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/net/buffer.cpp000066400000000000000000000135171315356162600240650ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/net/evbuffer.hpp" #include #include namespace mk { namespace net { Buffer::Buffer() { evbuf = make_shared_evbuffer(); } Buffer::Buffer(evbuffer *b) : Buffer() { if (b != nullptr && evbuffer_add_buffer(evbuf.get(), b) != 0) { throw std::runtime_error("evbuffer_add_buffer failed"); } } /*static*/ Var Buffer::make() { return Var(new Buffer); } Buffer::Buffer(std::string s) : Buffer() { write(s); } Buffer::Buffer(const void *p, size_t n) : Buffer() { write(p, n); } Buffer &Buffer::operator<<(evbuffer *source) { if (source == nullptr) throw std::runtime_error("source is nullptr"); if (evbuffer_add_buffer(evbuf.get(), source) != 0) throw std::runtime_error("evbuffer_add_buffer failed"); return *this; } Buffer &Buffer::operator>>(evbuffer *dest) { if (dest == nullptr) throw std::runtime_error("dest is nullptr"); if (evbuffer_add_buffer(dest, evbuf.get()) != 0) throw std::runtime_error("evbuffer_add_buffer failed"); return *this; } Buffer &Buffer::operator<<(Buffer &source) { *this << source.evbuf.get(); return *this; } Buffer &Buffer::operator>>(Buffer &dest) { *this >> dest.evbuf.get(); return *this; } size_t Buffer::length() { return evbuffer_get_length(evbuf.get()); } void Buffer::for_each(std::function fn) { auto required = evbuffer_peek(evbuf.get(), -1, nullptr, nullptr, 0); if (required < 0) throw std::runtime_error("unexpected error"); if (required == 0) return; std::unique_ptr raii; raii.reset(new evbuffer_iovec[required]); // Guarantee cleanup auto iov = raii.get(); auto used = evbuffer_peek(evbuf.get(), -1, nullptr, iov, required); if (used != required) throw std::runtime_error("unexpected error"); for (auto i = 0; i < required && fn(iov[i].iov_base, iov[i].iov_len); ++i) { /* nothing */; } } void Buffer::discard(size_t count) { if (evbuffer_drain(evbuf.get(), count) != 0) throw std::runtime_error("evbuffer_drain failed"); } std::string Buffer::readpeek(bool ispeek, size_t upto) { size_t nbytes = 0; std::string out; for_each([&nbytes, &out, &upto](const void *p, size_t n) { if (upto < n) n = upto; out.append((const char *)p, n); upto -= n; nbytes += n; return (upto > 0); }); /* * We do this after for_each() because we are not supposed * to modify the underlying `evbuf` during for_each(). */ if (!ispeek) discard(nbytes); return out; } ErrorOr Buffer::readline(size_t maxline) { size_t eol_length = 0; auto search_result = evbuffer_search_eol(evbuf.get(), nullptr, &eol_length, EVBUFFER_EOL_CRLF); if (search_result.pos < 0) { if (length() > maxline) { return EOLNotFoundError(); } return std::string(); } /* * Promotion to size_t safe because eol_length is a small * number and because we know that pos is non-negative. */ if (eol_length != 1 && eol_length != 2) { throw std::runtime_error("unexpected error"); } auto len = (size_t)search_result.pos + eol_length; if (len > maxline) { return LineTooLongError(); } return read(len); } void Buffer::write(const void *buf, size_t count) { if (buf == nullptr) throw std::runtime_error("buf is nullptr"); if (evbuffer_add(evbuf.get(), buf, count) != 0) throw std::runtime_error("evbuffer_add failed"); } ErrorOr Buffer::read_uint8() { uint8_t value = 0; if (length() < sizeof (value)) { return NotEnoughDataError(); } std::string str = read(sizeof (value)); memcpy(&value, str.data(), sizeof (value)); return value; } void Buffer::write_uint8(uint8_t num) { write(&num, sizeof(num)); } ErrorOr Buffer::read_uint16() { uint16_t value = 0; if (length() < sizeof (value)) { return NotEnoughDataError(); } std::string str = read(sizeof (value)); memcpy(&value, str.data(), sizeof (value)); value = ntohs(value); return value; } void Buffer::write_uint16(uint16_t num) { num = htons(num); write(&num, sizeof(num)); } ErrorOr Buffer::read_uint32() { uint32_t value = 0; if (length() < sizeof (value)) { return NotEnoughDataError(); } std::string str = read(sizeof (value)); memcpy(&value, str.data(), sizeof (value)); value = ntohl(value); return value; } void Buffer::write_uint32(uint32_t num) { num = htonl(num); write(&num, sizeof(num)); } void Buffer::write_rand(size_t count) { if (count == 0) return; char *p = new char[count]; evutil_secure_rng_get_bytes(p, count); auto ctrl = evbuffer_add_reference( evbuf.get(), p, count, [](const void *, size_t, void *p) { delete[] static_cast(p); }, p); if (ctrl != 0) throw std::runtime_error("evbuffer_add_reference"); } void Buffer::write(size_t count, std::function func) { if (count == 0) return; char *p = new char[count]; size_t used = func(p, count); if (used > count) { delete[] p; throw std::runtime_error("internal error"); } if (used == 0) { delete[] p; return; } auto ctrl = evbuffer_add_reference(evbuf.get(), p, used, [](const void *, size_t, void *p) { delete[] static_cast(p); }, p); if (ctrl != 0) throw std::runtime_error("evbuffer_add_reference"); } } // namespace net } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/net/builtin_ca_bundle.cpp000066400000000000000000054212401315356162600262570ustar00rootroot00000000000000 /* * Warning: autogenerated file; do not edit! * * Returns the CA file shipped with the libressl version we compile with * as a vector of unsigned characters. This could then be passed to libressl * specific functions for loading CAs from a memory buffer. * * Based on curl cacert-2017-06-07 */ #include "private/net/builtin_ca_bundle.hpp" namespace mk { namespace net { std::vector builtin_ca_bundle() { static std::vector cav{ 35, 35, 10, 35, 35, 32, 66, 117, 110, 100, 108, 101, 32, 111, 102, 32, 67, 65, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 10, 35, 35, 10, 35, 35, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 100, 97, 116, 97, 32, 102, 114, 111, 109, 32, 77, 111, 122, 105, 108, 108, 97, 32, 97, 115, 32, 111, 102, 58, 32, 87, 101, 100, 32, 74, 117, 110, 32, 32, 55, 32, 48, 51, 58, 49, 50, 58, 48, 53, 32, 50, 48, 49, 55, 32, 71, 77, 84, 10, 35, 35, 10, 35, 35, 32, 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 98, 117, 110, 100, 108, 101, 32, 111, 102, 32, 88, 46, 53, 48, 57, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 32, 111, 102, 32, 112, 117, 98, 108, 105, 99, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 105, 101, 115, 10, 35, 35, 32, 40, 67, 65, 41, 46, 32, 84, 104, 101, 115, 101, 32, 119, 101, 114, 101, 32, 97, 117, 116, 111, 109, 97, 116, 105, 99, 97, 108, 108, 121, 32, 101, 120, 116, 114, 97, 99, 116, 101, 100, 32, 102, 114, 111, 109, 32, 77, 111, 122, 105, 108, 108, 97, 39, 115, 32, 114, 111, 111, 116, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 10, 35, 35, 32, 102, 105, 108, 101, 32, 40, 99, 101, 114, 116, 100, 97, 116, 97, 46, 116, 120, 116, 41, 46, 32, 32, 84, 104, 105, 115, 32, 102, 105, 108, 101, 32, 99, 97, 110, 32, 98, 101, 32, 102, 111, 117, 110, 100, 32, 105, 110, 32, 116, 104, 101, 32, 109, 111, 122, 105, 108, 108, 97, 32, 115, 111, 117, 114, 99, 101, 32, 116, 114, 101, 101, 58, 10, 35, 35, 32, 104, 116, 116, 112, 115, 58, 47, 47, 104, 103, 46, 109, 111, 122, 105, 108, 108, 97, 46, 111, 114, 103, 47, 114, 101, 108, 101, 97, 115, 101, 115, 47, 109, 111, 122, 105, 108, 108, 97, 45, 114, 101, 108, 101, 97, 115, 101, 47, 114, 97, 119, 45, 102, 105, 108, 101, 47, 100, 101, 102, 97, 117, 108, 116, 47, 115, 101, 99, 117, 114, 105, 116, 121, 47, 110, 115, 115, 47, 108, 105, 98, 47, 99, 107, 102, 119, 47, 98, 117, 105, 108, 116, 105, 110, 115, 47, 99, 101, 114, 116, 100, 97, 116, 97, 46, 116, 120, 116, 10, 35, 35, 10, 35, 35, 32, 73, 116, 32, 99, 111, 110, 116, 97, 105, 110, 115, 32, 116, 104, 101, 32, 99, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 32, 105, 110, 32, 80, 69, 77, 32, 102, 111, 114, 109, 97, 116, 32, 97, 110, 100, 32, 116, 104, 101, 114, 101, 102, 111, 114, 101, 10, 35, 35, 32, 99, 97, 110, 32, 98, 101, 32, 100, 105, 114, 101, 99, 116, 108, 121, 32, 117, 115, 101, 100, 32, 119, 105, 116, 104, 32, 99, 117, 114, 108, 32, 47, 32, 108, 105, 98, 99, 117, 114, 108, 32, 47, 32, 112, 104, 112, 95, 99, 117, 114, 108, 44, 32, 111, 114, 32, 119, 105, 116, 104, 10, 35, 35, 32, 97, 110, 32, 65, 112, 97, 99, 104, 101, 43, 109, 111, 100, 95, 115, 115, 108, 32, 119, 101, 98, 115, 101, 114, 118, 101, 114, 32, 102, 111, 114, 32, 83, 83, 76, 32, 99, 108, 105, 101, 110, 116, 32, 97, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 46, 10, 35, 35, 32, 74, 117, 115, 116, 32, 99, 111, 110, 102, 105, 103, 117, 114, 101, 32, 116, 104, 105, 115, 32, 102, 105, 108, 101, 32, 97, 115, 32, 116, 104, 101, 32, 83, 83, 76, 67, 65, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 70, 105, 108, 101, 46, 10, 35, 35, 10, 35, 35, 32, 67, 111, 110, 118, 101, 114, 115, 105, 111, 110, 32, 100, 111, 110, 101, 32, 119, 105, 116, 104, 32, 109, 107, 45, 99, 97, 45, 98, 117, 110, 100, 108, 101, 46, 112, 108, 32, 118, 101, 114, 115, 105, 111, 110, 32, 49, 46, 50, 55, 46, 10, 35, 35, 32, 83, 72, 65, 50, 53, 54, 58, 32, 57, 51, 55, 53, 51, 50, 54, 56, 101, 49, 99, 53, 57, 54, 97, 101, 101, 50, 49, 56, 57, 51, 102, 98, 49, 99, 54, 57, 55, 53, 51, 51, 56, 51, 56, 57, 49, 51, 50, 102, 49, 53, 99, 57, 52, 50, 101, 100, 54, 53, 102, 99, 51, 57, 52, 97, 57, 48, 52, 51, 55, 49, 100, 55, 10, 35, 35, 10, 10, 10, 71, 108, 111, 98, 97, 108, 83, 105, 103, 110, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 100, 84, 67, 67, 65, 108, 50, 103, 65, 119, 73, 66, 65, 103, 73, 76, 66, 65, 65, 65, 65, 65, 65, 66, 70, 85, 116, 97, 119, 53, 81, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 86, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 81, 107, 85, 120, 10, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 111, 84, 69, 69, 100, 115, 98, 50, 74, 104, 98, 70, 78, 112, 90, 50, 52, 103, 98, 110, 89, 116, 99, 50, 69, 120, 69, 68, 65, 79, 66, 103, 78, 86, 66, 65, 115, 84, 66, 49, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 77, 84, 69, 107, 100, 115, 10, 98, 50, 74, 104, 98, 70, 78, 112, 90, 50, 52, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 84, 65, 101, 70, 119, 48, 53, 79, 68, 65, 53, 77, 68, 69, 120, 77, 106, 65, 119, 77, 68, 66, 97, 70, 119, 48, 121, 79, 68, 65, 120, 77, 106, 103, 120, 77, 106, 65, 119, 77, 68, 66, 97, 77, 70, 99, 120, 67, 122, 65, 74, 66, 103, 78, 86, 10, 66, 65, 89, 84, 65, 107, 74, 70, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 75, 69, 120, 66, 72, 98, 71, 57, 105, 89, 87, 120, 84, 97, 87, 100, 117, 73, 71, 53, 50, 76, 88, 78, 104, 77, 82, 65, 119, 68, 103, 89, 68, 86, 81, 81, 76, 69, 119, 100, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 82, 115, 119, 71, 81, 89, 68, 10, 86, 81, 81, 68, 69, 120, 74, 72, 98, 71, 57, 105, 89, 87, 120, 84, 97, 87, 100, 117, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 68, 97, 10, 68, 117, 97, 90, 106, 99, 54, 106, 52, 48, 43, 75, 102, 118, 118, 120, 105, 52, 77, 108, 97, 43, 112, 73, 72, 47, 69, 113, 115, 76, 109, 86, 69, 81, 83, 57, 56, 71, 80, 82, 52, 109, 100, 109, 122, 120, 122, 100, 122, 120, 116, 73, 75, 43, 54, 78, 105, 89, 54, 97, 114, 121, 109, 65, 90, 97, 118, 112, 120, 121, 48, 83, 121, 54, 115, 99, 10, 84, 72, 65, 72, 111, 84, 48, 75, 77, 77, 48, 86, 106, 85, 47, 52, 51, 100, 83, 77, 85, 66, 85, 99, 55, 49, 68, 117, 120, 67, 55, 51, 47, 79, 108, 83, 56, 112, 70, 57, 52, 71, 51, 86, 78, 84, 67, 79, 88, 107, 78, 122, 56, 107, 72, 112, 49, 87, 114, 106, 115, 111, 107, 54, 86, 106, 107, 52, 98, 119, 89, 56, 105, 71, 108, 98, 10, 75, 107, 51, 70, 112, 49, 83, 52, 98, 73, 110, 77, 109, 47, 107, 56, 121, 117, 88, 57, 105, 102, 85, 83, 80, 74, 74, 52, 108, 116, 98, 99, 100, 71, 54, 84, 82, 71, 72, 82, 106, 99, 100, 71, 115, 110, 85, 79, 104, 117, 103, 90, 105, 116, 86, 116, 98, 78, 86, 52, 70, 112, 87, 105, 54, 99, 103, 75, 79, 79, 118, 121, 74, 66, 78, 80, 10, 99, 49, 83, 84, 69, 52, 85, 54, 71, 55, 119, 101, 78, 76, 87, 76, 66, 89, 121, 53, 100, 52, 117, 120, 50, 120, 56, 103, 107, 97, 115, 74, 85, 50, 54, 81, 122, 110, 115, 51, 100, 76, 108, 119, 82, 53, 69, 105, 85, 87, 77, 87, 101, 97, 54, 120, 114, 107, 69, 109, 67, 77, 103, 90, 75, 57, 70, 71, 113, 107, 106, 87, 90, 67, 114, 88, 10, 103, 122, 84, 47, 76, 67, 114, 66, 98, 66, 108, 68, 83, 103, 101, 70, 53, 57, 78, 56, 57, 105, 70, 111, 55, 43, 114, 121, 85, 112, 57, 47, 107, 53, 68, 80, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 80, 66, 103, 78, 86, 10, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 103, 101, 50, 89, 97, 82, 81, 50, 88, 121, 111, 108, 81, 76, 51, 48, 69, 122, 84, 83, 111, 47, 47, 122, 57, 83, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 10, 65, 65, 79, 67, 65, 81, 69, 65, 49, 110, 80, 110, 102, 69, 57, 50, 48, 73, 50, 47, 55, 76, 113, 105, 118, 106, 84, 70, 75, 68, 75, 49, 102, 80, 120, 115, 110, 67, 119, 114, 118, 81, 109, 101, 85, 55, 57, 114, 88, 113, 111, 82, 83, 76, 98, 108, 67, 75, 79, 122, 121, 106, 49, 104, 84, 100, 78, 71, 67, 98, 77, 43, 119, 54, 68, 106, 10, 89, 49, 85, 98, 56, 114, 114, 118, 114, 84, 110, 104, 81, 55, 107, 52, 111, 43, 89, 118, 105, 105, 89, 55, 55, 54, 66, 81, 86, 118, 110, 71, 67, 118, 48, 52, 122, 99, 81, 76, 99, 70, 71, 85, 108, 53, 103, 69, 51, 56, 78, 102, 108, 78, 85, 86, 121, 82, 82, 66, 110, 77, 82, 100, 100, 87, 81, 86, 68, 102, 57, 86, 77, 79, 121, 71, 10, 106, 47, 56, 78, 55, 121, 121, 53, 89, 48, 98, 50, 113, 118, 122, 102, 118, 71, 110, 57, 76, 104, 74, 73, 90, 74, 114, 103, 108, 102, 67, 109, 55, 121, 109, 80, 65, 98, 69, 86, 116, 81, 119, 100, 112, 102, 53, 112, 76, 71, 107, 107, 101, 66, 54, 122, 112, 120, 120, 120, 89, 117, 55, 75, 121, 74, 101, 115, 70, 49, 50, 75, 119, 118, 104, 72, 10, 104, 109, 52, 113, 120, 70, 89, 120, 108, 100, 66, 110, 105, 89, 85, 114, 43, 87, 121, 109, 88, 85, 97, 100, 68, 75, 113, 67, 53, 74, 108, 82, 51, 88, 67, 51, 50, 49, 89, 57, 89, 101, 82, 113, 52, 86, 122, 87, 57, 118, 52, 57, 51, 107, 72, 77, 66, 54, 53, 106, 85, 114, 57, 84, 85, 47, 81, 114, 54, 99, 102, 57, 116, 118, 101, 67, 10, 88, 52, 88, 83, 81, 82, 106, 98, 103, 98, 77, 69, 72, 77, 85, 102, 112, 73, 66, 118, 70, 83, 68, 74, 51, 103, 121, 73, 67, 104, 51, 87, 90, 108, 88, 105, 47, 69, 106, 74, 75, 83, 90, 112, 52, 65, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 108, 111, 98, 97, 108, 83, 105, 103, 110, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 82, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 117, 106, 67, 67, 65, 113, 75, 103, 65, 119, 73, 66, 65, 103, 73, 76, 66, 65, 65, 65, 65, 65, 65, 66, 68, 52, 89, 109, 53, 103, 48, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 84, 68, 69, 103, 77, 66, 52, 71, 65, 49, 85, 69, 67, 120, 77, 88, 82, 50, 120, 118, 10, 89, 109, 70, 115, 85, 50, 108, 110, 98, 105, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 67, 48, 103, 85, 106, 73, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 111, 84, 67, 107, 100, 115, 98, 50, 74, 104, 98, 70, 78, 112, 90, 50, 52, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 77, 84, 67, 107, 100, 115, 98, 50, 74, 104, 10, 98, 70, 78, 112, 90, 50, 52, 119, 72, 104, 99, 78, 77, 68, 89, 120, 77, 106, 69, 49, 77, 68, 103, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 106, 69, 120, 77, 106, 69, 49, 77, 68, 103, 119, 77, 68, 65, 119, 87, 106, 66, 77, 77, 83, 65, 119, 72, 103, 89, 68, 86, 81, 81, 76, 69, 120, 100, 72, 98, 71, 57, 105, 89, 87, 120, 84, 10, 97, 87, 100, 117, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 76, 83, 66, 83, 77, 106, 69, 84, 77, 66, 69, 71, 65, 49, 85, 69, 67, 104, 77, 75, 82, 50, 120, 118, 89, 109, 70, 115, 85, 50, 108, 110, 98, 106, 69, 84, 77, 66, 69, 71, 65, 49, 85, 69, 65, 120, 77, 75, 82, 50, 120, 118, 89, 109, 70, 115, 85, 50, 108, 110, 10, 98, 106, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 75, 98, 80, 74, 65, 54, 43, 76, 109, 56, 111, 109, 85, 86, 67, 120, 75, 115, 43, 73, 86, 83, 98, 67, 57, 78, 47, 104, 72, 68, 54, 10, 69, 114, 80, 76, 118, 52, 100, 102, 120, 110, 43, 71, 48, 55, 73, 119, 88, 78, 98, 57, 114, 102, 70, 55, 51, 79, 88, 52, 89, 74, 89, 74, 107, 104, 68, 49, 48, 70, 80, 101, 43, 51, 116, 43, 99, 52, 105, 115, 85, 111, 104, 55, 83, 113, 98, 75, 83, 97, 90, 101, 113, 75, 101, 77, 87, 104, 71, 56, 101, 111, 76, 114, 118, 111, 122, 112, 10, 115, 54, 121, 87, 74, 81, 101, 88, 83, 112, 107, 113, 66, 121, 43, 48, 72, 110, 101, 47, 105, 103, 43, 49, 65, 110, 119, 98, 108, 114, 106, 70, 117, 84, 111, 115, 118, 78, 89, 83, 117, 101, 116, 90, 102, 101, 76, 81, 66, 111, 90, 102, 88, 107, 108, 113, 116, 84, 108, 101, 105, 68, 84, 115, 118, 72, 103, 77, 67, 74, 105, 69, 98, 75, 106, 78, 10, 83, 55, 83, 103, 102, 81, 120, 53, 84, 102, 67, 52, 76, 99, 115, 104, 121, 116, 86, 115, 87, 51, 51, 104, 111, 67, 109, 69, 111, 102, 110, 84, 108, 69, 110, 76, 74, 71, 75, 82, 73, 76, 122, 100, 67, 57, 88, 90, 122, 80, 110, 113, 74, 119, 111, 114, 99, 53, 72, 71, 110, 82, 117, 115, 121, 77, 118, 111, 52, 75, 68, 48, 76, 53, 67, 76, 10, 84, 102, 117, 119, 78, 104, 118, 50, 71, 88, 113, 70, 52, 71, 51, 121, 89, 82, 79, 73, 88, 74, 47, 103, 107, 119, 112, 82, 108, 52, 112, 97, 122, 113, 43, 114, 49, 102, 101, 113, 67, 97, 112, 103, 118, 100, 122, 90, 88, 57, 57, 121, 113, 87, 65, 84, 88, 103, 65, 66, 121, 85, 114, 54, 80, 54, 84, 113, 66, 119, 77, 104, 65, 111, 54, 67, 10, 121, 103, 80, 67, 109, 52, 56, 67, 65, 119, 69, 65, 65, 97, 79, 66, 110, 68, 67, 66, 109, 84, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 10, 70, 103, 81, 85, 109, 43, 73, 72, 86, 50, 99, 99, 72, 115, 66, 113, 66, 116, 53, 90, 116, 74, 111, 116, 51, 57, 119, 90, 104, 105, 52, 119, 78, 103, 89, 68, 86, 82, 48, 102, 66, 67, 56, 119, 76, 84, 65, 114, 111, 67, 109, 103, 74, 52, 89, 108, 97, 72, 82, 48, 99, 68, 111, 118, 76, 50, 78, 121, 98, 67, 53, 110, 98, 71, 57, 105, 10, 89, 87, 120, 122, 97, 87, 100, 117, 76, 109, 53, 108, 100, 67, 57, 121, 98, 50, 57, 48, 76, 88, 73, 121, 76, 109, 78, 121, 98, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 83, 98, 52, 103, 100, 88, 90, 120, 119, 101, 119, 71, 111, 71, 51, 108, 109, 48, 109, 105, 51, 102, 51, 66, 109, 71, 76, 106, 65, 78, 10, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 109, 89, 70, 84, 104, 120, 120, 111, 108, 52, 97, 82, 55, 79, 66, 75, 117, 69, 81, 76, 113, 52, 71, 115, 74, 48, 47, 87, 119, 98, 103, 99, 81, 51, 105, 122, 68, 74, 114, 56, 54, 105, 119, 56, 98, 109, 69, 98, 84, 85, 115, 112, 10, 57, 90, 56, 70, 72, 83, 98, 66, 117, 79, 109, 68, 65, 71, 74, 70, 116, 113, 107, 73, 107, 55, 109, 112, 77, 48, 115, 89, 109, 115, 76, 52, 104, 52, 104, 79, 50, 57, 49, 120, 78, 66, 114, 66, 86, 78, 112, 71, 80, 43, 68, 84, 75, 113, 116, 116, 86, 67, 76, 49, 79, 109, 76, 78, 73, 71, 43, 54, 75, 89, 110, 88, 51, 90, 72, 117, 10, 48, 49, 121, 105, 80, 113, 70, 98, 81, 102, 88, 102, 53, 87, 82, 68, 76, 101, 110, 86, 79, 97, 118, 83, 111, 116, 43, 51, 105, 57, 68, 65, 103, 66, 107, 99, 82, 99, 65, 116, 106, 79, 106, 52, 76, 97, 82, 48, 86, 107, 110, 70, 66, 98, 86, 80, 70, 100, 53, 117, 82, 72, 103, 53, 104, 54, 104, 43, 117, 47, 78, 53, 71, 74, 71, 55, 10, 57, 71, 43, 100, 119, 102, 67, 77, 78, 89, 120, 100, 65, 102, 118, 68, 98, 98, 110, 118, 82, 71, 49, 53, 82, 106, 70, 43, 67, 118, 54, 112, 103, 115, 72, 47, 55, 54, 116, 117, 73, 77, 82, 81, 121, 86, 43, 100, 84, 90, 115, 88, 106, 65, 122, 108, 65, 99, 109, 103, 81, 87, 112, 122, 85, 47, 113, 108, 85, 76, 82, 117, 74, 81, 47, 55, 10, 84, 66, 106, 48, 47, 86, 76, 90, 106, 109, 109, 120, 54, 66, 69, 80, 51, 111, 106, 89, 43, 120, 49, 74, 57, 54, 114, 101, 108, 99, 56, 103, 101, 77, 74, 103, 69, 116, 115, 108, 81, 73, 120, 113, 47, 72, 53, 67, 79, 69, 66, 107, 69, 118, 101, 101, 103, 101, 71, 84, 76, 103, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 86, 101, 114, 105, 115, 105, 103, 110, 32, 67, 108, 97, 115, 115, 32, 51, 32, 80, 117, 98, 108, 105, 99, 32, 80, 114, 105, 109, 97, 114, 121, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 45, 32, 71, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 71, 106, 67, 67, 65, 119, 73, 67, 69, 81, 67, 98, 102, 103, 90, 74, 111, 122, 53, 105, 117, 100, 88, 117, 107, 69, 104, 120, 75, 101, 57, 88, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 77, 73, 72, 75, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 10, 85, 122, 69, 88, 77, 66, 85, 71, 65, 49, 85, 69, 67, 104, 77, 79, 86, 109, 86, 121, 97, 86, 78, 112, 90, 50, 52, 115, 73, 69, 108, 117, 89, 121, 52, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 115, 84, 70, 108, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 73, 70, 82, 121, 100, 88, 78, 48, 73, 69, 53, 108, 100, 72, 100, 118, 10, 99, 109, 115, 120, 79, 106, 65, 52, 66, 103, 78, 86, 66, 65, 115, 84, 77, 83, 104, 106, 75, 83, 65, 120, 79, 84, 107, 53, 73, 70, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 76, 67, 66, 74, 98, 109, 77, 117, 73, 67, 48, 103, 82, 109, 57, 121, 73, 71, 70, 49, 100, 71, 104, 118, 99, 109, 108, 54, 90, 87, 81, 103, 100, 88, 78, 108, 10, 73, 71, 57, 117, 98, 72, 107, 120, 82, 84, 66, 68, 66, 103, 78, 86, 66, 65, 77, 84, 80, 70, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 73, 69, 78, 115, 89, 88, 78, 122, 73, 68, 77, 103, 85, 72, 86, 105, 98, 71, 108, 106, 73, 70, 66, 121, 97, 87, 49, 104, 99, 110, 107, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 10, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 103, 76, 83, 66, 72, 77, 122, 65, 101, 70, 119, 48, 53, 79, 84, 69, 119, 77, 68, 69, 119, 77, 68, 65, 119, 77, 68, 66, 97, 70, 119, 48, 122, 78, 106, 65, 51, 77, 84, 89, 121, 77, 122, 85, 53, 78, 84, 108, 97, 77, 73, 72, 75, 77, 81, 115, 119, 10, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 88, 77, 66, 85, 71, 65, 49, 85, 69, 67, 104, 77, 79, 86, 109, 86, 121, 97, 86, 78, 112, 90, 50, 52, 115, 73, 69, 108, 117, 89, 121, 52, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 115, 84, 70, 108, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 73, 70, 82, 121, 10, 100, 88, 78, 48, 73, 69, 53, 108, 100, 72, 100, 118, 99, 109, 115, 120, 79, 106, 65, 52, 66, 103, 78, 86, 66, 65, 115, 84, 77, 83, 104, 106, 75, 83, 65, 120, 79, 84, 107, 53, 73, 70, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 76, 67, 66, 74, 98, 109, 77, 117, 73, 67, 48, 103, 82, 109, 57, 121, 73, 71, 70, 49, 100, 71, 104, 118, 10, 99, 109, 108, 54, 90, 87, 81, 103, 100, 88, 78, 108, 73, 71, 57, 117, 98, 72, 107, 120, 82, 84, 66, 68, 66, 103, 78, 86, 66, 65, 77, 84, 80, 70, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 73, 69, 78, 115, 89, 88, 78, 122, 73, 68, 77, 103, 85, 72, 86, 105, 98, 71, 108, 106, 73, 70, 66, 121, 97, 87, 49, 104, 99, 110, 107, 103, 10, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 103, 76, 83, 66, 72, 77, 122, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 10, 103, 103, 69, 66, 65, 77, 117, 54, 110, 70, 76, 56, 101, 66, 56, 97, 72, 109, 56, 98, 78, 51, 79, 57, 43, 77, 108, 114, 108, 66, 73, 119, 84, 47, 65, 50, 82, 47, 88, 81, 107, 81, 114, 49, 70, 56, 105, 108, 89, 99, 69, 87, 81, 69, 51, 55, 105, 109, 71, 81, 53, 88, 89, 103, 119, 82, 69, 71, 102, 97, 115, 115, 98, 113, 98, 49, 10, 69, 85, 71, 79, 43, 105, 50, 116, 75, 109, 70, 90, 112, 71, 99, 109, 84, 78, 68, 111, 118, 70, 74, 98, 99, 67, 65, 69, 87, 78, 70, 54, 121, 97, 82, 112, 118, 73, 77, 88, 90, 75, 48, 70, 105, 55, 122, 81, 87, 77, 54, 78, 106, 80, 88, 114, 56, 69, 74, 74, 67, 53, 50, 88, 74, 50, 99, 121, 98, 117, 71, 117, 107, 120, 85, 99, 10, 99, 76, 119, 103, 84, 83, 56, 89, 51, 112, 75, 73, 54, 71, 121, 70, 86, 120, 69, 97, 54, 88, 55, 106, 74, 104, 70, 85, 111, 107, 87, 87, 86, 89, 80, 75, 77, 73, 110, 111, 51, 78, 105, 106, 55, 83, 113, 65, 80, 51, 57, 53, 90, 86, 99, 43, 70, 83, 66, 109, 67, 67, 43, 86, 107, 55, 43, 113, 82, 121, 43, 111, 82, 112, 102, 119, 10, 69, 117, 76, 43, 119, 103, 111, 114, 85, 101, 90, 50, 53, 114, 100, 71, 116, 43, 73, 78, 112, 115, 121, 111, 119, 48, 120, 90, 86, 89, 110, 109, 54, 70, 78, 99, 72, 79, 113, 100, 56, 71, 73, 87, 67, 54, 102, 74, 88, 119, 122, 119, 51, 115, 74, 50, 122, 113, 47, 51, 97, 118, 76, 54, 81, 97, 97, 105, 77, 120, 84, 74, 53, 88, 112, 106, 10, 48, 53, 53, 105, 78, 57, 87, 70, 90, 90, 52, 79, 53, 108, 77, 107, 100, 66, 116, 101, 72, 82, 74, 84, 87, 56, 99, 115, 53, 52, 78, 74, 79, 120, 87, 117, 105, 109, 105, 53, 86, 53, 99, 67, 65, 119, 69, 65, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 10, 69, 82, 83, 87, 119, 97, 117, 83, 67, 80, 99, 47, 76, 56, 109, 121, 47, 117, 82, 97, 110, 50, 84, 101, 50, 121, 70, 80, 104, 112, 107, 48, 100, 106, 90, 88, 51, 100, 65, 86, 76, 56, 87, 116, 102, 120, 85, 102, 78, 50, 74, 122, 80, 116, 84, 110, 88, 56, 52, 88, 65, 57, 115, 49, 43, 105, 118, 98, 114, 109, 65, 74, 88, 120, 53, 102, 10, 106, 50, 54, 55, 67, 122, 51, 113, 87, 104, 77, 101, 68, 71, 66, 118, 116, 99, 67, 49, 73, 121, 73, 117, 66, 119, 118, 76, 113, 88, 84, 76, 82, 55, 115, 100, 119, 100, 101, 108, 97, 56, 119, 118, 48, 107, 76, 57, 83, 100, 50, 110, 105, 99, 57, 84, 117, 116, 111, 65, 87, 105, 105, 47, 103, 116, 47, 52, 117, 104, 77, 100, 85, 73, 97, 67, 10, 47, 89, 52, 119, 106, 121, 108, 71, 115, 66, 52, 57, 78, 100, 111, 52, 89, 104, 89, 89, 83, 113, 51, 109, 116, 108, 70, 115, 51, 113, 57, 105, 54, 119, 72, 81, 72, 105, 84, 43, 101, 111, 56, 83, 71, 104, 74, 111, 117, 80, 116, 109, 109, 82, 81, 85, 82, 86, 121, 117, 53, 54, 53, 112, 70, 52, 69, 114, 87, 106, 102, 74, 88, 105, 114, 48, 10, 120, 117, 75, 104, 88, 70, 83, 98, 112, 108, 81, 65, 122, 47, 68, 120, 119, 99, 101, 89, 77, 66, 111, 55, 78, 104, 98, 98, 111, 50, 55, 113, 47, 97, 50, 121, 119, 116, 114, 118, 65, 107, 99, 84, 105, 115, 68, 120, 115, 122, 71, 116, 84, 120, 122, 104, 84, 53, 121, 118, 68, 119, 121, 100, 57, 51, 103, 78, 50, 80, 81, 49, 86, 111, 68, 97, 10, 116, 50, 48, 88, 106, 53, 48, 101, 103, 87, 84, 104, 47, 115, 86, 70, 117, 113, 49, 114, 117, 81, 112, 54, 84, 107, 57, 76, 104, 79, 53, 76, 56, 88, 51, 100, 69, 81, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 32, 80, 114, 101, 109, 105, 117, 109, 32, 50, 48, 52, 56, 32, 83, 101, 99, 117, 114, 101, 32, 83, 101, 114, 118, 101, 114, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 75, 106, 67, 67, 65, 120, 75, 103, 65, 119, 73, 66, 65, 103, 73, 69, 79, 71, 80, 101, 43, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 66, 116, 68, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 67, 104, 77, 76, 82, 87, 53, 48, 99, 110, 86, 122, 100, 67, 53, 117, 10, 90, 88, 81, 120, 81, 68, 65, 43, 66, 103, 78, 86, 66, 65, 115, 85, 78, 51, 100, 51, 100, 121, 53, 108, 98, 110, 82, 121, 100, 88, 78, 48, 76, 109, 53, 108, 100, 67, 57, 68, 85, 70, 78, 102, 77, 106, 65, 48, 79, 67, 66, 112, 98, 109, 78, 118, 99, 110, 65, 117, 73, 71, 74, 53, 73, 72, 74, 108, 90, 105, 52, 103, 75, 71, 120, 112, 10, 98, 87, 108, 48, 99, 121, 66, 115, 97, 87, 70, 105, 76, 105, 107, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 115, 84, 72, 67, 104, 106, 75, 83, 65, 120, 79, 84, 107, 53, 73, 69, 86, 117, 100, 72, 74, 49, 99, 51, 81, 117, 98, 109, 86, 48, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 77, 122, 65, 120, 66, 103, 78, 86, 10, 66, 65, 77, 84, 75, 107, 86, 117, 100, 72, 74, 49, 99, 51, 81, 117, 98, 109, 86, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 73, 67, 103, 121, 77, 68, 81, 52, 75, 84, 65, 101, 70, 119, 48, 53, 79, 84, 69, 121, 77, 106, 81, 120, 10, 78, 122, 85, 119, 78, 84, 70, 97, 70, 119, 48, 121, 79, 84, 65, 51, 77, 106, 81, 120, 78, 68, 69, 49, 77, 84, 74, 97, 77, 73, 71, 48, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 75, 69, 119, 116, 70, 98, 110, 82, 121, 100, 88, 78, 48, 76, 109, 53, 108, 100, 68, 70, 65, 77, 68, 52, 71, 65, 49, 85, 69, 67, 120, 81, 51, 10, 100, 51, 100, 51, 76, 109, 86, 117, 100, 72, 74, 49, 99, 51, 81, 117, 98, 109, 86, 48, 76, 48, 78, 81, 85, 49, 56, 121, 77, 68, 81, 52, 73, 71, 108, 117, 89, 50, 57, 121, 99, 67, 52, 103, 89, 110, 107, 103, 99, 109, 86, 109, 76, 105, 65, 111, 98, 71, 108, 116, 97, 88, 82, 122, 73, 71, 120, 112, 89, 87, 73, 117, 75, 84, 69, 108, 10, 77, 67, 77, 71, 65, 49, 85, 69, 67, 120, 77, 99, 75, 71, 77, 112, 73, 68, 69, 53, 79, 84, 107, 103, 82, 87, 53, 48, 99, 110, 86, 122, 100, 67, 53, 117, 90, 88, 81, 103, 84, 71, 108, 116, 97, 88, 82, 108, 90, 68, 69, 122, 77, 68, 69, 71, 65, 49, 85, 69, 65, 120, 77, 113, 82, 87, 53, 48, 99, 110, 86, 122, 100, 67, 53, 117, 10, 90, 88, 81, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 103, 75, 68, 73, 119, 78, 68, 103, 112, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 10, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 114, 85, 49, 76, 113, 82, 75, 71, 115, 117, 113, 106, 73, 65, 99, 86, 70, 109, 81, 113, 75, 48, 118, 82, 118, 119, 116, 75, 84, 89, 55, 116, 103, 72, 97, 108, 90, 55, 100, 52, 81, 77, 66, 122, 81, 115, 104, 111, 119, 78, 116, 84, 75, 57, 49, 101, 117, 72, 97, 89, 78, 90, 79, 76, 10, 71, 112, 49, 56, 69, 122, 111, 79, 72, 49, 117, 51, 72, 115, 47, 108, 74, 66, 81, 101, 115, 89, 71, 112, 106, 88, 50, 52, 122, 71, 116, 76, 65, 47, 69, 67, 68, 78, 121, 114, 112, 85, 65, 107, 65, 72, 57, 48, 108, 75, 71, 100, 67, 67, 109, 122, 105, 65, 118, 49, 104, 51, 101, 100, 86, 99, 51, 107, 119, 51, 55, 88, 97, 109, 83, 114, 10, 104, 82, 83, 71, 108, 86, 117, 88, 77, 108, 66, 118, 80, 99, 105, 54, 90, 103, 122, 106, 47, 76, 50, 52, 83, 99, 70, 50, 105, 85, 107, 90, 47, 99, 67, 111, 118, 89, 109, 106, 90, 121, 47, 71, 110, 55, 120, 120, 71, 87, 67, 52, 76, 101, 107, 115, 121, 90, 66, 50, 90, 110, 117, 85, 52, 113, 57, 52, 49, 109, 86, 84, 88, 84, 122, 87, 10, 110, 76, 76, 80, 75, 81, 80, 53, 76, 54, 82, 81, 115, 116, 82, 73, 122, 103, 85, 121, 86, 89, 114, 57, 115, 109, 82, 77, 68, 117, 83, 89, 66, 51, 88, 98, 102, 57, 43, 53, 67, 70, 86, 103, 104, 84, 65, 112, 43, 88, 116, 73, 112, 71, 109, 71, 52, 122, 85, 47, 72, 111, 90, 100, 101, 110, 111, 86, 118, 101, 56, 65, 106, 104, 85, 105, 10, 86, 66, 99, 65, 107, 67, 97, 84, 118, 65, 53, 74, 97, 74, 71, 47, 43, 69, 102, 84, 110, 90, 86, 67, 119, 81, 53, 78, 51, 50, 56, 109, 122, 56, 77, 89, 73, 87, 74, 109, 81, 51, 68, 87, 49, 99, 65, 72, 52, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 10, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 86, 101, 83, 66, 48, 82, 71, 65, 118, 116, 105, 74, 117, 81, 105, 106, 77, 102, 109, 104, 74, 65, 107, 87, 117, 88, 65, 119, 68, 81, 89, 74, 10, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 68, 117, 98, 106, 49, 97, 98, 77, 79, 100, 84, 109, 88, 120, 54, 101, 97, 100, 78, 108, 57, 99, 90, 108, 90, 68, 55, 66, 104, 47, 75, 77, 51, 120, 71, 89, 52, 43, 87, 90, 105, 84, 54, 81, 66, 115, 104, 74, 56, 114, 109, 99, 110, 80, 121, 10, 84, 47, 52, 120, 109, 102, 51, 73, 68, 69, 120, 111, 85, 56, 97, 65, 103, 104, 79, 89, 43, 114, 97, 116, 50, 108, 48, 57, 56, 99, 53, 117, 57, 104, 85, 82, 108, 73, 73, 77, 55, 106, 43, 86, 114, 120, 71, 114, 68, 57, 99, 118, 51, 104, 56, 68, 106, 49, 99, 115, 72, 115, 109, 55, 109, 104, 112, 69, 108, 101, 115, 89, 84, 54, 89, 102, 10, 122, 88, 49, 88, 69, 67, 43, 98, 66, 65, 108, 97, 104, 76, 86, 117, 50, 66, 48, 54, 52, 100, 97, 101, 48, 87, 120, 53, 88, 110, 107, 99, 70, 77, 88, 106, 48, 69, 121, 84, 79, 50, 85, 56, 55, 100, 56, 57, 118, 113, 98, 108, 108, 82, 114, 68, 116, 82, 110, 68, 118, 86, 53, 98, 117, 47, 56, 106, 55, 50, 103, 90, 121, 120, 75, 84, 10, 74, 49, 119, 68, 76, 87, 56, 119, 48, 66, 54, 50, 71, 113, 122, 101, 87, 118, 102, 82, 113, 113, 103, 110, 112, 118, 53, 53, 103, 99, 82, 53, 109, 84, 78, 88, 117, 104, 75, 119, 113, 101, 66, 67, 98, 74, 80, 75, 86, 116, 55, 43, 98, 89, 81, 76, 67, 73, 116, 43, 106, 101, 114, 88, 109, 67, 72, 71, 56, 43, 99, 56, 101, 83, 57, 101, 10, 110, 78, 70, 77, 70, 89, 51, 104, 55, 67, 73, 51, 122, 74, 112, 68, 67, 53, 102, 99, 103, 74, 67, 78, 115, 50, 101, 98, 98, 48, 103, 73, 70, 86, 98, 80, 118, 47, 69, 114, 102, 70, 54, 97, 100, 117, 108, 90, 107, 77, 86, 56, 103, 122, 85, 82, 90, 86, 69, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 66, 97, 108, 116, 105, 109, 111, 114, 101, 32, 67, 121, 98, 101, 114, 84, 114, 117, 115, 116, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 100, 122, 67, 67, 65, 108, 43, 103, 65, 119, 73, 66, 65, 103, 73, 69, 65, 103, 65, 65, 117, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 97, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 74, 82, 84, 69, 83, 77, 66, 65, 71, 65, 49, 85, 69, 10, 67, 104, 77, 74, 81, 109, 70, 115, 100, 71, 108, 116, 98, 51, 74, 108, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 76, 69, 119, 112, 68, 101, 87, 74, 108, 99, 108, 82, 121, 100, 88, 78, 48, 77, 83, 73, 119, 73, 65, 89, 68, 86, 81, 81, 68, 69, 120, 108, 67, 89, 87, 120, 48, 97, 87, 49, 118, 99, 109, 85, 103, 81, 51, 108, 105, 10, 90, 88, 74, 85, 99, 110, 86, 122, 100, 67, 66, 83, 98, 50, 57, 48, 77, 66, 52, 88, 68, 84, 65, 119, 77, 68, 85, 120, 77, 106, 69, 52, 78, 68, 89, 119, 77, 70, 111, 88, 68, 84, 73, 49, 77, 68, 85, 120, 77, 106, 73, 122, 78, 84, 107, 119, 77, 70, 111, 119, 87, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 10, 83, 85, 85, 120, 69, 106, 65, 81, 66, 103, 78, 86, 66, 65, 111, 84, 67, 85, 74, 104, 98, 72, 82, 112, 98, 87, 57, 121, 90, 84, 69, 84, 77, 66, 69, 71, 65, 49, 85, 69, 67, 120, 77, 75, 81, 51, 108, 105, 90, 88, 74, 85, 99, 110, 86, 122, 100, 68, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 65, 120, 77, 90, 81, 109, 70, 115, 10, 100, 71, 108, 116, 98, 51, 74, 108, 73, 69, 78, 53, 89, 109, 86, 121, 86, 72, 74, 49, 99, 51, 81, 103, 85, 109, 57, 118, 100, 68, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 75, 77, 69, 10, 117, 121, 75, 114, 109, 68, 49, 88, 54, 67, 90, 121, 109, 114, 86, 53, 49, 67, 110, 105, 52, 101, 105, 86, 103, 76, 71, 119, 52, 49, 117, 79, 75, 121, 109, 97, 90, 78, 43, 104, 88, 101, 50, 119, 67, 81, 86, 116, 50, 121, 103, 117, 122, 109, 75, 105, 89, 118, 54, 48, 105, 78, 111, 83, 54, 122, 106, 114, 73, 90, 51, 65, 81, 83, 115, 66, 10, 85, 110, 117, 73, 100, 57, 77, 99, 106, 56, 101, 54, 117, 89, 105, 49, 97, 103, 110, 110, 99, 43, 103, 82, 81, 75, 102, 82, 122, 77, 112, 105, 106, 83, 51, 108, 106, 119, 117, 109, 85, 78, 75, 111, 85, 77, 77, 111, 54, 118, 87, 114, 74, 89, 101, 75, 109, 112, 89, 99, 113, 87, 101, 52, 80, 119, 122, 86, 57, 47, 108, 83, 69, 121, 47, 67, 10, 71, 57, 86, 119, 99, 80, 67, 80, 119, 66, 76, 75, 66, 115, 117, 97, 52, 100, 110, 75, 77, 51, 112, 51, 49, 118, 106, 115, 117, 102, 70, 111, 82, 69, 74, 73, 69, 57, 76, 65, 119, 113, 83, 117, 88, 109, 68, 43, 116, 113, 89, 70, 47, 76, 84, 100, 66, 49, 107, 67, 49, 70, 107, 89, 109, 71, 80, 49, 112, 87, 80, 103, 107, 65, 120, 57, 10, 88, 98, 73, 71, 101, 118, 79, 70, 54, 117, 118, 85, 65, 54, 53, 101, 104, 68, 53, 102, 47, 120, 88, 116, 97, 98, 122, 53, 79, 84, 90, 121, 100, 99, 57, 51, 85, 107, 51, 122, 121, 90, 65, 115, 117, 84, 51, 108, 121, 83, 78, 84, 80, 120, 56, 107, 109, 67, 70, 99, 66, 53, 107, 112, 118, 99, 89, 54, 55, 79, 100, 117, 104, 106, 112, 114, 10, 108, 51, 82, 106, 77, 55, 49, 111, 71, 68, 72, 119, 101, 73, 49, 50, 118, 47, 121, 101, 106, 108, 48, 113, 104, 113, 100, 78, 107, 78, 119, 110, 71, 106, 107, 67, 65, 119, 69, 65, 65, 97, 78, 70, 77, 69, 77, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 79, 87, 100, 87, 84, 67, 67, 82, 49, 106, 77, 114, 80, 111, 73, 10, 86, 68, 97, 71, 101, 122, 113, 49, 66, 69, 51, 119, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 77, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 10, 66, 81, 85, 65, 65, 52, 73, 66, 65, 81, 67, 70, 68, 70, 50, 79, 53, 71, 57, 82, 97, 69, 73, 70, 111, 78, 50, 55, 84, 121, 99, 108, 104, 65, 79, 57, 57, 50, 84, 57, 76, 100, 99, 119, 52, 54, 81, 81, 70, 43, 118, 97, 75, 83, 109, 50, 101, 84, 57, 50, 57, 104, 107, 84, 73, 55, 103, 81, 67, 118, 108, 89, 112, 78, 82, 104, 10, 99, 76, 48, 69, 89, 87, 111, 83, 105, 104, 102, 86, 67, 114, 51, 70, 118, 68, 66, 56, 49, 117, 107, 77, 74, 89, 50, 71, 81, 69, 47, 115, 122, 75, 78, 43, 79, 77, 89, 51, 69, 85, 47, 116, 51, 87, 103, 120, 106, 107, 122, 83, 115, 119, 70, 48, 55, 114, 53, 49, 88, 103, 100, 73, 71, 110, 57, 119, 47, 120, 90, 99, 104, 77, 66, 53, 10, 104, 98, 103, 70, 47, 88, 43, 43, 90, 82, 71, 106, 68, 56, 65, 67, 116, 80, 104, 83, 78, 122, 107, 69, 49, 97, 107, 120, 101, 104, 105, 47, 111, 67, 114, 48, 69, 112, 110, 51, 111, 48, 87, 67, 52, 122, 120, 101, 57, 90, 50, 101, 116, 99, 105, 101, 102, 67, 55, 73, 112, 74, 53, 79, 67, 66, 82, 76, 98, 102, 49, 119, 98, 87, 115, 97, 10, 89, 55, 49, 107, 53, 104, 43, 51, 122, 118, 68, 121, 110, 121, 54, 55, 71, 55, 102, 121, 85, 73, 104, 122, 107, 115, 76, 105, 52, 120, 97, 78, 109, 106, 73, 67, 113, 52, 52, 89, 51, 101, 107, 81, 69, 101, 53, 43, 78, 97, 117, 81, 114, 122, 52, 119, 108, 72, 114, 81, 77, 122, 50, 110, 90, 81, 47, 49, 47, 73, 54, 101, 89, 115, 57, 72, 10, 82, 67, 119, 66, 88, 98, 115, 100, 116, 84, 76, 83, 82, 57, 73, 52, 76, 116, 68, 43, 103, 100, 119, 121, 97, 104, 54, 49, 55, 106, 122, 86, 47, 79, 101, 66, 72, 82, 110, 68, 74, 69, 76, 113, 89, 122, 109, 112, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 100, 100, 84, 114, 117, 115, 116, 32, 76, 111, 119, 45, 86, 97, 108, 117, 101, 32, 83, 101, 114, 118, 105, 99, 101, 115, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 71, 68, 67, 67, 65, 119, 67, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 108, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 84, 82, 84, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 67, 104, 77, 76, 10, 81, 87, 82, 107, 86, 72, 74, 49, 99, 51, 81, 103, 81, 85, 73, 120, 72, 84, 65, 98, 66, 103, 78, 86, 66, 65, 115, 84, 70, 69, 70, 107, 90, 70, 82, 121, 100, 88, 78, 48, 73, 70, 82, 85, 85, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 77, 83, 69, 119, 72, 119, 89, 68, 86, 81, 81, 68, 69, 120, 104, 66, 90, 71, 82, 85, 10, 99, 110, 86, 122, 100, 67, 66, 68, 98, 71, 70, 122, 99, 121, 65, 120, 73, 69, 78, 66, 73, 70, 74, 118, 98, 51, 81, 119, 72, 104, 99, 78, 77, 68, 65, 119, 78, 84, 77, 119, 77, 84, 65, 122, 79, 68, 77, 120, 87, 104, 99, 78, 77, 106, 65, 119, 78, 84, 77, 119, 77, 84, 65, 122, 79, 68, 77, 120, 87, 106, 66, 108, 77, 81, 115, 119, 10, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 84, 82, 84, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 67, 104, 77, 76, 81, 87, 82, 107, 86, 72, 74, 49, 99, 51, 81, 103, 81, 85, 73, 120, 72, 84, 65, 98, 66, 103, 78, 86, 66, 65, 115, 84, 70, 69, 70, 107, 90, 70, 82, 121, 100, 88, 78, 48, 73, 70, 82, 85, 85, 67, 66, 79, 10, 90, 88, 82, 51, 98, 51, 74, 114, 77, 83, 69, 119, 72, 119, 89, 68, 86, 81, 81, 68, 69, 120, 104, 66, 90, 71, 82, 85, 99, 110, 86, 122, 100, 67, 66, 68, 98, 71, 70, 122, 99, 121, 65, 120, 73, 69, 78, 66, 73, 70, 74, 118, 98, 51, 81, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 10, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 87, 108, 116, 81, 104, 83, 87, 68, 105, 97, 43, 104, 66, 66, 119, 122, 101, 120, 79, 68, 99, 69, 121, 80, 78, 119, 84, 88, 72, 43, 57, 90, 79, 69, 81, 112, 110, 88, 118, 85, 71, 87, 50, 117, 108, 67, 68, 116, 98, 75, 82, 89, 54, 10, 53, 52, 101, 121, 78, 65, 98, 70, 118, 65, 87, 108, 65, 51, 121, 67, 121, 121, 107, 81, 114, 117, 71, 73, 103, 98, 51, 87, 110, 116, 80, 43, 76, 86, 98, 66, 70, 99, 55, 106, 74, 112, 48, 86, 76, 104, 68, 55, 66, 111, 56, 119, 66, 78, 54, 110, 116, 71, 79, 48, 47, 55, 71, 99, 114, 106, 121, 118, 100, 55, 90, 87, 120, 98, 87, 114, 10, 111, 117, 108, 112, 79, 106, 48, 79, 77, 51, 107, 121, 80, 51, 67, 67, 107, 112, 108, 104, 98, 89, 48, 119, 67, 73, 57, 120, 80, 54, 90, 73, 86, 120, 110, 52, 74, 100, 120, 76, 90, 108, 121, 108, 100, 73, 43, 89, 114, 115, 106, 53, 119, 65, 89, 105, 53, 54, 120, 122, 51, 54, 85, 117, 43, 49, 76, 99, 115, 82, 86, 108, 73, 80, 111, 49, 10, 90, 109, 110, 101, 51, 121, 122, 120, 98, 114, 119, 119, 50, 121, 119, 107, 69, 116, 118, 114, 78, 84, 86, 111, 107, 77, 115, 65, 115, 74, 99, 104, 80, 88, 81, 104, 73, 50, 85, 48, 75, 55, 116, 52, 87, 97, 80, 87, 52, 88, 89, 53, 109, 113, 82, 74, 106, 111, 120, 48, 114, 50, 54, 107, 109, 113, 80, 90, 109, 57, 73, 52, 88, 74, 117, 105, 10, 71, 77, 120, 49, 73, 52, 83, 43, 54, 43, 74, 78, 77, 51, 71, 79, 71, 118, 68, 67, 43, 77, 99, 100, 111, 113, 48, 68, 108, 121, 122, 52, 122, 121, 88, 71, 57, 114, 103, 107, 77, 98, 70, 106, 88, 90, 74, 47, 89, 47, 65, 108, 121, 86, 77, 117, 72, 55, 57, 78, 65, 103, 77, 66, 65, 65, 71, 106, 103, 100, 73, 119, 103, 99, 56, 119, 10, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 74, 87, 120, 116, 80, 67, 85, 116, 114, 51, 72, 50, 116, 69, 82, 67, 83, 71, 43, 119, 97, 57, 74, 47, 82, 66, 55, 77, 65, 115, 71, 65, 49, 85, 100, 68, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 10, 65, 81, 72, 47, 77, 73, 71, 80, 66, 103, 78, 86, 72, 83, 77, 69, 103, 89, 99, 119, 103, 89, 83, 65, 70, 74, 87, 120, 116, 80, 67, 85, 116, 114, 51, 72, 50, 116, 69, 82, 67, 83, 71, 43, 119, 97, 57, 74, 47, 82, 66, 55, 111, 87, 109, 107, 90, 122, 66, 108, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 84, 10, 82, 84, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 67, 104, 77, 76, 81, 87, 82, 107, 86, 72, 74, 49, 99, 51, 81, 103, 81, 85, 73, 120, 72, 84, 65, 98, 66, 103, 78, 86, 66, 65, 115, 84, 70, 69, 70, 107, 90, 70, 82, 121, 100, 88, 78, 48, 73, 70, 82, 85, 85, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 77, 83, 69, 119, 10, 72, 119, 89, 68, 86, 81, 81, 68, 69, 120, 104, 66, 90, 71, 82, 85, 99, 110, 86, 122, 100, 67, 66, 68, 98, 71, 70, 122, 99, 121, 65, 120, 73, 69, 78, 66, 73, 70, 74, 118, 98, 51, 83, 67, 65, 81, 69, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 67, 120, 116, 10, 90, 66, 115, 102, 122, 81, 51, 100, 117, 81, 72, 54, 108, 109, 77, 48, 77, 107, 104, 72, 109, 97, 54, 88, 55, 102, 49, 121, 70, 113, 90, 122, 82, 49, 114, 48, 54, 57, 51, 112, 57, 100, 98, 55, 82, 99, 119, 112, 105, 85, 82, 100, 118, 48, 89, 53, 80, 101, 106, 117, 118, 69, 49, 85, 104, 104, 52, 100, 98, 79, 77, 88, 74, 48, 80, 104, 10, 105, 86, 89, 114, 113, 87, 57, 121, 84, 107, 107, 122, 52, 51, 74, 56, 75, 105, 79, 97, 118, 68, 55, 47, 75, 67, 114, 116, 111, 47, 56, 99, 73, 55, 112, 68, 86, 119, 108, 110, 84, 85, 116, 105, 66, 105, 51, 52, 47, 50, 121, 100, 89, 66, 55, 89, 72, 69, 116, 57, 116, 84, 69, 118, 50, 100, 66, 56, 88, 102, 106, 101, 97, 52, 77, 89, 10, 101, 68, 100, 88, 76, 43, 103, 122, 66, 50, 102, 102, 72, 115, 100, 114, 75, 112, 86, 50, 114, 111, 57, 88, 111, 47, 68, 48, 85, 114, 83, 112, 85, 119, 106, 80, 52, 69, 47, 84, 101, 108, 79, 76, 47, 98, 115, 99, 86, 106, 98, 121, 47, 114, 75, 50, 53, 88, 97, 55, 49, 83, 74, 108, 112, 122, 47, 43, 48, 87, 97, 116, 67, 55, 120, 114, 10, 109, 89, 98, 118, 80, 51, 51, 122, 71, 68, 76, 75, 101, 56, 98, 106, 113, 50, 82, 71, 108, 102, 103, 109, 97, 100, 108, 86, 103, 51, 115, 115, 108, 103, 102, 47, 87, 83, 120, 69, 111, 56, 98, 108, 54, 97, 110, 99, 111, 87, 79, 65, 87, 105, 70, 101, 73, 99, 57, 84, 86, 80, 67, 54, 98, 52, 110, 98, 113, 75, 113, 86, 122, 52, 118, 106, 10, 99, 99, 119, 101, 71, 121, 66, 69, 67, 77, 66, 54, 116, 107, 68, 57, 120, 79, 81, 49, 52, 82, 48, 87, 72, 78, 67, 56, 75, 52, 55, 87, 99, 100, 107, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 100, 100, 84, 114, 117, 115, 116, 32, 69, 120, 116, 101, 114, 110, 97, 108, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 78, 106, 67, 67, 65, 120, 54, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 118, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 84, 82, 84, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 67, 104, 77, 76, 10, 81, 87, 82, 107, 86, 72, 74, 49, 99, 51, 81, 103, 81, 85, 73, 120, 74, 106, 65, 107, 66, 103, 78, 86, 66, 65, 115, 84, 72, 85, 70, 107, 90, 70, 82, 121, 100, 88, 78, 48, 73, 69, 86, 52, 100, 71, 86, 121, 98, 109, 70, 115, 73, 70, 82, 85, 85, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 77, 83, 73, 119, 73, 65, 89, 68, 10, 86, 81, 81, 68, 69, 120, 108, 66, 90, 71, 82, 85, 99, 110, 86, 122, 100, 67, 66, 70, 101, 72, 82, 108, 99, 109, 53, 104, 98, 67, 66, 68, 81, 83, 66, 83, 98, 50, 57, 48, 77, 66, 52, 88, 68, 84, 65, 119, 77, 68, 85, 122, 77, 68, 69, 119, 78, 68, 103, 122, 79, 70, 111, 88, 68, 84, 73, 119, 77, 68, 85, 122, 77, 68, 69, 119, 10, 78, 68, 103, 122, 79, 70, 111, 119, 98, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 85, 48, 85, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 111, 84, 67, 48, 70, 107, 90, 70, 82, 121, 100, 88, 78, 48, 73, 69, 70, 67, 77, 83, 89, 119, 74, 65, 89, 68, 86, 81, 81, 76, 69, 120, 49, 66, 90, 71, 82, 85, 10, 99, 110, 86, 122, 100, 67, 66, 70, 101, 72, 82, 108, 99, 109, 53, 104, 98, 67, 66, 85, 86, 70, 65, 103, 84, 109, 86, 48, 100, 50, 57, 121, 97, 122, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 65, 120, 77, 90, 81, 87, 82, 107, 86, 72, 74, 49, 99, 51, 81, 103, 82, 88, 104, 48, 90, 88, 74, 117, 89, 87, 119, 103, 81, 48, 69, 103, 10, 85, 109, 57, 118, 100, 68, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 76, 102, 51, 71, 106, 80, 109, 56, 103, 65, 69, 76, 84, 110, 103, 84, 108, 118, 116, 72, 55, 120, 115, 68, 56, 50, 49, 10, 43, 105, 79, 50, 122, 116, 54, 98, 69, 84, 79, 88, 112, 67, 108, 77, 102, 90, 79, 102, 118, 85, 113, 56, 107, 43, 48, 68, 71, 117, 79, 80, 122, 43, 86, 116, 85, 70, 114, 87, 108, 121, 109, 85, 87, 111, 67, 119, 83, 88, 114, 98, 76, 112, 88, 57, 117, 77, 113, 47, 78, 122, 103, 116, 72, 106, 54, 82, 81, 97, 49, 119, 86, 115, 102, 119, 10, 84, 122, 47, 111, 77, 112, 53, 48, 121, 115, 105, 81, 86, 79, 110, 71, 88, 119, 57, 52, 110, 90, 112, 65, 80, 65, 54, 115, 89, 97, 112, 101, 70, 73, 43, 101, 104, 54, 70, 113, 85, 78, 122, 88, 109, 107, 54, 118, 66, 98, 79, 109, 99, 90, 83, 99, 99, 98, 78, 81, 89, 65, 114, 72, 69, 53, 48, 52, 66, 52, 89, 67, 113, 79, 109, 111, 10, 97, 83, 89, 89, 107, 75, 116, 77, 115, 69, 56, 106, 113, 122, 112, 80, 104, 78, 106, 102, 122, 112, 47, 104, 97, 87, 43, 55, 49, 48, 76, 88, 97, 48, 84, 107, 120, 54, 51, 117, 98, 85, 70, 102, 99, 108, 112, 120, 67, 68, 101, 122, 101, 87, 87, 107, 87, 97, 67, 85, 78, 47, 99, 65, 76, 119, 51, 67, 107, 110, 76, 97, 48, 68, 104, 121, 10, 50, 120, 83, 111, 82, 99, 82, 100, 75, 110, 50, 51, 116, 78, 98, 69, 55, 113, 122, 78, 69, 48, 83, 51, 121, 83, 118, 100, 81, 119, 65, 108, 43, 109, 71, 53, 97, 87, 112, 89, 73, 120, 71, 51, 112, 122, 79, 80, 86, 110, 86, 90, 57, 99, 48, 112, 49, 48, 97, 51, 67, 105, 116, 108, 116, 116, 78, 67, 98, 120, 87, 121, 117, 72, 118, 55, 10, 55, 43, 108, 100, 85, 57, 85, 48, 87, 105, 99, 67, 65, 119, 69, 65, 65, 97, 79, 66, 51, 68, 67, 66, 50, 84, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 114, 98, 50, 89, 101, 106, 83, 48, 74, 118, 102, 54, 120, 67, 90, 85, 55, 119, 79, 57, 52, 67, 84, 76, 86, 66, 111, 119, 67, 119, 89, 68, 86, 82, 48, 80, 10, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 103, 90, 107, 71, 65, 49, 85, 100, 73, 119, 83, 66, 107, 84, 67, 66, 106, 111, 65, 85, 114, 98, 50, 89, 101, 106, 83, 48, 74, 118, 102, 54, 120, 67, 90, 85, 55, 119, 79, 57, 52, 67, 84, 76, 10, 86, 66, 113, 104, 99, 54, 82, 120, 77, 71, 56, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 78, 70, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 75, 69, 119, 116, 66, 90, 71, 82, 85, 99, 110, 86, 122, 100, 67, 66, 66, 81, 106, 69, 109, 77, 67, 81, 71, 65, 49, 85, 69, 67, 120, 77, 100, 81, 87, 82, 107, 10, 86, 72, 74, 49, 99, 51, 81, 103, 82, 88, 104, 48, 90, 88, 74, 117, 89, 87, 119, 103, 86, 70, 82, 81, 73, 69, 53, 108, 100, 72, 100, 118, 99, 109, 115, 120, 73, 106, 65, 103, 66, 103, 78, 86, 66, 65, 77, 84, 71, 85, 70, 107, 90, 70, 82, 121, 100, 88, 78, 48, 73, 69, 86, 52, 100, 71, 86, 121, 98, 109, 70, 115, 73, 69, 78, 66, 10, 73, 70, 74, 118, 98, 51, 83, 67, 65, 81, 69, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 76, 67, 98, 52, 73, 85, 108, 119, 116, 89, 106, 52, 103, 43, 87, 66, 112, 75, 100, 81, 90, 105, 99, 50, 89, 82, 53, 103, 100, 107, 101, 87, 120, 81, 72, 73, 122, 90, 108, 10, 106, 55, 68, 89, 100, 55, 117, 115, 81, 87, 120, 72, 89, 73, 78, 82, 115, 80, 107, 121, 80, 101, 102, 56, 57, 105, 89, 84, 120, 52, 65, 87, 112, 98, 57, 97, 47, 73, 102, 80, 101, 72, 109, 74, 73, 90, 114, 105, 84, 65, 99, 75, 104, 106, 87, 56, 56, 116, 53, 82, 120, 78, 75, 87, 116, 57, 120, 43, 84, 117, 53, 119, 47, 82, 119, 53, 10, 54, 119, 119, 67, 85, 82, 81, 116, 106, 114, 48, 87, 52, 77, 72, 102, 82, 110, 88, 110, 74, 75, 51, 115, 57, 69, 75, 48, 104, 90, 78, 119, 69, 71, 101, 54, 110, 81, 89, 49, 83, 104, 106, 84, 75, 51, 114, 77, 85, 85, 75, 104, 101, 109, 80, 82, 53, 114, 117, 104, 120, 83, 118, 67, 78, 114, 52, 84, 68, 101, 97, 57, 89, 51, 53, 53, 10, 101, 54, 99, 74, 68, 85, 67, 114, 97, 116, 50, 80, 105, 115, 80, 50, 57, 111, 119, 97, 81, 103, 86, 82, 49, 69, 88, 49, 110, 54, 100, 105, 73, 87, 103, 86, 73, 69, 77, 56, 109, 101, 100, 56, 118, 83, 84, 89, 113, 90, 69, 88, 99, 52, 103, 47, 86, 104, 115, 120, 79, 66, 105, 48, 99, 81, 43, 97, 122, 99, 103, 79, 110, 111, 52, 117, 10, 71, 43, 71, 77, 109, 73, 80, 76, 72, 122, 72, 120, 82, 69, 122, 71, 66, 72, 78, 74, 100, 109, 65, 80, 120, 47, 105, 57, 70, 52, 66, 114, 76, 117, 110, 77, 84, 65, 53, 97, 109, 110, 107, 80, 73, 65, 111, 117, 49, 90, 53, 106, 74, 104, 53, 86, 107, 112, 84, 89, 103, 104, 100, 97, 101, 57, 67, 56, 120, 52, 57, 79, 104, 103, 81, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 100, 100, 84, 114, 117, 115, 116, 32, 80, 117, 98, 108, 105, 99, 32, 83, 101, 114, 118, 105, 99, 101, 115, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 70, 84, 67, 67, 65, 118, 50, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 107, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 84, 82, 84, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 67, 104, 77, 76, 10, 81, 87, 82, 107, 86, 72, 74, 49, 99, 51, 81, 103, 81, 85, 73, 120, 72, 84, 65, 98, 66, 103, 78, 86, 66, 65, 115, 84, 70, 69, 70, 107, 90, 70, 82, 121, 100, 88, 78, 48, 73, 70, 82, 85, 85, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 77, 83, 65, 119, 72, 103, 89, 68, 86, 81, 81, 68, 69, 120, 100, 66, 90, 71, 82, 85, 10, 99, 110, 86, 122, 100, 67, 66, 81, 100, 87, 74, 115, 97, 87, 77, 103, 81, 48, 69, 103, 85, 109, 57, 118, 100, 68, 65, 101, 70, 119, 48, 119, 77, 68, 65, 49, 77, 122, 65, 120, 77, 68, 81, 120, 78, 84, 66, 97, 70, 119, 48, 121, 77, 68, 65, 49, 77, 122, 65, 120, 77, 68, 81, 120, 78, 84, 66, 97, 77, 71, 81, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 78, 70, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 75, 69, 119, 116, 66, 90, 71, 82, 85, 99, 110, 86, 122, 100, 67, 66, 66, 81, 106, 69, 100, 77, 66, 115, 71, 65, 49, 85, 69, 67, 120, 77, 85, 81, 87, 82, 107, 86, 72, 74, 49, 99, 51, 81, 103, 86, 70, 82, 81, 73, 69, 53, 108, 10, 100, 72, 100, 118, 99, 109, 115, 120, 73, 68, 65, 101, 66, 103, 78, 86, 66, 65, 77, 84, 70, 48, 70, 107, 90, 70, 82, 121, 100, 88, 78, 48, 73, 70, 66, 49, 89, 109, 120, 112, 89, 121, 66, 68, 81, 83, 66, 83, 98, 50, 57, 48, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 10, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 54, 82, 111, 119, 106, 52, 79, 73, 70, 77, 69, 103, 50, 68, 121, 98, 106, 120, 116, 43, 65, 51, 83, 55, 50, 109, 110, 84, 82, 113, 88, 52, 106, 115, 73, 77, 69, 90, 66, 82, 112, 83, 57, 109, 86, 69, 66, 86, 54, 116, 115, 102, 83, 108, 98, 117, 10, 110, 121, 78, 117, 57, 68, 110, 76, 111, 98, 108, 118, 56, 110, 55, 53, 88, 89, 99, 109, 89, 90, 52, 99, 43, 79, 76, 115, 112, 111, 72, 52, 73, 99, 85, 107, 122, 66, 69, 77, 80, 57, 115, 109, 99, 110, 114, 72, 65, 90, 99, 72, 70, 47, 110, 88, 71, 67, 119, 119, 102, 81, 53, 54, 72, 109, 73, 101, 120, 107, 118, 65, 47, 88, 49, 105, 10, 100, 57, 78, 69, 72, 105, 102, 50, 80, 48, 116, 69, 115, 55, 99, 52, 50, 84, 107, 102, 89, 78, 86, 82, 107, 110, 77, 68, 116, 65, 66, 112, 52, 47, 77, 85, 84, 117, 55, 82, 51, 65, 110, 80, 100, 122, 82, 71, 85, 76, 68, 52, 69, 102, 76, 43, 79, 72, 110, 51, 66, 122, 110, 43, 85, 90, 75, 88, 67, 49, 115, 73, 88, 122, 83, 71, 10, 65, 97, 50, 73, 108, 43, 116, 109, 122, 86, 55, 82, 47, 57, 120, 57, 56, 111, 84, 97, 117, 110, 101, 116, 51, 73, 65, 73, 120, 54, 101, 72, 49, 108, 87, 102, 108, 50, 114, 111, 121, 66, 70, 107, 117, 117, 99, 90, 75, 84, 56, 82, 115, 51, 105, 81, 104, 67, 66, 83, 87, 120, 72, 118, 101, 78, 67, 68, 57, 116, 86, 73, 107, 78, 65, 119, 10, 72, 77, 43, 65, 43, 87, 68, 43, 101, 101, 83, 73, 56, 116, 48, 65, 54, 53, 82, 70, 54, 50, 87, 85, 97, 85, 67, 54, 119, 78, 87, 48, 117, 76, 112, 57, 66, 66, 71, 111, 54, 122, 69, 70, 108, 112, 82, 79, 87, 67, 71, 79, 110, 57, 66, 103, 47, 81, 73, 68, 65, 81, 65, 66, 111, 52, 72, 82, 77, 73, 72, 79, 77, 66, 48, 71, 10, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 83, 66, 80, 106, 102, 89, 107, 114, 65, 102, 100, 53, 57, 99, 116, 75, 116, 122, 113, 117, 102, 50, 78, 71, 65, 118, 43, 106, 65, 76, 66, 103, 78, 86, 72, 81, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 10, 47, 122, 67, 66, 106, 103, 89, 68, 86, 82, 48, 106, 66, 73, 71, 71, 77, 73, 71, 68, 103, 66, 83, 66, 80, 106, 102, 89, 107, 114, 65, 102, 100, 53, 57, 99, 116, 75, 116, 122, 113, 117, 102, 50, 78, 71, 65, 118, 43, 113, 70, 111, 112, 71, 89, 119, 90, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 85, 48, 85, 120, 10, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 111, 84, 67, 48, 70, 107, 90, 70, 82, 121, 100, 88, 78, 48, 73, 69, 70, 67, 77, 82, 48, 119, 71, 119, 89, 68, 86, 81, 81, 76, 69, 120, 82, 66, 90, 71, 82, 85, 99, 110, 86, 122, 100, 67, 66, 85, 86, 70, 65, 103, 84, 109, 86, 48, 100, 50, 57, 121, 97, 122, 69, 103, 77, 66, 52, 71, 10, 65, 49, 85, 69, 65, 120, 77, 88, 81, 87, 82, 107, 86, 72, 74, 49, 99, 51, 81, 103, 85, 72, 86, 105, 98, 71, 108, 106, 73, 69, 78, 66, 73, 70, 74, 118, 98, 51, 83, 67, 65, 81, 69, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 65, 80, 51, 70, 85, 114, 52, 10, 74, 78, 111, 106, 86, 104, 97, 84, 100, 116, 48, 50, 75, 76, 109, 117, 71, 55, 106, 68, 56, 87, 83, 54, 73, 66, 104, 52, 108, 83, 107, 110, 86, 119, 87, 56, 102, 67, 114, 48, 117, 86, 70, 86, 50, 111, 99, 67, 51, 103, 56, 87, 70, 122, 72, 52, 113, 110, 107, 117, 67, 82, 79, 55, 114, 55, 73, 103, 71, 82, 76, 108, 107, 47, 108, 76, 10, 43, 89, 80, 111, 82, 78, 87, 121, 81, 83, 87, 47, 105, 72, 86, 118, 47, 120, 68, 56, 83, 108, 84, 81, 88, 47, 68, 54, 55, 122, 90, 122, 102, 82, 115, 50, 82, 99, 89, 104, 98, 98, 81, 86, 117, 69, 55, 80, 110, 70, 121, 108, 80, 86, 111, 65, 106, 103, 98, 106, 80, 71, 115, 121, 101, 47, 75, 102, 56, 76, 98, 57, 51, 47, 65, 111, 10, 71, 69, 106, 119, 120, 114, 122, 81, 118, 122, 83, 65, 108, 115, 74, 75, 115, 87, 50, 79, 120, 53, 66, 70, 51, 105, 57, 110, 114, 69, 85, 69, 111, 51, 114, 99, 86, 90, 76, 74, 82, 50, 98, 89, 71, 111, 122, 72, 55, 90, 120, 79, 109, 117, 65, 83, 117, 55, 86, 113, 84, 73, 84, 104, 52, 83, 73, 78, 104, 119, 66, 107, 47, 111, 120, 57, 10, 89, 106, 108, 108, 112, 117, 57, 67, 116, 111, 65, 108, 69, 109, 69, 66, 113, 67, 81, 84, 99, 65, 65, 82, 74, 108, 47, 54, 78, 86, 68, 70, 83, 77, 119, 71, 82, 43, 103, 110, 50, 72, 67, 78, 88, 50, 84, 109, 111, 85, 81, 109, 88, 105, 76, 115, 107, 115, 51, 47, 81, 112, 112, 69, 73, 87, 49, 99, 120, 101, 77, 105, 72, 86, 57, 72, 10, 69, 117, 102, 79, 88, 49, 51, 54, 50, 75, 113, 120, 77, 121, 51, 90, 100, 118, 74, 79, 79, 106, 77, 77, 75, 55, 77, 116, 107, 65, 89, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 100, 100, 84, 114, 117, 115, 116, 32, 81, 117, 97, 108, 105, 102, 105, 101, 100, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 72, 106, 67, 67, 65, 119, 97, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 110, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 84, 82, 84, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 67, 104, 77, 76, 10, 81, 87, 82, 107, 86, 72, 74, 49, 99, 51, 81, 103, 81, 85, 73, 120, 72, 84, 65, 98, 66, 103, 78, 86, 66, 65, 115, 84, 70, 69, 70, 107, 90, 70, 82, 121, 100, 88, 78, 48, 73, 70, 82, 85, 85, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 77, 83, 77, 119, 73, 81, 89, 68, 86, 81, 81, 68, 69, 120, 112, 66, 90, 71, 82, 85, 10, 99, 110, 86, 122, 100, 67, 66, 82, 100, 87, 70, 115, 97, 87, 90, 112, 90, 87, 81, 103, 81, 48, 69, 103, 85, 109, 57, 118, 100, 68, 65, 101, 70, 119, 48, 119, 77, 68, 65, 49, 77, 122, 65, 120, 77, 68, 81, 48, 78, 84, 66, 97, 70, 119, 48, 121, 77, 68, 65, 49, 77, 122, 65, 120, 77, 68, 81, 48, 78, 84, 66, 97, 77, 71, 99, 120, 10, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 78, 70, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 75, 69, 119, 116, 66, 90, 71, 82, 85, 99, 110, 86, 122, 100, 67, 66, 66, 81, 106, 69, 100, 77, 66, 115, 71, 65, 49, 85, 69, 67, 120, 77, 85, 81, 87, 82, 107, 86, 72, 74, 49, 99, 51, 81, 103, 86, 70, 82, 81, 10, 73, 69, 53, 108, 100, 72, 100, 118, 99, 109, 115, 120, 73, 122, 65, 104, 66, 103, 78, 86, 66, 65, 77, 84, 71, 107, 70, 107, 90, 70, 82, 121, 100, 88, 78, 48, 73, 70, 70, 49, 89, 87, 120, 112, 90, 109, 108, 108, 90, 67, 66, 68, 81, 83, 66, 83, 98, 50, 57, 48, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 10, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 53, 66, 54, 97, 47, 116, 119, 74, 87, 111, 101, 107, 110, 48, 101, 43, 69, 86, 43, 118, 104, 68, 84, 98, 89, 106, 120, 53, 101, 76, 102, 112, 77, 76, 88, 115, 68, 66, 119, 113, 120, 66, 98, 47, 52, 79, 120, 120, 10, 54, 52, 114, 49, 69, 87, 55, 116, 84, 119, 50, 82, 48, 104, 73, 89, 76, 85, 107, 86, 65, 99, 75, 107, 73, 104, 80, 72, 69, 87, 84, 47, 73, 104, 75, 97, 117, 89, 53, 99, 76, 119, 106, 80, 99, 87, 113, 122, 90, 119, 70, 90, 56, 86, 49, 71, 56, 55, 66, 52, 112, 102, 89, 79, 81, 110, 114, 106, 102, 120, 118, 77, 48, 80, 67, 51, 10, 75, 80, 48, 113, 54, 112, 54, 122, 115, 76, 107, 69, 113, 118, 51, 50, 120, 55, 83, 120, 117, 67, 113, 103, 43, 49, 106, 120, 71, 97, 66, 118, 99, 67, 86, 43, 80, 109, 108, 75, 102, 119, 56, 105, 50, 79, 43, 116, 67, 66, 71, 97, 75, 90, 110, 104, 113, 107, 82, 70, 109, 104, 74, 101, 80, 112, 49, 116, 85, 118, 122, 110, 111, 68, 49, 111, 10, 76, 47, 66, 76, 99, 72, 119, 84, 79, 75, 50, 56, 70, 83, 88, 120, 49, 115, 54, 114, 111, 115, 65, 120, 49, 105, 43, 102, 52, 80, 56, 85, 87, 102, 121, 69, 107, 57, 109, 72, 102, 69, 120, 85, 69, 43, 117, 102, 48, 83, 48, 82, 43, 66, 103, 54, 79, 116, 52, 108, 50, 102, 102, 84, 81, 79, 50, 107, 66, 104, 76, 69, 79, 43, 71, 82, 10, 119, 86, 89, 49, 56, 66, 84, 99, 90, 84, 89, 74, 98, 113, 117, 107, 66, 56, 99, 49, 48, 99, 73, 68, 77, 122, 90, 98, 100, 83, 90, 116, 81, 118, 69, 83, 97, 48, 78, 118, 83, 51, 71, 85, 43, 106, 81, 100, 55, 82, 78, 117, 121, 111, 66, 47, 109, 67, 57, 115, 117, 87, 88, 89, 54, 81, 73, 68, 65, 81, 65, 66, 111, 52, 72, 85, 10, 77, 73, 72, 82, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 81, 53, 108, 89, 116, 105, 105, 49, 122, 74, 49, 73, 67, 54, 87, 65, 43, 88, 80, 120, 85, 73, 81, 56, 121, 89, 112, 122, 65, 76, 66, 103, 78, 86, 72, 81, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 10, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 67, 66, 107, 81, 89, 68, 86, 82, 48, 106, 66, 73, 71, 74, 77, 73, 71, 71, 103, 66, 81, 53, 108, 89, 116, 105, 105, 49, 122, 74, 49, 73, 67, 54, 87, 65, 43, 88, 80, 120, 85, 73, 81, 56, 121, 89, 112, 54, 70, 114, 112, 71, 107, 119, 90, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 85, 48, 85, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 111, 84, 67, 48, 70, 107, 90, 70, 82, 121, 100, 88, 78, 48, 73, 69, 70, 67, 77, 82, 48, 119, 71, 119, 89, 68, 86, 81, 81, 76, 69, 120, 82, 66, 90, 71, 82, 85, 99, 110, 86, 122, 100, 67, 66, 85, 86, 70, 65, 103, 84, 109, 86, 48, 100, 50, 57, 121, 10, 97, 122, 69, 106, 77, 67, 69, 71, 65, 49, 85, 69, 65, 120, 77, 97, 81, 87, 82, 107, 86, 72, 74, 49, 99, 51, 81, 103, 85, 88, 86, 104, 98, 71, 108, 109, 97, 87, 86, 107, 73, 69, 78, 66, 73, 70, 74, 118, 98, 51, 83, 67, 65, 81, 69, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 10, 103, 103, 69, 66, 65, 66, 109, 114, 100, 101, 114, 52, 105, 50, 86, 104, 108, 82, 79, 54, 97, 81, 84, 118, 104, 115, 111, 84, 111, 77, 101, 113, 84, 50, 81, 98, 80, 120, 106, 50, 113, 67, 48, 115, 86, 89, 56, 70, 116, 122, 68, 113, 81, 109, 111, 100, 119, 67, 86, 82, 76, 97, 101, 47, 68, 76, 80, 116, 55, 119, 104, 47, 98, 68, 120, 71, 10, 71, 117, 111, 89, 81, 57, 57, 50, 122, 80, 108, 109, 104, 112, 119, 115, 97, 80, 88, 112, 70, 47, 103, 120, 115, 120, 106, 69, 49, 107, 104, 57, 73, 48, 120, 111, 119, 88, 54, 55, 65, 82, 82, 118, 120, 100, 108, 117, 51, 114, 115, 69, 81, 109, 114, 52, 57, 108, 120, 57, 53, 100, 114, 54, 104, 43, 115, 78, 78, 86, 74, 110, 48, 74, 54, 88, 10, 100, 103, 87, 84, 80, 53, 88, 72, 65, 101, 90, 112, 86, 84, 104, 47, 69, 71, 71, 90, 121, 101, 78, 102, 112, 115, 111, 43, 103, 109, 78, 73, 113, 117, 73, 73, 83, 68, 54, 113, 56, 114, 75, 70, 89, 113, 97, 48, 112, 57, 109, 57, 78, 53, 120, 111, 116, 83, 49, 87, 102, 98, 67, 51, 80, 54, 67, 120, 66, 57, 98, 112, 84, 57, 122, 101, 10, 82, 88, 69, 119, 77, 110, 56, 98, 76, 103, 110, 53, 118, 49, 75, 104, 55, 115, 75, 65, 80, 103, 90, 99, 76, 108, 86, 65, 119, 82, 118, 49, 99, 69, 87, 119, 51, 70, 51, 54, 57, 110, 74, 97, 100, 57, 74, 106, 122, 99, 57, 89, 105, 81, 66, 67, 89, 122, 57, 53, 79, 100, 66, 69, 115, 73, 74, 117, 81, 82, 110, 111, 51, 101, 68, 66, 10, 105, 70, 114, 82, 72, 110, 71, 84, 72, 121, 81, 119, 100, 79, 85, 101, 113, 78, 52, 56, 74, 122, 100, 47, 103, 54, 54, 101, 100, 56, 47, 119, 77, 76, 72, 47, 83, 53, 110, 111, 120, 113, 69, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 69, 110, 116, 114, 117, 115, 116, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 107, 84, 67, 67, 65, 51, 109, 103, 65, 119, 73, 66, 65, 103, 73, 69, 82, 87, 116, 81, 86, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 66, 115, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 106, 65, 85, 66, 103, 78, 86, 10, 66, 65, 111, 84, 68, 85, 86, 117, 100, 72, 74, 49, 99, 51, 81, 115, 73, 69, 108, 117, 89, 121, 52, 120, 79, 84, 65, 51, 66, 103, 78, 86, 66, 65, 115, 84, 77, 72, 100, 51, 100, 121, 53, 108, 98, 110, 82, 121, 100, 88, 78, 48, 76, 109, 53, 108, 100, 67, 57, 68, 85, 70, 77, 103, 97, 88, 77, 103, 97, 87, 53, 106, 98, 51, 74, 119, 10, 98, 51, 74, 104, 100, 71, 86, 107, 73, 71, 74, 53, 73, 72, 74, 108, 90, 109, 86, 121, 90, 87, 53, 106, 90, 84, 69, 102, 77, 66, 48, 71, 65, 49, 85, 69, 67, 120, 77, 87, 75, 71, 77, 112, 73, 68, 73, 119, 77, 68, 89, 103, 82, 87, 53, 48, 99, 110, 86, 122, 100, 67, 119, 103, 83, 87, 53, 106, 76, 106, 69, 116, 77, 67, 115, 71, 10, 65, 49, 85, 69, 65, 120, 77, 107, 82, 87, 53, 48, 99, 110, 86, 122, 100, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 66, 52, 88, 68, 84, 65, 50, 77, 84, 69, 121, 78, 122, 73, 119, 77, 106, 77, 48, 10, 77, 108, 111, 88, 68, 84, 73, 50, 77, 84, 69, 121, 78, 122, 73, 119, 78, 84, 77, 48, 77, 108, 111, 119, 103, 98, 65, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 89, 119, 70, 65, 89, 68, 86, 81, 81, 75, 69, 119, 49, 70, 98, 110, 82, 121, 100, 88, 78, 48, 76, 67, 66, 74, 98, 109, 77, 117, 10, 77, 84, 107, 119, 78, 119, 89, 68, 86, 81, 81, 76, 69, 122, 66, 51, 100, 51, 99, 117, 90, 87, 53, 48, 99, 110, 86, 122, 100, 67, 53, 117, 90, 88, 81, 118, 81, 49, 66, 84, 73, 71, 108, 122, 73, 71, 108, 117, 89, 50, 57, 121, 99, 71, 57, 121, 89, 88, 82, 108, 90, 67, 66, 105, 101, 83, 66, 121, 90, 87, 90, 108, 99, 109, 86, 117, 10, 89, 50, 85, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 115, 84, 70, 105, 104, 106, 75, 83, 65, 121, 77, 68, 65, 50, 73, 69, 86, 117, 100, 72, 74, 49, 99, 51, 81, 115, 73, 69, 108, 117, 89, 121, 52, 120, 76, 84, 65, 114, 66, 103, 78, 86, 66, 65, 77, 84, 74, 69, 86, 117, 100, 72, 74, 49, 99, 51, 81, 103, 85, 109, 57, 118, 10, 100, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 84, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 10, 65, 76, 97, 86, 116, 107, 78, 67, 43, 115, 90, 116, 75, 109, 57, 73, 51, 53, 82, 77, 79, 86, 99, 70, 55, 115, 78, 53, 69, 85, 70, 111, 78, 117, 51, 115, 47, 112, 111, 66, 106, 54, 69, 52, 75, 80, 122, 51, 69, 69, 90, 109, 76, 107, 48, 101, 71, 114, 69, 97, 84, 115, 98, 82, 119, 74, 87, 73, 115, 77, 110, 47, 77, 89, 115, 122, 10, 65, 57, 117, 51, 103, 51, 115, 43, 73, 73, 82, 101, 55, 98, 74, 87, 75, 75, 102, 52, 52, 76, 108, 65, 99, 84, 102, 70, 121, 48, 99, 79, 108, 121, 112, 111, 119, 67, 75, 86, 89, 104, 88, 98, 82, 57, 110, 49, 48, 67, 118, 47, 103, 107, 118, 74, 114, 84, 55, 101, 84, 78, 117, 81, 103, 70, 65, 47, 67, 89, 113, 69, 65, 79, 119, 119, 10, 67, 106, 48, 89, 122, 102, 118, 57, 75, 108, 109, 97, 73, 53, 85, 88, 76, 69, 87, 101, 72, 50, 53, 68, 101, 87, 48, 77, 88, 74, 106, 43, 83, 75, 102, 70, 73, 48, 100, 99, 88, 118, 49, 117, 53, 120, 54, 48, 57, 109, 104, 70, 48, 89, 97, 68, 87, 54, 75, 75, 106, 98, 72, 106, 75, 89, 68, 43, 74, 88, 71, 73, 114, 98, 54, 56, 10, 106, 54, 120, 83, 108, 107, 117, 113, 85, 89, 51, 107, 69, 122, 69, 90, 54, 69, 53, 78, 110, 57, 117, 115, 115, 50, 114, 86, 118, 68, 108, 85, 99, 99, 112, 54, 101, 110, 43, 81, 51, 88, 48, 100, 103, 78, 109, 66, 117, 49, 107, 109, 119, 104, 72, 43, 53, 112, 80, 105, 57, 52, 68, 107, 90, 102, 115, 48, 78, 119, 52, 112, 103, 72, 66, 78, 10, 114, 122, 105, 71, 76, 112, 53, 47, 86, 54, 43, 101, 70, 54, 55, 114, 72, 77, 115, 111, 73, 86, 43, 50, 72, 78, 106, 110, 111, 103, 81, 105, 43, 100, 80, 97, 50, 77, 115, 67, 65, 119, 69, 65, 65, 97, 79, 66, 115, 68, 67, 66, 114, 84, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 10, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 114, 66, 103, 78, 86, 72, 82, 65, 69, 74, 68, 65, 105, 103, 65, 56, 121, 77, 68, 65, 50, 77, 84, 69, 121, 78, 122, 73, 119, 77, 106, 77, 48, 77, 108, 113, 66, 68, 122, 73, 119, 77, 106, 89, 120, 77, 84, 73, 51, 77, 106, 65, 49, 10, 77, 122, 81, 121, 87, 106, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 82, 111, 107, 79, 82, 110, 112, 75, 90, 84, 103, 77, 101, 71, 90, 113, 84, 120, 57, 48, 116, 68, 43, 52, 83, 57, 98, 84, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 97, 74, 68, 107, 90, 54, 83, 109, 85, 52, 68, 72, 10, 104, 109, 97, 107, 56, 102, 100, 76, 81, 47, 117, 69, 118, 87, 48, 119, 72, 81, 89, 74, 75, 111, 90, 73, 104, 118, 90, 57, 66, 48, 69, 65, 66, 66, 65, 119, 68, 104, 115, 73, 86, 106, 99, 117, 77, 84, 111, 48, 76, 106, 65, 68, 65, 103, 83, 81, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 10, 65, 52, 73, 66, 65, 81, 67, 84, 49, 68, 67, 119, 49, 119, 77, 103, 75, 116, 68, 53, 89, 43, 105, 82, 68, 65, 85, 103, 113, 86, 56, 90, 121, 110, 116, 121, 84, 116, 83, 120, 50, 57, 67, 87, 43, 49, 82, 97, 71, 83, 119, 77, 67, 80, 101, 121, 118, 73, 87, 111, 110, 88, 57, 116, 79, 49, 75, 122, 75, 116, 118, 110, 49, 73, 83, 77, 10, 89, 47, 89, 80, 121, 121, 89, 66, 107, 86, 66, 115, 57, 70, 56, 85, 52, 112, 78, 48, 119, 66, 79, 101, 77, 68, 112, 81, 52, 55, 82, 103, 120, 82, 122, 119, 73, 107, 83, 78, 99, 85, 101, 115, 121, 66, 114, 74, 54, 90, 117, 97, 65, 71, 65, 84, 47, 51, 66, 43, 88, 120, 70, 78, 83, 82, 117, 122, 70, 86, 74, 55, 121, 86, 84, 97, 10, 118, 53, 50, 86, 114, 50, 117, 97, 50, 74, 55, 112, 56, 101, 82, 68, 106, 101, 73, 82, 82, 68, 113, 47, 114, 55, 50, 68, 81, 110, 78, 83, 105, 54, 113, 55, 112, 121, 110, 80, 57, 87, 81, 99, 67, 107, 51, 82, 118, 75, 113, 115, 110, 121, 114, 81, 47, 51, 57, 47, 50, 110, 51, 113, 115, 101, 48, 119, 74, 99, 71, 69, 50, 106, 84, 83, 10, 87, 51, 105, 68, 86, 117, 121, 99, 78, 115, 77, 109, 52, 104, 72, 50, 90, 48, 107, 100, 107, 113, 117, 77, 43, 43, 118, 47, 101, 117, 54, 70, 83, 113, 100, 81, 103, 80, 67, 110, 88, 69, 113, 85, 76, 108, 56, 70, 109, 84, 120, 83, 81, 101, 68, 78, 116, 71, 80, 80, 65, 85, 79, 54, 110, 73, 80, 99, 106, 50, 65, 55, 56, 49, 113, 48, 10, 116, 72, 117, 117, 50, 103, 117, 81, 79, 72, 88, 118, 103, 82, 49, 109, 48, 118, 100, 88, 99, 68, 97, 122, 118, 47, 119, 111, 114, 51, 69, 108, 104, 86, 115, 84, 47, 104, 53, 47, 87, 114, 81, 56, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 101, 111, 84, 114, 117, 115, 116, 32, 71, 108, 111, 98, 97, 108, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 86, 68, 67, 67, 65, 106, 121, 103, 65, 119, 73, 66, 65, 103, 73, 68, 65, 106, 82, 87, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 77, 69, 73, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 89, 119, 70, 65, 89, 68, 86, 81, 81, 75, 10, 69, 119, 49, 72, 90, 87, 57, 85, 99, 110, 86, 122, 100, 67, 66, 74, 98, 109, 77, 117, 77, 82, 115, 119, 71, 81, 89, 68, 86, 81, 81, 68, 69, 120, 74, 72, 90, 87, 57, 85, 99, 110, 86, 122, 100, 67, 66, 72, 98, 71, 57, 105, 89, 87, 119, 103, 81, 48, 69, 119, 72, 104, 99, 78, 77, 68, 73, 119, 78, 84, 73, 120, 77, 68, 81, 119, 10, 77, 68, 65, 119, 87, 104, 99, 78, 77, 106, 73, 119, 78, 84, 73, 120, 77, 68, 81, 119, 77, 68, 65, 119, 87, 106, 66, 67, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 67, 104, 77, 78, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 83, 87, 53, 106, 10, 76, 106, 69, 98, 77, 66, 107, 71, 65, 49, 85, 69, 65, 120, 77, 83, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 82, 50, 120, 118, 89, 109, 70, 115, 73, 69, 78, 66, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 10, 67, 103, 75, 67, 65, 81, 69, 65, 50, 115, 119, 89, 89, 122, 68, 57, 57, 66, 99, 106, 71, 108, 90, 43, 87, 57, 56, 56, 98, 68, 106, 107, 99, 98, 100, 52, 107, 100, 83, 56, 111, 100, 104, 77, 43, 75, 104, 68, 116, 103, 80, 112, 84, 83, 69, 72, 67, 73, 106, 97, 87, 67, 57, 109, 79, 83, 109, 57, 66, 88, 105, 76, 110, 84, 106, 111, 10, 66, 98, 100, 113, 102, 110, 71, 107, 53, 115, 82, 103, 112, 114, 68, 118, 103, 79, 83, 74, 75, 65, 43, 101, 74, 100, 98, 116, 103, 47, 79, 116, 112, 112, 72, 72, 109, 77, 108, 67, 71, 68, 85, 85, 110, 97, 50, 89, 82, 112, 73, 117, 84, 56, 114, 120, 104, 48, 80, 66, 70, 112, 86, 88, 76, 86, 68, 118, 105, 83, 50, 65, 101, 108, 101, 116, 10, 56, 117, 53, 102, 97, 57, 73, 65, 106, 98, 107, 85, 43, 66, 81, 86, 78, 100, 110, 65, 82, 113, 78, 55, 99, 115, 105, 82, 118, 56, 108, 86, 75, 56, 51, 81, 108, 122, 54, 99, 74, 109, 84, 77, 51, 56, 54, 68, 71, 88, 72, 75, 84, 117, 98, 85, 49, 88, 117, 112, 71, 99, 49, 86, 51, 115, 106, 115, 48, 108, 52, 52, 85, 43, 86, 99, 10, 84, 52, 119, 116, 47, 108, 65, 106, 78, 118, 120, 109, 53, 115, 117, 79, 112, 68, 107, 90, 65, 76, 101, 86, 65, 106, 109, 82, 67, 119, 55, 43, 79, 67, 55, 82, 72, 81, 87, 97, 57, 107, 48, 43, 98, 119, 56, 72, 72, 97, 56, 115, 72, 111, 57, 103, 79, 101, 76, 54, 78, 108, 77, 84, 79, 100, 82, 101, 74, 105, 118, 98, 80, 97, 103, 85, 10, 118, 84, 76, 114, 71, 65, 77, 111, 85, 103, 82, 120, 53, 97, 115, 122, 80, 101, 69, 52, 117, 119, 99, 50, 104, 71, 75, 99, 101, 101, 111, 87, 77, 80, 82, 102, 119, 67, 118, 111, 99, 87, 118, 107, 43, 81, 73, 68, 65, 81, 65, 66, 111, 49, 77, 119, 85, 84, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 10, 65, 81, 72, 47, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 84, 65, 101, 112, 104, 111, 106, 89, 110, 55, 113, 119, 86, 107, 68, 66, 70, 57, 113, 110, 49, 108, 117, 77, 114, 77, 84, 106, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 84, 65, 101, 112, 104, 111, 106, 89, 110, 55, 113, 119, 86, 107, 10, 68, 66, 70, 57, 113, 110, 49, 108, 117, 77, 114, 77, 84, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 78, 101, 77, 112, 97, 117, 85, 118, 88, 86, 83, 79, 75, 86, 67, 85, 110, 53, 107, 97, 70, 79, 83, 80, 101, 67, 112, 105, 108, 75, 73, 110, 90, 53, 55, 81, 10, 122, 120, 112, 101, 82, 43, 110, 66, 115, 113, 84, 80, 51, 85, 69, 97, 66, 85, 54, 98, 83, 43, 53, 75, 98, 49, 86, 83, 115, 121, 83, 104, 78, 119, 114, 114, 90, 72, 89, 113, 76, 105, 122, 122, 47, 84, 116, 49, 107, 76, 47, 54, 99, 100, 106, 72, 80, 84, 102, 83, 116, 81, 87, 86, 89, 114, 109, 109, 51, 111, 107, 57, 78, 110, 115, 52, 10, 100, 48, 105, 88, 114, 75, 89, 103, 106, 121, 54, 109, 121, 81, 122, 67, 115, 112, 108, 70, 65, 77, 102, 79, 69, 86, 69, 105, 73, 117, 67, 108, 54, 114, 89, 86, 83, 65, 108, 107, 54, 108, 53, 80, 100, 80, 99, 70, 80, 115, 101, 75, 85, 103, 122, 98, 70, 98, 83, 57, 98, 90, 118, 108, 120, 114, 70, 85, 97, 75, 110, 106, 97, 90, 67, 50, 10, 109, 113, 85, 80, 117, 76, 107, 47, 73, 72, 50, 117, 83, 114, 87, 52, 110, 79, 81, 100, 116, 113, 118, 109, 108, 75, 88, 66, 120, 52, 79, 116, 50, 47, 85, 110, 104, 119, 52, 69, 98, 78, 88, 47, 51, 97, 66, 100, 55, 89, 100, 83, 116, 121, 115, 86, 65, 113, 52, 53, 112, 109, 112, 48, 54, 100, 114, 69, 53, 55, 120, 78, 78, 66, 54, 112, 10, 88, 69, 48, 122, 88, 53, 73, 74, 76, 52, 104, 109, 88, 88, 101, 88, 120, 120, 49, 50, 69, 54, 110, 86, 53, 102, 69, 87, 67, 82, 69, 49, 49, 97, 122, 98, 74, 72, 70, 119, 76, 74, 104, 87, 67, 57, 107, 88, 116, 78, 72, 106, 85, 83, 116, 101, 100, 101, 106, 86, 48, 78, 120, 80, 78, 79, 51, 67, 66, 87, 97, 65, 111, 99, 118, 109, 10, 77, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 101, 111, 84, 114, 117, 115, 116, 32, 71, 108, 111, 98, 97, 108, 32, 67, 65, 32, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 90, 106, 67, 67, 65, 107, 54, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 69, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 67, 104, 77, 78, 10, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 83, 87, 53, 106, 76, 106, 69, 100, 77, 66, 115, 71, 65, 49, 85, 69, 65, 120, 77, 85, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 82, 50, 120, 118, 89, 109, 70, 115, 73, 69, 78, 66, 73, 68, 73, 119, 72, 104, 99, 78, 77, 68, 81, 119, 77, 122, 65, 48, 77, 68, 85, 119, 10, 77, 68, 65, 119, 87, 104, 99, 78, 77, 84, 107, 119, 77, 122, 65, 48, 77, 68, 85, 119, 77, 68, 65, 119, 87, 106, 66, 69, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 67, 104, 77, 78, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 83, 87, 53, 106, 10, 76, 106, 69, 100, 77, 66, 115, 71, 65, 49, 85, 69, 65, 120, 77, 85, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 82, 50, 120, 118, 89, 109, 70, 115, 73, 69, 78, 66, 73, 68, 73, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 10, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 68, 118, 80, 69, 49, 65, 80, 82, 68, 102, 79, 49, 77, 65, 52, 87, 102, 43, 108, 71, 65, 86, 80, 111, 87, 73, 56, 89, 107, 78, 107, 77, 103, 111, 73, 53, 107, 70, 54, 67, 115, 103, 110, 99, 98, 122, 89, 69, 98, 89, 119, 98, 76, 86, 106, 68, 72, 90, 51, 67, 66, 53, 74, 73, 71, 47, 10, 78, 84, 76, 56, 89, 50, 110, 98, 115, 83, 112, 114, 55, 105, 70, 89, 56, 103, 106, 112, 101, 77, 116, 118, 121, 47, 119, 87, 85, 115, 105, 82, 120, 80, 56, 57, 99, 57, 54, 120, 80, 113, 102, 67, 102, 87, 98, 66, 57, 88, 53, 83, 74, 66, 114, 105, 49, 87, 101, 82, 48, 73, 73, 81, 49, 51, 104, 76, 84, 121, 116, 67, 79, 98, 49, 107, 10, 76, 85, 67, 103, 115, 66, 68, 84, 79, 69, 104, 71, 105, 75, 69, 77, 117, 122, 111, 122, 75, 109, 75, 89, 43, 119, 67, 100, 69, 49, 108, 47, 98, 122, 116, 121, 113, 117, 54, 109, 68, 52, 98, 53, 66, 87, 72, 113, 90, 51, 56, 77, 78, 53, 97, 76, 53, 109, 107, 87, 82, 120, 72, 67, 74, 49, 107, 68, 115, 54, 90, 103, 119, 105, 70, 65, 10, 86, 118, 113, 103, 120, 51, 48, 54, 69, 43, 80, 115, 86, 56, 101, 122, 49, 113, 54, 100, 105, 89, 68, 51, 65, 101, 99, 115, 57, 112, 89, 114, 69, 119, 49, 53, 76, 78, 110, 65, 53, 73, 90, 55, 83, 52, 119, 77, 99, 111, 75, 75, 43, 120, 102, 78, 65, 71, 119, 54, 69, 122, 121, 119, 104, 73, 100, 76, 70, 110, 111, 112, 115, 107, 47, 98, 10, 72, 100, 81, 76, 56, 50, 89, 51, 118, 100, 106, 50, 86, 55, 116, 101, 74, 72, 113, 52, 80, 73, 117, 53, 43, 112, 73, 97, 71, 111, 83, 101, 50, 72, 83, 80, 113, 104, 116, 47, 88, 118, 84, 43, 82, 83, 73, 104, 65, 103, 77, 66, 65, 65, 71, 106, 89, 122, 66, 104, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 10, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 72, 69, 52, 78, 118, 73, 67, 77, 86, 78, 72, 75, 50, 54, 54, 90, 85, 97, 112, 69, 66, 86, 89, 73, 65, 85, 74, 77, 66, 56, 71, 65, 49, 85, 100, 73, 119, 81, 89, 77, 66, 97, 65, 70, 72, 69, 52, 78, 118, 73, 67, 77, 86, 78, 72, 10, 75, 50, 54, 54, 90, 85, 97, 112, 69, 66, 86, 89, 73, 65, 85, 74, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 104, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 65, 47, 101, 49, 75, 54, 116, 100, 69, 80, 120, 55, 10, 115, 114, 74, 101, 114, 74, 115, 79, 102, 108, 78, 52, 87, 84, 53, 67, 66, 80, 53, 49, 111, 54, 50, 115, 103, 85, 55, 88, 65, 111, 116, 101, 120, 67, 51, 73, 85, 110, 98, 72, 76, 66, 47, 56, 103, 84, 75, 89, 48, 85, 118, 71, 107, 112, 77, 122, 78, 84, 69, 118, 47, 78, 103, 100, 82, 78, 51, 103, 103, 88, 43, 100, 54, 89, 118, 104, 10, 90, 74, 70, 105, 67, 122, 107, 73, 106, 75, 120, 48, 110, 86, 110, 90, 101, 108, 108, 83, 108, 120, 71, 53, 70, 110, 116, 118, 82, 100, 79, 87, 50, 84, 70, 57, 65, 106, 89, 80, 110, 68, 116, 117, 122, 121, 119, 78, 65, 48, 90, 70, 54, 54, 68, 48, 102, 48, 104, 69, 120, 103, 104, 65, 122, 78, 52, 98, 99, 76, 85, 112, 114, 98, 113, 76, 10, 79, 122, 82, 108, 100, 82, 116, 120, 73, 82, 48, 115, 70, 65, 113, 119, 108, 112, 87, 52, 49, 117, 114, 121, 90, 102, 115, 112, 117, 107, 47, 113, 107, 90, 78, 48, 97, 98, 98, 121, 47, 43, 69, 97, 48, 65, 122, 82, 100, 111, 88, 76, 105, 105, 87, 57, 108, 49, 52, 115, 98, 120, 87, 90, 74, 117, 101, 50, 75, 102, 56, 105, 55, 77, 107, 67, 10, 120, 49, 89, 65, 122, 85, 109, 53, 115, 50, 120, 55, 85, 119, 81, 97, 52, 113, 106, 74, 113, 104, 73, 70, 73, 56, 76, 79, 53, 55, 115, 69, 65, 115, 122, 65, 82, 54, 76, 107, 120, 67, 107, 118, 87, 48, 86, 88, 105, 86, 72, 117, 80, 79, 116, 83, 67, 80, 56, 72, 78, 82, 54, 102, 78, 87, 112, 72, 83, 108, 97, 89, 48, 86, 113, 70, 10, 72, 52, 122, 49, 73, 114, 43, 114, 122, 111, 80, 122, 52, 105, 73, 112, 114, 110, 50, 68, 81, 75, 105, 54, 98, 65, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 101, 111, 84, 114, 117, 115, 116, 32, 85, 110, 105, 118, 101, 114, 115, 97, 108, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 97, 68, 67, 67, 65, 49, 67, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 70, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 67, 104, 77, 78, 10, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 83, 87, 53, 106, 76, 106, 69, 101, 77, 66, 119, 71, 65, 49, 85, 69, 65, 120, 77, 86, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 86, 87, 53, 112, 100, 109, 86, 121, 99, 50, 70, 115, 73, 69, 78, 66, 77, 66, 52, 88, 68, 84, 65, 48, 77, 68, 77, 119, 78, 68, 65, 49, 10, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 73, 53, 77, 68, 77, 119, 78, 68, 65, 49, 77, 68, 65, 119, 77, 70, 111, 119, 82, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 106, 65, 85, 66, 103, 78, 86, 66, 65, 111, 84, 68, 85, 100, 108, 98, 49, 82, 121, 100, 88, 78, 48, 73, 69, 108, 117, 10, 89, 121, 52, 120, 72, 106, 65, 99, 66, 103, 78, 86, 66, 65, 77, 84, 70, 85, 100, 108, 98, 49, 82, 121, 100, 88, 78, 48, 73, 70, 86, 117, 97, 88, 90, 108, 99, 110, 78, 104, 98, 67, 66, 68, 81, 84, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 10, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 75, 89, 86, 86, 97, 67, 106, 120, 117, 65, 102, 106, 74, 48, 104, 85, 78, 102, 66, 118, 105, 116, 98, 116, 97, 83, 101, 111, 100, 108, 121, 87, 76, 48, 65, 71, 48, 121, 47, 89, 99, 107, 85, 72, 85, 87, 67, 113, 56, 89, 100, 103, 78, 89, 57, 54, 120, 67, 99, 79, 113, 57, 116, 10, 74, 80, 105, 56, 99, 81, 71, 101, 66, 118, 86, 56, 88, 120, 55, 66, 68, 108, 88, 75, 103, 53, 112, 90, 77, 75, 52, 90, 121, 122, 66, 73, 108, 101, 48, 105, 78, 52, 51, 48, 83, 112, 112, 121, 90, 106, 54, 116, 108, 99, 68, 103, 70, 103, 68, 103, 69, 66, 56, 114, 77, 81, 55, 88, 108, 70, 84, 84, 81, 106, 79, 103, 78, 66, 48, 101, 10, 82, 88, 98, 100, 84, 56, 111, 89, 78, 43, 121, 70, 70, 88, 111, 90, 67, 80, 122, 86, 120, 53, 122, 119, 56, 113, 107, 117, 69, 75, 109, 83, 53, 106, 49, 89, 80, 97, 107, 87, 97, 68, 119, 118, 100, 83, 69, 89, 102, 121, 104, 51, 112, 101, 70, 104, 70, 55, 101, 109, 54, 102, 103, 101, 109, 100, 116, 122, 98, 118, 81, 75, 111, 105, 70, 115, 10, 55, 116, 113, 113, 104, 90, 74, 109, 114, 47, 90, 54, 97, 52, 76, 97, 117, 105, 73, 73, 78, 81, 47, 80, 81, 118, 69, 49, 43, 109, 114, 117, 102, 105, 115, 108, 122, 68, 111, 82, 53, 71, 50, 118, 99, 55, 74, 50, 72, 97, 51, 81, 115, 110, 104, 110, 71, 113, 81, 53, 72, 70, 69, 76, 90, 49, 97, 68, 47, 84, 104, 100, 68, 99, 55, 100, 10, 56, 76, 115, 114, 108, 104, 47, 101, 101, 122, 74, 83, 47, 82, 50, 55, 116, 81, 97, 104, 115, 105, 70, 101, 112, 100, 97, 86, 97, 72, 47, 119, 109, 90, 55, 99, 82, 81, 103, 43, 53, 57, 73, 74, 68, 84, 87, 85, 51, 89, 66, 79, 85, 53, 102, 88, 116, 81, 108, 69, 73, 71, 81, 87, 70, 119, 77, 67, 84, 70, 77, 78, 97, 78, 55, 86, 10, 113, 110, 74, 78, 107, 50, 50, 67, 68, 116, 117, 99, 118, 99, 43, 48, 56, 49, 120, 100, 86, 72, 112, 112, 67, 90, 98, 87, 50, 120, 72, 66, 106, 88, 87, 111, 116, 77, 56, 53, 121, 77, 52, 56, 118, 67, 82, 56, 53, 109, 76, 75, 52, 98, 49, 57, 112, 55, 49, 88, 90, 81, 118, 107, 47, 105, 88, 116, 116, 109, 107, 81, 51, 67, 103, 97, 10, 82, 114, 48, 66, 72, 100, 67, 88, 116, 101, 71, 89, 79, 56, 65, 51, 90, 78, 89, 57, 108, 79, 52, 76, 52, 102, 85, 111, 114, 103, 116, 87, 118, 51, 71, 76, 73, 121, 108, 66, 106, 111, 98, 70, 83, 49, 74, 55, 50, 72, 71, 114, 72, 52, 111, 86, 112, 106, 117, 68, 87, 116, 100, 89, 65, 86, 72, 71, 84, 69, 72, 90, 102, 57, 104, 66, 10, 90, 51, 75, 105, 75, 78, 57, 103, 103, 54, 109, 101, 121, 72, 118, 56, 85, 51, 78, 121, 87, 102, 87, 84, 101, 104, 100, 50, 68, 115, 55, 51, 53, 86, 122, 90, 67, 49, 85, 48, 111, 113, 112, 98, 116, 87, 112, 85, 53, 120, 80, 75, 86, 43, 121, 88, 98, 102, 82, 101, 66, 105, 57, 70, 105, 49, 106, 85, 73, 120, 97, 83, 53, 66, 90, 117, 10, 75, 71, 78, 90, 77, 78, 57, 81, 65, 90, 120, 106, 105, 82, 113, 102, 50, 120, 101, 85, 103, 110, 65, 51, 119, 121, 83, 101, 109, 107, 102, 87, 87, 115, 112, 79, 113, 71, 109, 74, 99, 104, 43, 82, 98, 78, 116, 43, 110, 104, 117, 116, 120, 120, 57, 122, 51, 83, 120, 80, 71, 87, 88, 57, 102, 53, 78, 65, 69, 67, 55, 83, 56, 79, 48, 56, 10, 110, 105, 52, 111, 80, 109, 107, 109, 77, 56, 86, 55, 65, 103, 77, 66, 65, 65, 71, 106, 89, 122, 66, 104, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 78, 113, 55, 76, 113, 113, 119, 68, 76, 105, 73, 74, 108, 70, 48, 10, 88, 71, 48, 68, 48, 56, 68, 89, 106, 51, 114, 87, 77, 66, 56, 71, 65, 49, 85, 100, 73, 119, 81, 89, 77, 66, 97, 65, 70, 78, 113, 55, 76, 113, 113, 119, 68, 76, 105, 73, 74, 108, 70, 48, 88, 71, 48, 68, 48, 56, 68, 89, 106, 51, 114, 87, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 10, 104, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 103, 69, 65, 77, 88, 106, 109, 120, 55, 88, 102, 117, 74, 82, 65, 121, 88, 72, 69, 113, 68, 88, 115, 82, 104, 51, 67, 104, 102, 77, 111, 87, 73, 97, 119, 67, 47, 121, 79, 115, 106, 109, 80, 82, 70, 87, 114, 90, 73, 82, 99, 10, 97, 97, 110, 81, 109, 106, 103, 56, 43, 117, 85, 102, 78, 101, 86, 69, 52, 52, 66, 53, 108, 71, 105, 107, 117, 56, 83, 102, 80, 101, 69, 48, 122, 84, 66, 71, 105, 49, 81, 114, 108, 97, 88, 118, 57, 122, 43, 90, 104, 80, 48, 49, 53, 115, 56, 120, 120, 116, 120, 113, 118, 54, 102, 88, 73, 119, 106, 104, 109, 70, 55, 68, 87, 103, 104, 50, 10, 113, 97, 97, 118, 100, 121, 43, 51, 89, 76, 49, 69, 82, 109, 114, 118, 108, 47, 57, 122, 108, 99, 71, 79, 54, 74, 80, 55, 47, 84, 71, 51, 55, 70, 99, 82, 69, 85, 87, 98, 77, 80, 69, 97, 105, 68, 110, 66, 84, 122, 121, 110, 65, 78, 88, 72, 47, 75, 116, 116, 103, 67, 74, 119, 112, 81, 122, 103, 88, 81, 81, 112, 65, 118, 118, 76, 10, 111, 74, 72, 82, 102, 78, 98, 68, 102, 108, 68, 86, 110, 86, 105, 43, 81, 84, 106, 114, 117, 88, 85, 56, 70, 100, 109, 98, 121, 85, 113, 68, 87, 99, 68, 97, 85, 47, 48, 122, 117, 122, 89, 89, 109, 52, 85, 80, 70, 100, 51, 117, 76, 97, 120, 50, 107, 55, 110, 90, 65, 89, 49, 73, 69, 75, 106, 55, 57, 84, 105, 71, 56, 100, 115, 75, 10, 120, 114, 50, 69, 111, 121, 78, 66, 51, 116, 90, 51, 98, 52, 88, 85, 104, 82, 120, 81, 52, 75, 53, 82, 105, 114, 113, 78, 80, 110, 98, 105, 117, 99, 111, 110, 56, 108, 43, 102, 55, 50, 53, 90, 68, 81, 98, 89, 75, 120, 101, 107, 48, 110, 120, 114, 117, 49, 56, 85, 71, 107, 105, 80, 71, 107, 122, 110, 115, 48, 99, 99, 106, 107, 120, 70, 10, 75, 121, 68, 117, 83, 78, 47, 110, 51, 81, 109, 79, 71, 75, 106, 97, 81, 73, 50, 83, 74, 104, 70, 84, 89, 88, 78, 100, 54, 55, 51, 110, 120, 69, 48, 112, 78, 50, 72, 114, 114, 68, 107, 116, 90, 121, 52, 87, 49, 118, 85, 65, 103, 52, 87, 104, 122, 72, 57, 50, 120, 72, 51, 107, 116, 48, 116, 109, 55, 119, 78, 70, 89, 71, 109, 50, 10, 68, 70, 75, 87, 107, 111, 82, 101, 112, 113, 79, 49, 112, 68, 52, 114, 50, 99, 122, 89, 71, 48, 101, 113, 56, 107, 84, 97, 84, 47, 107, 68, 54, 80, 65, 85, 121, 122, 47, 122, 103, 57, 55, 81, 119, 86, 84, 106, 116, 43, 103, 75, 78, 48, 50, 76, 73, 70, 107, 68, 77, 66, 109, 104, 76, 77, 105, 57, 69, 82, 47, 102, 114, 115, 108, 75, 10, 120, 102, 77, 110, 90, 109, 97, 71, 114, 71, 105, 82, 47, 57, 110, 109, 85, 120, 119, 80, 105, 49, 120, 112, 90, 81, 111, 109, 121, 66, 52, 48, 119, 49, 49, 82, 101, 57, 101, 112, 110, 65, 97, 104, 78, 116, 51, 86, 105, 90, 83, 56, 50, 101, 81, 116, 68, 70, 52, 74, 98, 65, 105, 88, 102, 75, 77, 57, 102, 74, 80, 47, 80, 54, 69, 85, 10, 112, 56, 43, 49, 88, 101, 118, 98, 50, 120, 122, 69, 100, 116, 43, 73, 117, 98, 49, 70, 66, 90, 85, 98, 114, 118, 120, 71, 97, 107, 121, 118, 83, 79, 80, 79, 114, 103, 47, 83, 102, 117, 118, 109, 98, 74, 120, 80, 103, 87, 112, 54, 90, 75, 121, 55, 80, 116, 88, 110, 121, 51, 89, 117, 120, 97, 100, 73, 119, 86, 121, 81, 68, 56, 118, 73, 10, 80, 47, 114, 109, 77, 117, 71, 78, 71, 50, 43, 107, 53, 111, 55, 89, 43, 83, 108, 73, 105, 115, 53, 122, 47, 105, 119, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 101, 111, 84, 114, 117, 115, 116, 32, 85, 110, 105, 118, 101, 114, 115, 97, 108, 32, 67, 65, 32, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 98, 68, 67, 67, 65, 49, 83, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 72, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 67, 104, 77, 78, 10, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 83, 87, 53, 106, 76, 106, 69, 103, 77, 66, 52, 71, 65, 49, 85, 69, 65, 120, 77, 88, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 86, 87, 53, 112, 100, 109, 86, 121, 99, 50, 70, 115, 73, 69, 78, 66, 73, 68, 73, 119, 72, 104, 99, 78, 77, 68, 81, 119, 77, 122, 65, 48, 10, 77, 68, 85, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 106, 107, 119, 77, 122, 65, 48, 77, 68, 85, 119, 77, 68, 65, 119, 87, 106, 66, 72, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 67, 104, 77, 78, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 10, 83, 87, 53, 106, 76, 106, 69, 103, 77, 66, 52, 71, 65, 49, 85, 69, 65, 120, 77, 88, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 86, 87, 53, 112, 100, 109, 86, 121, 99, 50, 70, 115, 73, 69, 78, 66, 73, 68, 73, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 10, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 122, 86, 70, 76, 66, 121, 84, 55, 121, 50, 100, 121, 120, 85, 120, 112, 90, 75, 101, 101, 120, 119, 48, 85, 111, 53, 100, 102, 82, 55, 99, 88, 70, 83, 54, 71, 113, 100, 72, 116, 88, 114, 48, 111, 109, 47, 78, 106, 49, 88, 113, 100, 117, 71, 100, 116, 48, 10, 68, 69, 56, 49, 87, 122, 73, 76, 65, 101, 80, 98, 54, 51, 112, 51, 78, 101, 113, 113, 87, 117, 68, 87, 54, 75, 70, 88, 108, 80, 67, 81, 111, 51, 82, 87, 108, 69, 81, 119, 65, 120, 53, 99, 84, 105, 117, 70, 74, 110, 83, 67, 101, 103, 120, 50, 111, 71, 57, 78, 122, 107, 69, 116, 111, 66, 85, 71, 70, 70, 43, 51, 81, 115, 49, 55, 10, 106, 49, 104, 104, 78, 78, 119, 113, 67, 80, 107, 117, 119, 119, 71, 109, 73, 107, 81, 99, 84, 65, 101, 67, 53, 108, 118, 79, 48, 69, 112, 56, 66, 78, 77, 90, 99, 121, 102, 119, 113, 112, 104, 47, 76, 113, 57, 79, 54, 52, 99, 101, 74, 72, 100, 113, 88, 98, 98, 111, 87, 48, 87, 54, 51, 77, 79, 104, 66, 87, 57, 87, 106, 111, 56, 81, 10, 74, 113, 86, 74, 119, 121, 55, 88, 81, 89, 99, 105, 52, 69, 43, 71, 121, 109, 67, 49, 54, 113, 70, 106, 119, 65, 71, 88, 69, 72, 109, 57, 65, 68, 119, 83, 98, 83, 115, 86, 115, 97, 120, 76, 115, 101, 52, 89, 117, 85, 54, 87, 51, 78, 120, 50, 47, 122, 117, 43, 122, 49, 56, 68, 119, 80, 119, 55, 54, 76, 53, 71, 71, 47, 47, 97, 10, 81, 77, 74, 83, 57, 47, 55, 106, 79, 118, 100, 113, 100, 122, 88, 81, 50, 111, 51, 114, 88, 104, 104, 113, 77, 99, 99, 101, 117, 106, 119, 98, 75, 78, 90, 114, 86, 77, 97, 113, 87, 57, 101, 105, 76, 66, 115, 90, 122, 75, 73, 67, 57, 112, 116, 90, 118, 84, 100, 114, 104, 114, 86, 116, 103, 114, 114, 89, 54, 115, 108, 87, 118, 75, 107, 50, 10, 87, 80, 48, 43, 71, 102, 80, 116, 68, 67, 97, 112, 107, 122, 106, 52, 84, 56, 70, 100, 73, 103, 98, 81, 108, 43, 114, 104, 114, 99, 90, 86, 52, 73, 69, 114, 75, 73, 77, 54, 43, 118, 82, 55, 73, 86, 69, 65, 118, 108, 73, 52, 122, 115, 49, 109, 101, 97, 106, 48, 103, 86, 98, 105, 48, 73, 77, 74, 82, 49, 70, 98, 85, 71, 114, 80, 10, 50, 48, 103, 97, 88, 84, 55, 51, 121, 47, 90, 108, 57, 50, 122, 120, 108, 102, 103, 67, 79, 122, 74, 87, 103, 106, 108, 54, 87, 55, 48, 118, 105, 82, 117, 47, 111, 98, 84, 111, 47, 51, 43, 78, 106, 78, 56, 68, 56, 87, 66, 79, 87, 66, 70, 77, 54, 54, 77, 47, 69, 67, 117, 68, 109, 103, 70, 122, 50, 90, 82, 116, 104, 65, 65, 110, 10, 90, 113, 122, 119, 99, 69, 65, 74, 81, 112, 75, 116, 84, 53, 77, 78, 89, 81, 108, 82, 74, 78, 105, 83, 49, 81, 117, 85, 89, 98, 75, 72, 115, 117, 51, 47, 109, 106, 88, 47, 104, 86, 84, 75, 55, 85, 82, 68, 114, 66, 115, 56, 70, 109, 116, 73, 83, 103, 111, 99, 81, 73, 103, 102, 107, 115, 73, 76, 65, 65, 88, 47, 56, 115, 103, 67, 10, 83, 113, 83, 113, 113, 99, 121, 90, 108, 112, 119, 118, 87, 79, 66, 57, 52, 98, 54, 55, 66, 57, 120, 102, 66, 72, 74, 99, 77, 84, 84, 68, 55, 70, 56, 116, 52, 68, 49, 107, 107, 67, 76, 109, 48, 101, 121, 52, 76, 116, 49, 90, 114, 116, 109, 104, 78, 55, 57, 85, 78, 100, 120, 122, 77, 107, 43, 77, 66, 66, 52, 122, 115, 115, 108, 71, 10, 56, 100, 104, 99, 121, 70, 86, 81, 121, 87, 105, 57, 113, 76, 111, 50, 67, 81, 73, 68, 65, 81, 65, 66, 111, 50, 77, 119, 89, 84, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 50, 56, 49, 88, 104, 43, 113, 81, 50, 10, 43, 47, 67, 102, 88, 71, 74, 120, 55, 84, 122, 48, 82, 122, 103, 81, 75, 122, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 82, 50, 56, 49, 88, 104, 43, 113, 81, 50, 43, 47, 67, 102, 88, 71, 74, 120, 55, 84, 122, 48, 82, 122, 103, 81, 75, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 10, 66, 65, 77, 67, 65, 89, 89, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 73, 66, 65, 71, 98, 66, 120, 105, 80, 122, 50, 101, 65, 117, 98, 108, 47, 111, 122, 54, 54, 119, 115, 67, 86, 78, 75, 47, 103, 55, 87, 74, 116, 65, 74, 68, 100, 97, 121, 54, 115, 87, 83, 102, 43, 122, 10, 100, 88, 107, 122, 111, 83, 57, 116, 99, 66, 99, 48, 107, 102, 53, 110, 102, 111, 47, 115, 109, 43, 86, 101, 103, 113, 108, 86, 72, 121, 47, 99, 49, 70, 69, 72, 69, 118, 54, 115, 70, 106, 52, 115, 78, 99, 90, 106, 47, 78, 119, 81, 54, 119, 50, 106, 113, 116, 66, 56, 122, 78, 72, 81, 76, 49, 69, 117, 120, 66, 82, 97, 51, 117, 103, 90, 10, 52, 84, 55, 71, 122, 75, 81, 112, 53, 121, 54, 69, 113, 103, 89, 119, 101, 72, 90, 85, 99, 121, 105, 89, 87, 84, 106, 103, 65, 65, 49, 105, 48, 48, 74, 57, 73, 90, 43, 117, 80, 84, 113, 77, 49, 102, 112, 51, 68, 82, 103, 114, 70, 103, 53, 102, 78, 117, 72, 56, 75, 114, 85, 119, 74, 77, 47, 103, 89, 119, 120, 55, 87, 66, 114, 43, 10, 109, 98, 112, 67, 69, 114, 71, 82, 57, 72, 120, 111, 52, 115, 106, 111, 114, 121, 122, 113, 121, 88, 54, 117, 117, 121, 111, 57, 68, 82, 88, 99, 78, 74, 87, 50, 71, 72, 83, 111, 97, 103, 47, 72, 116, 80, 81, 84, 120, 79, 82, 98, 55, 81, 114, 83, 112, 74, 100, 77, 75, 117, 48, 118, 98, 66, 75, 74, 80, 102, 69, 110, 99, 75, 112, 113, 10, 65, 49, 73, 104, 110, 48, 67, 111, 90, 49, 68, 121, 56, 49, 111, 102, 51, 57, 56, 106, 57, 116, 120, 52, 84, 117, 97, 89, 84, 49, 85, 54, 85, 43, 80, 118, 56, 118, 83, 102, 120, 51, 122, 89, 87, 75, 56, 112, 73, 112, 101, 52, 52, 76, 50, 82, 76, 114, 66, 50, 55, 70, 99, 82, 122, 43, 56, 112, 82, 80, 80, 112, 104, 88, 112, 103, 10, 89, 43, 82, 100, 77, 52, 107, 88, 50, 84, 71, 113, 50, 116, 98, 122, 71, 68, 86, 121, 122, 52, 99, 114, 76, 50, 77, 106, 104, 70, 50, 69, 106, 68, 57, 88, 111, 73, 106, 56, 109, 90, 69, 111, 74, 109, 109, 90, 49, 73, 43, 88, 82, 76, 54, 79, 49, 85, 105, 120, 112, 67, 103, 112, 56, 82, 87, 48, 52, 101, 87, 101, 51, 102, 105, 80, 10, 112, 109, 56, 109, 49, 119, 107, 56, 79, 104, 119, 82, 68, 113, 90, 115, 78, 47, 101, 116, 82, 73, 99, 115, 75, 77, 102, 89, 100, 73, 75, 122, 48, 71, 57, 75, 86, 55, 115, 49, 75, 83, 101, 103, 105, 43, 103, 104, 112, 52, 100, 107, 78, 108, 51, 77, 50, 66, 97, 115, 120, 55, 73, 110, 81, 74, 74, 86, 79, 67, 105, 78, 85, 87, 55, 100, 10, 70, 71, 100, 84, 98, 72, 70, 99, 74, 111, 82, 78, 100, 86, 113, 50, 102, 109, 66, 87, 113, 85, 50, 116, 43, 53, 115, 101, 108, 47, 77, 78, 50, 100, 75, 88, 86, 72, 102, 97, 80, 82, 75, 51, 52, 66, 55, 118, 67, 65, 97, 115, 43, 89, 87, 72, 54, 97, 76, 99, 114, 51, 52, 89, 69, 111, 80, 57, 86, 104, 100, 66, 76, 116, 85, 112, 10, 103, 110, 50, 90, 57, 68, 72, 50, 99, 97, 110, 80, 76, 65, 69, 110, 112, 81, 87, 53, 113, 114, 74, 73, 84, 105, 114, 118, 110, 53, 78, 83, 85, 90, 85, 56, 85, 110, 79, 79, 86, 107, 119, 88, 81, 77, 65, 74, 75, 79, 83, 76, 97, 107, 104, 84, 50, 43, 122, 78, 86, 86, 88, 120, 120, 118, 106, 112, 111, 105, 120, 77, 112, 116, 69, 109, 10, 88, 51, 54, 118, 87, 107, 122, 97, 72, 54, 98, 121, 72, 67, 120, 43, 114, 103, 73, 87, 48, 108, 98, 81, 76, 49, 100, 84, 82, 43, 105, 83, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 86, 105, 115, 97, 32, 101, 67, 111, 109, 109, 101, 114, 99, 101, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 111, 106, 67, 67, 65, 111, 113, 103, 65, 119, 73, 66, 65, 103, 73, 81, 69, 52, 89, 49, 84, 82, 48, 47, 66, 118, 76, 66, 43, 87, 85, 70, 49, 90, 65, 99, 89, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 114, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 78, 77, 65, 115, 71, 65, 49, 85, 69, 67, 104, 77, 69, 86, 107, 108, 84, 81, 84, 69, 118, 77, 67, 48, 71, 65, 49, 85, 69, 67, 120, 77, 109, 86, 109, 108, 122, 89, 83, 66, 74, 98, 110, 82, 108, 99, 109, 53, 104, 100, 71, 108, 118, 98, 109, 70, 115, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 85, 103, 10, 81, 88, 78, 122, 98, 50, 78, 112, 89, 88, 82, 112, 98, 50, 52, 120, 72, 68, 65, 97, 66, 103, 78, 86, 66, 65, 77, 84, 69, 49, 90, 112, 99, 50, 69, 103, 90, 85, 78, 118, 98, 87, 49, 108, 99, 109, 78, 108, 73, 70, 74, 118, 98, 51, 81, 119, 72, 104, 99, 78, 77, 68, 73, 119, 78, 106, 73, 50, 77, 68, 73, 120, 79, 68, 77, 50, 10, 87, 104, 99, 78, 77, 106, 73, 119, 78, 106, 73, 48, 77, 68, 65, 120, 78, 106, 69, 121, 87, 106, 66, 114, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 78, 77, 65, 115, 71, 65, 49, 85, 69, 67, 104, 77, 69, 86, 107, 108, 84, 81, 84, 69, 118, 77, 67, 48, 71, 65, 49, 85, 69, 67, 120, 77, 109, 10, 86, 109, 108, 122, 89, 83, 66, 74, 98, 110, 82, 108, 99, 109, 53, 104, 100, 71, 108, 118, 98, 109, 70, 115, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 85, 103, 81, 88, 78, 122, 98, 50, 78, 112, 89, 88, 82, 112, 98, 50, 52, 120, 72, 68, 65, 97, 66, 103, 78, 86, 66, 65, 77, 84, 69, 49, 90, 112, 99, 50, 69, 103, 90, 85, 78, 118, 10, 98, 87, 49, 108, 99, 109, 78, 108, 73, 70, 74, 118, 98, 51, 81, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 118, 86, 57, 53, 87, 72, 109, 54, 104, 50, 109, 67, 120, 108, 67, 102, 76, 10, 70, 57, 115, 72, 80, 52, 67, 70, 84, 56, 105, 99, 116, 116, 68, 48, 98, 48, 47, 80, 109, 100, 106, 104, 50, 56, 74, 73, 88, 68, 113, 115, 79, 84, 80, 72, 72, 50, 113, 76, 74, 106, 48, 114, 78, 102, 86, 73, 115, 90, 72, 66, 65, 107, 52, 69, 108, 112, 70, 55, 115, 68, 80, 119, 115, 82, 82, 79, 69, 87, 43, 49, 81, 75, 56, 98, 10, 82, 97, 86, 75, 55, 51, 54, 50, 114, 80, 75, 103, 72, 49, 103, 47, 69, 107, 90, 103, 80, 73, 50, 104, 52, 72, 51, 80, 86, 122, 52, 122, 72, 118, 116, 72, 56, 97, 111, 86, 108, 119, 100, 86, 90, 113, 87, 49, 76, 83, 55, 89, 103, 70, 109, 121, 112, 119, 50, 51, 82, 117, 119, 104, 89, 47, 56, 49, 113, 54, 85, 67, 122, 121, 114, 48, 10, 84, 80, 53, 55, 57, 90, 82, 100, 104, 69, 50, 111, 56, 109, 67, 80, 50, 119, 52, 108, 80, 74, 57, 122, 99, 99, 43, 85, 51, 48, 114, 113, 50, 57, 57, 121, 79, 73, 122, 122, 108, 114, 51, 120, 70, 55, 122, 83, 117, 106, 116, 70, 87, 115, 97, 110, 57, 115, 89, 88, 105, 119, 71, 100, 47, 66, 109, 111, 75, 111, 77, 87, 117, 68, 112, 73, 10, 47, 107, 52, 43, 111, 75, 115, 71, 71, 101, 108, 84, 56, 52, 65, 84, 66, 43, 48, 116, 118, 122, 56, 75, 80, 70, 85, 103, 79, 83, 119, 115, 65, 71, 108, 48, 108, 85, 113, 56, 73, 76, 75, 112, 101, 101, 85, 89, 105, 90, 71, 111, 51, 66, 120, 78, 55, 55, 116, 43, 78, 119, 116, 100, 47, 106, 109, 108, 105, 70, 75, 77, 65, 71, 122, 115, 10, 71, 72, 120, 66, 118, 102, 97, 76, 100, 88, 101, 54, 89, 74, 50, 69, 53, 47, 52, 116, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 10, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 81, 86, 79, 73, 77, 80, 80, 121, 119, 47, 99, 68, 77, 101, 122, 85, 98, 43, 66, 52, 119, 103, 52, 78, 102, 68, 116, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 88, 47, 70, 66, 102, 88, 120, 99, 10, 67, 76, 107, 114, 52, 78, 87, 83, 82, 47, 112, 110, 88, 75, 85, 84, 119, 119, 77, 104, 109, 121, 116, 77, 105, 85, 98, 80, 87, 85, 51, 74, 47, 113, 86, 65, 116, 109, 80, 78, 51, 88, 69, 111, 108, 87, 99, 82, 122, 67, 83, 115, 48, 48, 82, 115, 99, 97, 52, 66, 73, 71, 115, 68, 111, 111, 56, 89, 116, 121, 107, 54, 102, 101, 85, 87, 10, 89, 70, 78, 52, 80, 77, 67, 118, 70, 89, 80, 51, 106, 49, 73, 122, 74, 76, 49, 107, 107, 53, 102, 117, 105, 47, 102, 98, 71, 75, 104, 116, 99, 98, 80, 51, 76, 66, 102, 81, 100, 67, 86, 112, 57, 47, 53, 114, 80, 74, 83, 43, 84, 85, 116, 66, 106, 69, 55, 105, 99, 57, 68, 106, 107, 67, 74, 122, 81, 56, 51, 122, 55, 43, 112, 122, 10, 122, 107, 87, 75, 115, 75, 90, 74, 47, 48, 120, 57, 110, 88, 71, 73, 120, 72, 89, 100, 107, 70, 115, 100, 55, 118, 51, 77, 57, 43, 55, 57, 89, 75, 87, 120, 101, 104, 90, 120, 48, 82, 98, 81, 102, 66, 73, 56, 98, 71, 109, 88, 50, 54, 53, 102, 79, 90, 112, 119, 76, 119, 85, 56, 71, 85, 89, 69, 109, 83, 65, 50, 48, 71, 66, 117, 10, 89, 81, 97, 55, 70, 107, 75, 77, 99, 80, 99, 119, 43, 43, 68, 98, 90, 113, 77, 65, 65, 98, 51, 109, 76, 78, 113, 82, 88, 54, 66, 71, 105, 48, 49, 113, 110, 68, 48, 57, 51, 81, 86, 71, 47, 110, 97, 47, 111, 65, 111, 56, 53, 65, 68, 109, 74, 55, 102, 47, 104, 67, 51, 101, 117, 105, 73, 110, 108, 104, 66, 120, 54, 121, 76, 116, 10, 51, 57, 56, 122, 110, 77, 47, 106, 114, 97, 54, 79, 49, 73, 55, 109, 84, 49, 71, 118, 70, 112, 76, 103, 88, 80, 89, 72, 68, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 101, 114, 116, 117, 109, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 68, 68, 67, 67, 65, 102, 83, 103, 65, 119, 73, 66, 65, 103, 73, 68, 65, 81, 65, 103, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 77, 68, 52, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 66, 77, 77, 82, 115, 119, 71, 81, 89, 68, 86, 81, 81, 75, 10, 69, 120, 74, 86, 98, 109, 108, 54, 90, 88, 82, 118, 73, 70, 78, 119, 76, 105, 66, 54, 73, 71, 56, 117, 98, 121, 52, 120, 69, 106, 65, 81, 66, 103, 78, 86, 66, 65, 77, 84, 67, 85, 78, 108, 99, 110, 82, 49, 98, 83, 66, 68, 81, 84, 65, 101, 70, 119, 48, 119, 77, 106, 65, 50, 77, 84, 69, 120, 77, 68, 81, 50, 77, 122, 108, 97, 10, 70, 119, 48, 121, 78, 122, 65, 50, 77, 84, 69, 120, 77, 68, 81, 50, 77, 122, 108, 97, 77, 68, 52, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 66, 77, 77, 82, 115, 119, 71, 81, 89, 68, 86, 81, 81, 75, 69, 120, 74, 86, 98, 109, 108, 54, 90, 88, 82, 118, 73, 70, 78, 119, 76, 105, 66, 54, 73, 71, 56, 117, 10, 98, 121, 52, 120, 69, 106, 65, 81, 66, 103, 78, 86, 66, 65, 77, 84, 67, 85, 78, 108, 99, 110, 82, 49, 98, 83, 66, 68, 81, 84, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 77, 54, 120, 10, 119, 83, 55, 84, 84, 51, 122, 78, 74, 99, 52, 89, 80, 107, 47, 69, 106, 71, 43, 65, 97, 110, 80, 73, 87, 49, 72, 52, 109, 57, 76, 99, 117, 119, 66, 99, 115, 97, 68, 56, 100, 81, 80, 117, 103, 102, 67, 73, 55, 105, 78, 83, 54, 101, 89, 86, 77, 52, 50, 115, 76, 81, 110, 70, 100, 118, 107, 114, 79, 89, 67, 74, 53, 74, 100, 76, 10, 107, 75, 87, 111, 101, 80, 104, 122, 81, 51, 117, 107, 89, 98, 68, 89, 87, 77, 122, 104, 98, 71, 90, 43, 110, 80, 77, 74, 88, 108, 86, 106, 104, 78, 87, 111, 55, 47, 79, 120, 76, 106, 66, 111, 115, 56, 81, 56, 50, 75, 120, 117, 106, 90, 108, 97, 107, 69, 52, 48, 51, 68, 97, 97, 106, 52, 71, 73, 85, 76, 100, 116, 108, 107, 73, 74, 10, 56, 57, 101, 86, 103, 119, 49, 66, 83, 55, 66, 113, 97, 47, 106, 56, 68, 51, 53, 105, 110, 50, 102, 69, 55, 83, 90, 102, 69, 67, 89, 80, 67, 69, 47, 119, 112, 70, 99, 111, 122, 111, 43, 52, 55, 85, 88, 50, 98, 117, 52, 108, 88, 97, 112, 117, 79, 98, 55, 107, 107, 121, 47, 90, 82, 54, 66, 121, 54, 47, 113, 109, 87, 54, 47, 75, 10, 85, 122, 47, 105, 68, 115, 97, 87, 86, 104, 70, 117, 57, 43, 108, 109, 113, 83, 98, 89, 102, 53, 86, 84, 55, 81, 113, 70, 105, 76, 112, 80, 75, 97, 86, 67, 106, 70, 54, 50, 47, 73, 85, 103, 65, 75, 112, 111, 67, 54, 69, 97, 104, 81, 71, 99, 120, 69, 90, 106, 103, 111, 105, 50, 73, 114, 72, 117, 47, 113, 112, 71, 87, 88, 55, 80, 10, 78, 83, 122, 86, 116, 116, 112, 100, 57, 48, 103, 122, 70, 70, 83, 50, 54, 57, 108, 118, 122, 115, 50, 73, 49, 113, 115, 98, 50, 112, 89, 55, 72, 86, 107, 67, 65, 119, 69, 65, 65, 97, 77, 84, 77, 66, 69, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 78, 66, 103, 107, 113, 10, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 117, 73, 51, 79, 55, 43, 99, 85, 117, 115, 47, 117, 115, 69, 83, 83, 98, 76, 81, 53, 80, 113, 75, 69, 98, 113, 50, 52, 73, 88, 102, 83, 49, 72, 101, 67, 104, 43, 89, 103, 81, 89, 72, 117, 52, 118, 103, 82, 116, 50, 80, 82, 70, 122, 101, 43, 10, 71, 88, 89, 107, 72, 65, 81, 97, 84, 79, 115, 57, 113, 109, 100, 118, 76, 100, 84, 78, 47, 109, 85, 120, 99, 77, 85, 98, 112, 103, 73, 75, 117, 109, 66, 55, 98, 86, 106, 67, 109, 107, 110, 43, 89, 122, 73, 76, 97, 43, 77, 54, 119, 75, 121, 114, 79, 55, 68, 111, 48, 119, 108, 82, 106, 66, 67, 68, 120, 106, 84, 103, 120, 83, 118, 103, 10, 71, 114, 90, 103, 70, 67, 100, 115, 77, 110, 101, 77, 118, 76, 74, 121, 109, 77, 47, 78, 122, 68, 43, 53, 121, 67, 82, 67, 70, 78, 90, 88, 47, 79, 89, 109, 81, 54, 107, 100, 53, 89, 67, 81, 122, 103, 78, 85, 75, 68, 55, 51, 80, 57, 80, 52, 84, 101, 49, 113, 67, 106, 113, 84, 69, 53, 115, 55, 70, 67, 77, 84, 89, 53, 119, 47, 10, 48, 89, 99, 110, 101, 101, 86, 77, 85, 101, 77, 66, 114, 89, 86, 100, 71, 106, 117, 120, 49, 88, 77, 81, 112, 78, 80, 121, 118, 71, 53, 107, 57, 86, 112, 87, 107, 75, 106, 72, 68, 107, 120, 48, 68, 121, 53, 120, 79, 47, 102, 73, 82, 47, 82, 112, 98, 120, 88, 121, 69, 86, 54, 68, 72, 112, 120, 56, 85, 113, 55, 57, 65, 116, 111, 83, 10, 113, 70, 108, 110, 71, 78, 117, 56, 99, 78, 50, 98, 115, 87, 110, 116, 103, 77, 54, 74, 81, 69, 104, 113, 68, 106, 88, 75, 75, 87, 89, 86, 73, 90, 81, 115, 54, 71, 65, 113, 109, 52, 86, 75, 81, 80, 78, 114, 105, 105, 84, 115, 66, 104, 89, 115, 99, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 111, 109, 111, 100, 111, 32, 65, 65, 65, 32, 83, 101, 114, 118, 105, 99, 101, 115, 32, 114, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 77, 106, 67, 67, 65, 120, 113, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 55, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 72, 81, 106, 69, 98, 77, 66, 107, 71, 65, 49, 85, 69, 67, 65, 119, 83, 10, 82, 51, 74, 108, 89, 88, 82, 108, 99, 105, 66, 78, 89, 87, 53, 106, 97, 71, 86, 122, 100, 71, 86, 121, 77, 82, 65, 119, 68, 103, 89, 68, 86, 81, 81, 72, 68, 65, 100, 84, 89, 87, 120, 109, 98, 51, 74, 107, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 68, 66, 70, 68, 98, 50, 49, 118, 90, 71, 56, 103, 81, 48, 69, 103, 10, 84, 71, 108, 116, 97, 88, 82, 108, 90, 68, 69, 104, 77, 66, 56, 71, 65, 49, 85, 69, 65, 119, 119, 89, 81, 85, 70, 66, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 86, 122, 77, 66, 52, 88, 68, 84, 65, 48, 77, 68, 69, 119, 77, 84, 65, 119, 77, 68, 65, 119, 10, 77, 70, 111, 88, 68, 84, 73, 52, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 101, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 48, 73, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 103, 77, 69, 107, 100, 121, 90, 87, 70, 48, 90, 88, 73, 103, 84, 87, 70, 117, 89, 50, 104, 108, 10, 99, 51, 82, 108, 99, 106, 69, 81, 77, 65, 52, 71, 65, 49, 85, 69, 66, 119, 119, 72, 85, 50, 70, 115, 90, 109, 57, 121, 90, 68, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 103, 119, 82, 81, 50, 57, 116, 98, 50, 82, 118, 73, 69, 78, 66, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 73, 84, 65, 102, 66, 103, 78, 86, 10, 66, 65, 77, 77, 71, 69, 70, 66, 81, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 83, 66, 84, 90, 88, 74, 50, 97, 87, 78, 108, 99, 122, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 10, 103, 103, 69, 66, 65, 76, 53, 65, 110, 102, 82, 117, 52, 101, 112, 50, 104, 120, 120, 78, 82, 85, 83, 79, 118, 107, 98, 73, 103, 119, 97, 100, 119, 83, 114, 43, 71, 66, 43, 79, 53, 65, 76, 54, 56, 54, 116, 100, 85, 73, 111, 87, 77, 81, 117, 97, 66, 116, 68, 70, 99, 67, 76, 78, 83, 83, 49, 85, 89, 56, 121, 50, 98, 109, 104, 71, 10, 67, 49, 80, 113, 121, 48, 119, 107, 119, 76, 120, 121, 84, 117, 114, 120, 70, 97, 55, 48, 86, 74, 111, 83, 67, 115, 78, 54, 115, 106, 78, 103, 52, 116, 113, 74, 86, 102, 77, 105, 87, 80, 80, 101, 51, 77, 47, 118, 103, 52, 97, 105, 106, 74, 82, 80, 110, 50, 106, 121, 109, 74, 66, 71, 104, 67, 102, 72, 100, 114, 47, 106, 122, 68, 85, 115, 10, 105, 49, 52, 72, 90, 71, 87, 67, 119, 69, 105, 119, 113, 74, 72, 53, 89, 90, 57, 50, 73, 70, 67, 111, 107, 99, 100, 109, 116, 101, 116, 52, 89, 103, 78, 87, 56, 73, 111, 97, 69, 43, 111, 120, 111, 120, 54, 103, 109, 102, 48, 52, 57, 118, 89, 110, 77, 108, 104, 118, 66, 47, 86, 114, 117, 80, 115, 85, 75, 54, 43, 51, 113, 115, 122, 87, 10, 89, 49, 57, 122, 106, 78, 111, 70, 109, 97, 103, 52, 113, 77, 115, 88, 101, 68, 90, 82, 114, 79, 109, 101, 57, 72, 103, 54, 106, 99, 56, 80, 50, 85, 76, 105, 109, 65, 121, 114, 76, 53, 56, 79, 65, 100, 55, 118, 110, 53, 108, 74, 56, 83, 51, 102, 114, 72, 82, 78, 71, 53, 105, 49, 82, 56, 88, 108, 75, 100, 72, 53, 107, 66, 106, 72, 10, 89, 112, 121, 43, 103, 56, 99, 109, 101, 122, 54, 75, 74, 99, 102, 65, 51, 90, 51, 109, 78, 87, 103, 81, 73, 74, 50, 80, 50, 78, 55, 83, 119, 52, 83, 99, 68, 86, 55, 111, 76, 56, 107, 67, 65, 119, 69, 65, 65, 97, 79, 66, 119, 68, 67, 66, 118, 84, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 111, 66, 69, 75, 10, 73, 122, 54, 87, 56, 81, 102, 115, 52, 113, 56, 112, 55, 52, 75, 108, 102, 57, 65, 119, 112, 76, 81, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 101, 119, 89, 68, 86, 82, 48, 102, 10, 66, 72, 81, 119, 99, 106, 65, 52, 111, 68, 97, 103, 78, 73, 89, 121, 97, 72, 82, 48, 99, 68, 111, 118, 76, 50, 78, 121, 98, 67, 53, 106, 98, 50, 49, 118, 90, 71, 57, 106, 89, 83, 53, 106, 98, 50, 48, 118, 81, 85, 70, 66, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 86, 84, 90, 88, 74, 50, 97, 87, 78, 108, 10, 99, 121, 53, 106, 99, 109, 119, 119, 78, 113, 65, 48, 111, 68, 75, 71, 77, 71, 104, 48, 100, 72, 65, 54, 76, 121, 57, 106, 99, 109, 119, 117, 89, 50, 57, 116, 98, 50, 82, 118, 76, 109, 53, 108, 100, 67, 57, 66, 81, 85, 70, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 86, 78, 108, 99, 110, 90, 112, 89, 50, 86, 122, 10, 76, 109, 78, 121, 98, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 67, 70, 98, 56, 65, 118, 67, 98, 54, 80, 43, 107, 43, 116, 90, 55, 120, 107, 83, 65, 122, 107, 47, 69, 120, 102, 89, 65, 87, 77, 121, 109, 116, 114, 119, 85, 83, 87, 103, 69, 100, 117, 106, 109, 10, 55, 108, 51, 115, 65, 103, 57, 103, 49, 111, 49, 81, 71, 69, 56, 109, 84, 103, 72, 106, 53, 114, 67, 108, 55, 114, 43, 56, 100, 70, 82, 66, 118, 47, 51, 56, 69, 114, 106, 72, 84, 49, 114, 48, 105, 87, 65, 70, 102, 50, 67, 51, 66, 85, 114, 122, 57, 118, 72, 67, 118, 56, 83, 53, 100, 73, 97, 50, 76, 88, 49, 114, 122, 78, 76, 122, 10, 82, 116, 48, 118, 120, 117, 66, 113, 119, 56, 77, 48, 65, 121, 120, 57, 108, 116, 49, 97, 119, 103, 54, 110, 67, 112, 110, 66, 66, 89, 117, 114, 68, 67, 47, 122, 88, 68, 114, 80, 98, 68, 100, 86, 67, 89, 102, 101, 85, 48, 66, 115, 87, 79, 47, 56, 116, 113, 116, 108, 98, 103, 84, 50, 71, 57, 119, 56, 52, 70, 111, 86, 120, 112, 55, 90, 10, 56, 86, 108, 73, 77, 67, 70, 108, 65, 50, 122, 115, 54, 83, 70, 122, 55, 74, 115, 68, 111, 101, 65, 51, 114, 97, 65, 86, 71, 73, 47, 54, 117, 103, 76, 79, 112, 121, 121, 112, 69, 66, 77, 115, 49, 79, 85, 73, 74, 113, 115, 105, 108, 50, 68, 52, 107, 70, 53, 48, 49, 75, 75, 97, 85, 55, 51, 121, 113, 87, 106, 103, 111, 109, 55, 67, 10, 49, 50, 121, 120, 111, 119, 43, 101, 118, 43, 116, 111, 53, 49, 98, 121, 114, 118, 76, 106, 75, 122, 103, 54, 67, 89, 71, 49, 97, 52, 88, 88, 118, 105, 51, 116, 80, 120, 113, 51, 115, 109, 80, 105, 57, 87, 73, 115, 103, 116, 82, 113, 65, 69, 70, 81, 56, 84, 109, 68, 110, 53, 88, 112, 78, 112, 97, 89, 98, 103, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 111, 109, 111, 100, 111, 32, 83, 101, 99, 117, 114, 101, 32, 83, 101, 114, 118, 105, 99, 101, 115, 32, 114, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 80, 122, 67, 67, 65, 121, 101, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 43, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 72, 81, 106, 69, 98, 77, 66, 107, 71, 65, 49, 85, 69, 67, 65, 119, 83, 10, 82, 51, 74, 108, 89, 88, 82, 108, 99, 105, 66, 78, 89, 87, 53, 106, 97, 71, 86, 122, 100, 71, 86, 121, 77, 82, 65, 119, 68, 103, 89, 68, 86, 81, 81, 72, 68, 65, 100, 84, 89, 87, 120, 109, 98, 51, 74, 107, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 68, 66, 70, 68, 98, 50, 49, 118, 90, 71, 56, 103, 81, 48, 69, 103, 10, 84, 71, 108, 116, 97, 88, 82, 108, 90, 68, 69, 107, 77, 67, 73, 71, 65, 49, 85, 69, 65, 119, 119, 98, 85, 50, 86, 106, 100, 88, 74, 108, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 86, 122, 77, 66, 52, 88, 68, 84, 65, 48, 77, 68, 69, 119, 77, 84, 65, 119, 10, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 73, 52, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 102, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 48, 73, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 103, 77, 69, 107, 100, 121, 90, 87, 70, 48, 90, 88, 73, 103, 84, 87, 70, 117, 10, 89, 50, 104, 108, 99, 51, 82, 108, 99, 106, 69, 81, 77, 65, 52, 71, 65, 49, 85, 69, 66, 119, 119, 72, 85, 50, 70, 115, 90, 109, 57, 121, 90, 68, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 103, 119, 82, 81, 50, 57, 116, 98, 50, 82, 118, 73, 69, 78, 66, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 74, 68, 65, 105, 10, 66, 103, 78, 86, 66, 65, 77, 77, 71, 49, 78, 108, 89, 51, 86, 121, 90, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 83, 66, 84, 90, 88, 74, 50, 97, 87, 78, 108, 99, 122, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 10, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 77, 66, 120, 77, 52, 75, 75, 48, 72, 68, 114, 99, 52, 101, 67, 81, 78, 85, 100, 53, 77, 118, 74, 68, 107, 75, 81, 43, 100, 52, 48, 117, 97, 71, 54, 69, 102, 81, 108, 104, 102, 80, 77, 99, 109, 51, 121, 101, 53, 100, 114, 115, 119, 102, 120, 100, 121, 83, 82, 88, 121, 87, 80, 10, 57, 110, 81, 57, 53, 73, 68, 67, 43, 68, 119, 78, 56, 55, 57, 65, 54, 118, 102, 73, 85, 116, 70, 121, 98, 43, 47, 73, 113, 48, 71, 52, 98, 105, 52, 88, 75, 112, 86, 112, 68, 77, 51, 83, 72, 112, 82, 55, 76, 90, 81, 100, 113, 110, 88, 88, 115, 53, 106, 76, 114, 76, 120, 107, 85, 48, 67, 56, 106, 54, 121, 115, 78, 115, 116, 99, 10, 114, 98, 118, 100, 52, 74, 81, 88, 55, 78, 70, 99, 48, 76, 47, 118, 112, 90, 88, 74, 107, 77, 87, 119, 114, 80, 115, 98, 81, 57, 57, 54, 67, 70, 50, 51, 117, 80, 74, 65, 71, 121, 115, 110, 110, 108, 68, 79, 88, 109, 87, 67, 105, 73, 120, 101, 48, 48, 52, 77, 101, 117, 111, 73, 107, 98, 89, 50, 113, 105, 116, 67, 43, 43, 114, 67, 10, 111, 122, 110, 108, 50, 121, 89, 52, 114, 89, 115, 75, 55, 104, 108, 106, 120, 120, 119, 107, 51, 119, 78, 52, 50, 117, 98, 113, 119, 85, 99, 97, 67, 119, 116, 71, 67, 100, 48, 67, 47, 78, 55, 76, 104, 49, 47, 88, 77, 71, 78, 111, 111, 97, 55, 99, 77, 113, 71, 54, 118, 118, 53, 69, 113, 50, 105, 50, 112, 82, 99, 86, 47, 98, 51, 86, 10, 112, 54, 101, 97, 53, 69, 81, 122, 54, 89, 105, 79, 47, 79, 49, 82, 54, 53, 78, 120, 84, 113, 48, 66, 53, 48, 83, 79, 113, 121, 51, 76, 113, 80, 52, 66, 83, 85, 106, 119, 119, 78, 51, 72, 97, 78, 105, 83, 47, 106, 48, 67, 65, 119, 69, 65, 65, 97, 79, 66, 120, 122, 67, 66, 120, 68, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 10, 70, 103, 81, 85, 80, 78, 105, 84, 105, 77, 76, 65, 103, 103, 110, 77, 65, 90, 107, 71, 107, 121, 68, 112, 110, 110, 65, 74, 89, 48, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 10, 103, 89, 69, 71, 65, 49, 85, 100, 72, 119, 82, 54, 77, 72, 103, 119, 79, 54, 65, 53, 111, 68, 101, 71, 78, 87, 104, 48, 100, 72, 65, 54, 76, 121, 57, 106, 99, 109, 119, 117, 89, 50, 57, 116, 98, 50, 82, 118, 89, 50, 69, 117, 89, 50, 57, 116, 76, 49, 78, 108, 89, 51, 86, 121, 90, 85, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 10, 89, 88, 82, 108, 85, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 117, 89, 51, 74, 115, 77, 68, 109, 103, 78, 54, 65, 49, 104, 106, 78, 111, 100, 72, 82, 119, 79, 105, 56, 118, 89, 51, 74, 115, 76, 109, 78, 118, 98, 87, 57, 107, 98, 121, 53, 117, 90, 88, 81, 118, 85, 50, 86, 106, 100, 88, 74, 108, 81, 50, 86, 121, 100, 71, 108, 109, 10, 97, 87, 78, 104, 100, 71, 86, 84, 90, 88, 74, 50, 97, 87, 78, 108, 99, 121, 53, 106, 99, 109, 119, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 73, 99, 66, 98, 83, 77, 100, 102, 108, 115, 88, 102, 99, 70, 104, 77, 115, 43, 80, 53, 47, 79, 75, 108, 70, 108, 109, 10, 52, 74, 52, 111, 113, 70, 55, 84, 116, 47, 81, 48, 53, 113, 111, 53, 115, 112, 99, 87, 120, 89, 74, 118, 77, 113, 84, 112, 106, 79, 101, 118, 47, 101, 47, 67, 54, 76, 108, 76, 113, 113, 80, 48, 53, 116, 113, 78, 90, 83, 72, 55, 117, 111, 68, 114, 74, 105, 105, 70, 71, 118, 52, 53, 106, 78, 53, 98, 66, 65, 83, 48, 86, 80, 109, 106, 10, 90, 53, 53, 66, 43, 103, 108, 83, 122, 65, 86, 73, 113, 77, 107, 47, 73, 81, 81, 101, 122, 107, 104, 114, 47, 73, 88, 111, 119, 110, 117, 118, 102, 55, 102, 77, 43, 70, 56, 54, 47, 84, 88, 71, 68, 101, 43, 88, 51, 69, 121, 114, 69, 101, 70, 114, 121, 122, 72, 82, 98, 80, 116, 73, 103, 75, 118, 99, 110, 68, 101, 52, 73, 82, 82, 76, 10, 68, 88, 69, 57, 55, 73, 77, 122, 98, 116, 70, 117, 77, 104, 98, 115, 109, 77, 99, 87, 105, 49, 109, 109, 78, 75, 115, 70, 86, 121, 50, 84, 57, 54, 111, 84, 121, 57, 73, 84, 52, 114, 99, 117, 79, 56, 49, 114, 85, 66, 99, 74, 97, 68, 54, 49, 74, 108, 102, 117, 116, 117, 67, 50, 51, 98, 107, 112, 103, 72, 108, 57, 106, 54, 80, 119, 10, 112, 67, 105, 107, 70, 99, 83, 70, 57, 67, 102, 85, 97, 55, 47, 108, 88, 79, 82, 108, 65, 110, 90, 85, 116, 79, 77, 51, 90, 105, 84, 84, 71, 87, 72, 73, 85, 104, 68, 108, 105, 122, 101, 97, 117, 97, 110, 53, 72, 98, 47, 113, 109, 90, 74, 104, 108, 118, 56, 66, 122, 97, 70, 102, 68, 98, 120, 120, 118, 65, 54, 115, 67, 120, 49, 72, 10, 82, 82, 51, 66, 55, 72, 122, 115, 47, 83, 107, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 111, 109, 111, 100, 111, 32, 84, 114, 117, 115, 116, 101, 100, 32, 83, 101, 114, 118, 105, 99, 101, 115, 32, 114, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 81, 122, 67, 67, 65, 121, 117, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 47, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 72, 81, 106, 69, 98, 77, 66, 107, 71, 65, 49, 85, 69, 67, 65, 119, 83, 10, 82, 51, 74, 108, 89, 88, 82, 108, 99, 105, 66, 78, 89, 87, 53, 106, 97, 71, 86, 122, 100, 71, 86, 121, 77, 82, 65, 119, 68, 103, 89, 68, 86, 81, 81, 72, 68, 65, 100, 84, 89, 87, 120, 109, 98, 51, 74, 107, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 68, 66, 70, 68, 98, 50, 49, 118, 90, 71, 56, 103, 81, 48, 69, 103, 10, 84, 71, 108, 116, 97, 88, 82, 108, 90, 68, 69, 108, 77, 67, 77, 71, 65, 49, 85, 69, 65, 119, 119, 99, 86, 72, 74, 49, 99, 51, 82, 108, 90, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 83, 66, 84, 90, 88, 74, 50, 97, 87, 78, 108, 99, 122, 65, 101, 70, 119, 48, 119, 78, 68, 65, 120, 77, 68, 69, 119, 10, 77, 68, 65, 119, 77, 68, 66, 97, 70, 119, 48, 121, 79, 68, 69, 121, 77, 122, 69, 121, 77, 122, 85, 53, 78, 84, 108, 97, 77, 72, 56, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 100, 67, 77, 82, 115, 119, 71, 81, 89, 68, 86, 81, 81, 73, 68, 66, 74, 72, 99, 109, 86, 104, 100, 71, 86, 121, 73, 69, 49, 104, 10, 98, 109, 78, 111, 90, 88, 78, 48, 90, 88, 73, 120, 69, 68, 65, 79, 66, 103, 78, 86, 66, 65, 99, 77, 66, 49, 78, 104, 98, 71, 90, 118, 99, 109, 81, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 78, 118, 98, 87, 57, 107, 98, 121, 66, 68, 81, 83, 66, 77, 97, 87, 49, 112, 100, 71, 86, 107, 77, 83, 85, 119, 10, 73, 119, 89, 68, 86, 81, 81, 68, 68, 66, 120, 85, 99, 110, 86, 122, 100, 71, 86, 107, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 86, 122, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 10, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 51, 51, 70, 118, 78, 108, 104, 84, 87, 118, 73, 50, 86, 70, 101, 65, 120, 72, 81, 73, 73, 79, 48, 89, 102, 121, 111, 100, 53, 106, 87, 97, 72, 105, 87, 115, 110, 79, 87, 87, 102, 110, 74, 83, 111, 66, 86, 67, 50, 49, 110, 100, 90, 72, 111, 97, 48, 76, 104, 55, 10, 51, 84, 107, 86, 118, 70, 86, 73, 120, 79, 48, 54, 65, 79, 111, 120, 69, 98, 114, 121, 99, 88, 81, 97, 90, 55, 106, 80, 77, 56, 121, 111, 77, 97, 43, 106, 52, 57, 100, 47, 118, 122, 77, 116, 84, 71, 111, 56, 55, 73, 118, 68, 107, 116, 74, 84, 100, 121, 82, 48, 110, 65, 100, 117, 99, 80, 121, 57, 67, 49, 116, 50, 117, 108, 47, 121, 10, 47, 57, 99, 51, 83, 48, 112, 103, 101, 80, 102, 119, 43, 115, 112, 119, 116, 79, 112, 90, 113, 113, 80, 79, 83, 67, 43, 112, 119, 55, 73, 76, 102, 104, 100, 121, 70, 103, 121, 109, 66, 119, 119, 98, 79, 77, 47, 74, 89, 114, 99, 47, 111, 74, 79, 108, 104, 48, 72, 121, 116, 51, 66, 65, 100, 57, 105, 43, 70, 72, 122, 106, 113, 77, 66, 54, 10, 106, 117, 108, 106, 97, 116, 69, 80, 109, 115, 98, 83, 57, 73, 115, 54, 70, 65, 82, 87, 49, 79, 50, 52, 122, 71, 55, 49, 43, 43, 73, 115, 87, 76, 49, 47, 84, 50, 115, 114, 57, 50, 65, 107, 87, 67, 84, 79, 74, 117, 56, 48, 107, 84, 114, 86, 52, 52, 72, 81, 115, 118, 65, 69, 65, 116, 100, 98, 116, 122, 54, 83, 114, 71, 115, 83, 10, 105, 118, 110, 107, 66, 98, 65, 55, 107, 85, 108, 99, 115, 117, 116, 84, 54, 118, 105, 102, 82, 52, 98, 117, 118, 53, 88, 65, 119, 65, 97, 102, 48, 108, 116, 101, 69, 82, 118, 48, 120, 119, 81, 49, 75, 100, 74, 86, 88, 79, 84, 116, 54, 119, 73, 68, 65, 81, 65, 66, 111, 52, 72, 74, 77, 73, 72, 71, 77, 66, 48, 71, 65, 49, 85, 100, 10, 68, 103, 81, 87, 66, 66, 84, 70, 101, 49, 105, 57, 55, 100, 111, 108, 97, 100, 76, 51, 87, 82, 97, 111, 115, 122, 76, 65, 101, 121, 100, 98, 57, 68, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 10, 47, 122, 67, 66, 103, 119, 89, 68, 86, 82, 48, 102, 66, 72, 119, 119, 101, 106, 65, 56, 111, 68, 113, 103, 79, 73, 89, 50, 97, 72, 82, 48, 99, 68, 111, 118, 76, 50, 78, 121, 98, 67, 53, 106, 98, 50, 49, 118, 90, 71, 57, 106, 89, 83, 53, 106, 98, 50, 48, 118, 86, 72, 74, 49, 99, 51, 82, 108, 90, 69, 78, 108, 99, 110, 82, 112, 10, 90, 109, 108, 106, 89, 88, 82, 108, 85, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 117, 89, 51, 74, 115, 77, 68, 113, 103, 79, 75, 65, 50, 104, 106, 82, 111, 100, 72, 82, 119, 79, 105, 56, 118, 89, 51, 74, 115, 76, 109, 78, 118, 98, 87, 57, 107, 98, 121, 53, 117, 90, 88, 81, 118, 86, 72, 74, 49, 99, 51, 82, 108, 90, 69, 78, 108, 10, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 85, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 117, 89, 51, 74, 115, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 66, 65, 81, 68, 73, 107, 52, 69, 55, 105, 98, 83, 118, 117, 73, 81, 83, 84, 73, 51, 83, 56, 78, 116, 119, 10, 117, 108, 101, 71, 70, 84, 81, 81, 117, 83, 57, 47, 72, 114, 67, 111, 105, 87, 67, 104, 105, 115, 74, 51, 68, 70, 66, 75, 109, 119, 67, 76, 50, 73, 118, 48, 81, 101, 76, 81, 103, 52, 112, 75, 72, 66, 81, 71, 115, 75, 78, 111, 66, 88, 65, 120, 77, 75, 100, 84, 109, 119, 55, 112, 83, 113, 66, 89, 97, 87, 99, 79, 114, 112, 51, 50, 10, 112, 83, 120, 66, 118, 122, 119, 71, 97, 43, 82, 90, 122, 71, 48, 81, 56, 90, 90, 118, 72, 57, 47, 48, 66, 65, 75, 107, 110, 48, 85, 43, 121, 78, 106, 54, 78, 107, 90, 69, 85, 68, 43, 67, 108, 53, 69, 102, 75, 78, 115, 89, 69, 89, 119, 113, 53, 71, 87, 68, 86, 120, 73, 83, 106, 66, 99, 47, 108, 68, 98, 43, 88, 98, 68, 65, 10, 66, 72, 99, 84, 117, 80, 81, 86, 49, 84, 56, 52, 122, 74, 81, 54, 86, 100, 67, 115, 109, 80, 87, 54, 65, 70, 47, 103, 104, 104, 109, 66, 101, 67, 56, 111, 119, 72, 55, 84, 122, 69, 73, 75, 57, 97, 53, 81, 111, 78, 69, 43, 120, 113, 70, 120, 55, 68, 43, 103, 73, 73, 120, 109, 79, 111, 109, 48, 106, 116, 84, 89, 115, 85, 48, 108, 10, 82, 43, 52, 118, 105, 77, 105, 49, 52, 81, 86, 70, 119, 76, 52, 85, 99, 100, 53, 54, 47, 89, 53, 55, 102, 85, 48, 73, 108, 113, 85, 83, 99, 47, 65, 116, 121, 106, 99, 110, 100, 66, 73, 110, 84, 77, 117, 50, 108, 43, 110, 90, 114, 103, 104, 116, 87, 106, 108, 65, 51, 81, 86, 72, 100, 87, 112, 97, 73, 98, 79, 106, 71, 77, 57, 79, 10, 57, 121, 53, 88, 116, 53, 104, 119, 88, 115, 106, 69, 101, 76, 66, 105, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 81, 117, 111, 86, 97, 100, 105, 115, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 48, 68, 67, 67, 66, 76, 105, 103, 65, 119, 73, 66, 65, 103, 73, 69, 79, 114, 90, 81, 105, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 47, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 67, 84, 84, 69, 90, 77, 66, 99, 71, 65, 49, 85, 69, 10, 67, 104, 77, 81, 85, 88, 86, 118, 86, 109, 70, 107, 97, 88, 77, 103, 84, 71, 108, 116, 97, 88, 82, 108, 90, 68, 69, 108, 77, 67, 77, 71, 65, 49, 85, 69, 67, 120, 77, 99, 85, 109, 57, 118, 100, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 10, 101, 84, 69, 117, 77, 67, 119, 71, 65, 49, 85, 69, 65, 120, 77, 108, 85, 88, 86, 118, 86, 109, 70, 107, 97, 88, 77, 103, 85, 109, 57, 118, 100, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 84, 65, 101, 70, 119, 48, 119, 77, 84, 65, 122, 10, 77, 84, 107, 120, 79, 68, 77, 122, 77, 122, 78, 97, 70, 119, 48, 121, 77, 84, 65, 122, 77, 84, 99, 120, 79, 68, 77, 122, 77, 122, 78, 97, 77, 72, 56, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 74, 78, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 75, 69, 120, 66, 82, 100, 87, 57, 87, 89, 87, 82, 112, 10, 99, 121, 66, 77, 97, 87, 49, 112, 100, 71, 86, 107, 77, 83, 85, 119, 73, 119, 89, 68, 86, 81, 81, 76, 69, 120, 120, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 83, 52, 119, 76, 65, 89, 68, 86, 81, 81, 68, 10, 69, 121, 86, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 10, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 118, 50, 71, 49, 108, 86, 79, 54, 86, 47, 122, 54, 56, 109, 99, 76, 79, 104, 114, 102, 69, 89, 66, 107, 108, 98, 84, 82, 118, 77, 49, 54, 122, 47, 89, 112, 108, 105, 52, 107, 86, 69, 65, 107, 79, 80, 99, 97, 104, 100, 120, 89, 84, 77, 117, 107, 10, 74, 48, 75, 88, 48, 74, 43, 68, 105, 115, 80, 107, 66, 103, 78, 98, 65, 75, 86, 82, 72, 110, 65, 69, 100, 79, 76, 66, 49, 68, 113, 114, 49, 54, 48, 55, 66, 120, 103, 70, 106, 118, 50, 68, 114, 79, 112, 109, 50, 82, 103, 98, 97, 73, 114, 49, 86, 120, 113, 89, 117, 118, 88, 116, 100, 106, 49, 56, 50, 100, 54, 85, 97, 106, 116, 76, 10, 70, 56, 72, 86, 106, 55, 49, 108, 79, 68, 113, 86, 48, 68, 49, 86, 78, 107, 55, 102, 101, 86, 99, 120, 75, 104, 55, 89, 87, 87, 86, 74, 87, 67, 67, 89, 102, 113, 116, 102, 102, 112, 47, 112, 49, 107, 51, 115, 103, 51, 83, 112, 120, 50, 122, 89, 55, 105, 108, 75, 104, 83, 111, 71, 70, 80, 108, 85, 53, 116, 80, 97, 90, 81, 101, 76, 10, 89, 122, 99, 83, 49, 57, 68, 115, 119, 51, 115, 103, 81, 85, 83, 106, 55, 99, 117, 103, 70, 43, 70, 120, 90, 99, 52, 100, 90, 106, 72, 51, 100, 103, 69, 90, 121, 72, 48, 68, 87, 76, 97, 86, 83, 82, 50, 109, 69, 105, 98, 111, 120, 103, 120, 50, 52, 79, 78, 109, 121, 43, 112, 100, 112, 105, 98, 117, 53, 99, 120, 102, 118, 87, 101, 110, 10, 65, 83, 99, 79, 111, 115, 112, 85, 120, 98, 70, 54, 108, 82, 49, 120, 72, 107, 111, 112, 105, 103, 80, 99, 97, 107, 88, 66, 112, 66, 108, 101, 98, 122, 98, 78, 119, 54, 75, 119, 116, 47, 53, 99, 79, 79, 74, 83, 118, 80, 104, 69, 81, 43, 97, 81, 117, 119, 73, 68, 65, 81, 65, 66, 111, 52, 73, 67, 85, 106, 67, 67, 65, 107, 52, 119, 10, 80, 81, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 81, 69, 69, 77, 84, 65, 118, 77, 67, 48, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 122, 65, 66, 104, 105, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 57, 106, 99, 51, 65, 117, 99, 88, 86, 118, 100, 109, 70, 107, 97, 88, 78, 118, 90, 109, 90, 122, 97, 71, 57, 121, 10, 90, 83, 53, 106, 98, 50, 48, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 67, 67, 65, 82, 111, 71, 65, 49, 85, 100, 73, 65, 83, 67, 65, 82, 69, 119, 103, 103, 69, 78, 77, 73, 73, 66, 67, 81, 89, 74, 75, 119, 89, 66, 66, 65, 71, 43, 87, 65, 65, 66, 77, 73, 72, 55, 10, 77, 73, 72, 85, 66, 103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 67, 65, 106, 67, 66, 120, 120, 113, 66, 120, 70, 74, 108, 98, 71, 108, 104, 98, 109, 78, 108, 73, 71, 57, 117, 73, 72, 82, 111, 90, 83, 66, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 10, 89, 88, 82, 108, 73, 71, 74, 53, 73, 71, 70, 117, 101, 83, 66, 119, 89, 88, 74, 48, 101, 83, 66, 104, 99, 51, 78, 49, 98, 87, 86, 122, 73, 71, 70, 106, 89, 50, 86, 119, 100, 71, 70, 117, 89, 50, 85, 103, 98, 50, 89, 103, 100, 71, 104, 108, 73, 72, 82, 111, 90, 87, 52, 103, 89, 88, 66, 119, 98, 71, 108, 106, 89, 87, 74, 115, 10, 90, 83, 66, 122, 100, 71, 70, 117, 90, 71, 70, 121, 90, 67, 66, 48, 90, 88, 74, 116, 99, 121, 66, 104, 98, 109, 81, 103, 89, 50, 57, 117, 90, 71, 108, 48, 97, 87, 57, 117, 99, 121, 66, 118, 90, 105, 66, 49, 99, 50, 85, 115, 73, 71, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 99, 72, 74, 104, 10, 89, 51, 82, 112, 89, 50, 86, 122, 76, 67, 66, 104, 98, 109, 81, 103, 100, 71, 104, 108, 73, 70, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 73, 70, 66, 118, 98, 71, 108, 106, 101, 83, 52, 119, 73, 103, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 103, 69, 87, 10, 70, 109, 104, 48, 100, 72, 65, 54, 76, 121, 57, 51, 100, 51, 99, 117, 99, 88, 86, 118, 100, 109, 70, 107, 97, 88, 77, 117, 89, 109, 48, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 73, 116, 76, 98, 101, 51, 84, 75, 98, 107, 71, 71, 101, 119, 53, 79, 97, 110, 119, 108, 52, 82, 113, 121, 43, 47, 102, 77, 73, 71, 117, 10, 66, 103, 78, 86, 72, 83, 77, 69, 103, 97, 89, 119, 103, 97, 79, 65, 70, 73, 116, 76, 98, 101, 51, 84, 75, 98, 107, 71, 71, 101, 119, 53, 79, 97, 110, 119, 108, 52, 82, 113, 121, 43, 47, 102, 111, 89, 71, 69, 112, 73, 71, 66, 77, 72, 56, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 74, 78, 77, 82, 107, 119, 10, 70, 119, 89, 68, 86, 81, 81, 75, 69, 120, 66, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 77, 97, 87, 49, 112, 100, 71, 86, 107, 77, 83, 85, 119, 73, 119, 89, 68, 86, 81, 81, 76, 69, 120, 120, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 10, 97, 71, 57, 121, 97, 88, 82, 53, 77, 83, 52, 119, 76, 65, 89, 68, 86, 81, 81, 68, 69, 121, 86, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 103, 103, 81, 54, 10, 116, 108, 67, 76, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 105, 116, 81, 85, 116, 102, 55, 48, 109, 112, 75, 110, 71, 100, 83, 107, 102, 110, 73, 89, 106, 57, 108, 111, 10, 102, 70, 73, 107, 51, 87, 100, 118, 79, 88, 114, 69, 113, 108, 52, 57, 52, 108, 105, 119, 84, 88, 67, 89, 104, 71, 72, 111, 71, 43, 78, 112, 71, 65, 55, 79, 43, 48, 100, 81, 111, 69, 55, 47, 56, 67, 81, 102, 118, 98, 76, 79, 57, 83, 102, 56, 55, 67, 57, 84, 113, 110, 78, 55, 65, 122, 49, 48, 98, 117, 89, 87, 110, 117, 117, 108, 10, 76, 115, 83, 47, 86, 105, 100, 81, 75, 50, 75, 54, 118, 107, 115, 99, 80, 70, 86, 99, 81, 82, 48, 107, 118, 111, 73, 103, 82, 49, 51, 86, 82, 72, 53, 54, 70, 109, 106, 102, 102, 85, 49, 82, 99, 72, 104, 88, 72, 84, 77, 101, 47, 81, 75, 90, 110, 65, 122, 78, 67, 103, 86, 80, 120, 55, 117, 79, 112, 72, 88, 54, 83, 109, 50, 120, 10, 103, 73, 52, 74, 86, 114, 109, 99, 71, 109, 68, 43, 88, 99, 72, 88, 101, 116, 119, 82, 101, 78, 68, 87, 88, 99, 71, 51, 49, 97, 48, 121, 109, 81, 77, 54, 105, 115, 120, 85, 74, 84, 107, 120, 103, 88, 115, 84, 73, 108, 71, 54, 82, 109, 121, 104, 117, 53, 55, 54, 66, 71, 120, 74, 74, 110, 83, 80, 48, 110, 80, 114, 122, 68, 67, 105, 10, 53, 117, 112, 90, 73, 111, 102, 52, 108, 47, 85, 79, 47, 101, 114, 77, 107, 113, 81, 87, 120, 70, 73, 89, 54, 105, 72, 79, 115, 102, 72, 109, 104, 73, 72, 108, 117, 113, 109, 71, 75, 80, 74, 68, 87, 108, 48, 83, 110, 97, 119, 101, 50, 97, 106, 108, 67, 109, 113, 110, 102, 54, 67, 72, 75, 99, 47, 121, 105, 85, 51, 85, 55, 77, 88, 105, 10, 53, 110, 114, 81, 78, 105, 79, 75, 83, 110, 81, 50, 43, 81, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 81, 117, 111, 86, 97, 100, 105, 115, 32, 82, 111, 111, 116, 32, 67, 65, 32, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 116, 122, 67, 67, 65, 53, 43, 103, 65, 119, 73, 66, 65, 103, 73, 67, 66, 81, 107, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 82, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 81, 107, 48, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 111, 84, 10, 69, 70, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 77, 84, 69, 108, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 77, 106, 65, 101, 70, 119, 48, 119, 78, 106, 69, 120, 77, 106, 81, 120, 10, 79, 68, 73, 51, 77, 68, 66, 97, 70, 119, 48, 122, 77, 84, 69, 120, 77, 106, 81, 120, 79, 68, 73, 122, 77, 122, 78, 97, 77, 69, 85, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 74, 78, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 75, 69, 120, 66, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 77, 10, 97, 87, 49, 112, 100, 71, 86, 107, 77, 82, 115, 119, 71, 81, 89, 68, 86, 81, 81, 68, 69, 120, 74, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 68, 73, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 10, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 97, 71, 77, 112, 76, 108, 65, 48, 65, 76, 97, 56, 68, 75, 89, 114, 119, 68, 52, 72, 73, 114, 107, 119, 90, 104, 82, 48, 73, 110, 54, 115, 112, 82, 73, 88, 122, 76, 52, 71, 116, 77, 104, 54, 81, 82, 114, 43, 106, 104, 105, 89, 97, 72, 118, 53, 43, 72, 66, 103, 54, 10, 88, 74, 120, 103, 70, 121, 111, 54, 100, 73, 77, 122, 77, 72, 49, 104, 86, 66, 72, 76, 55, 97, 118, 103, 53, 116, 75, 105, 102, 118, 86, 114, 98, 120, 105, 51, 67, 103, 115, 116, 47, 101, 107, 43, 55, 119, 114, 71, 115, 120, 68, 112, 51, 77, 74, 71, 70, 47, 104, 100, 47, 97, 84, 97, 47, 53, 53, 74, 87, 112, 122, 109, 77, 43, 89, 107, 10, 108, 118, 99, 47, 117, 108, 115, 114, 72, 72, 111, 49, 119, 116, 90, 110, 47, 113, 116, 109, 85, 73, 116, 116, 75, 71, 65, 114, 55, 57, 100, 103, 119, 56, 101, 84, 118, 73, 48, 50, 107, 102, 78, 47, 43, 78, 115, 82, 69, 56, 83, 99, 100, 51, 98, 66, 114, 114, 99, 67, 97, 111, 70, 54, 113, 85, 87, 68, 52, 103, 88, 109, 117, 86, 98, 66, 10, 108, 68, 101, 80, 83, 72, 70, 106, 73, 117, 119, 88, 90, 81, 101, 86, 105, 107, 118, 102, 106, 56, 90, 97, 67, 117, 87, 119, 52, 49, 57, 101, 97, 120, 71, 114, 68, 80, 109, 70, 54, 48, 84, 112, 43, 65, 82, 122, 56, 117, 110, 43, 88, 74, 105, 77, 57, 88, 79, 118, 97, 55, 82, 43, 122, 100, 82, 99, 65, 105, 116, 77, 79, 101, 71, 121, 10, 108, 90, 85, 116, 81, 111, 102, 88, 49, 98, 79, 81, 81, 55, 100, 115, 69, 47, 72, 101, 51, 102, 98, 69, 43, 73, 107, 47, 48, 88, 88, 49, 107, 115, 79, 82, 49, 89, 113, 73, 48, 74, 68, 115, 51, 71, 51, 101, 105, 99, 74, 108, 99, 90, 97, 76, 68, 81, 80, 57, 110, 76, 57, 98, 70, 113, 121, 83, 50, 43, 114, 43, 101, 88, 121, 116, 10, 54, 54, 47, 51, 70, 115, 118, 98, 122, 83, 85, 114, 53, 82, 47, 55, 109, 112, 47, 105, 85, 99, 119, 54, 85, 119, 120, 73, 53, 103, 54, 57, 121, 98, 82, 50, 66, 108, 76, 109, 69, 82, 79, 70, 99, 109, 77, 68, 66, 79, 65, 69, 78, 105, 115, 103, 71, 81, 76, 111, 100, 75, 99, 102, 116, 115, 108, 87, 90, 118, 66, 49, 74, 100, 120, 110, 10, 119, 81, 53, 104, 89, 73, 105, 122, 80, 116, 71, 111, 47, 75, 80, 97, 72, 98, 68, 82, 115, 83, 78, 85, 51, 48, 82, 50, 98, 101, 49, 66, 50, 77, 71, 121, 73, 114, 90, 84, 72, 78, 56, 49, 72, 100, 121, 104, 100, 121, 111, 120, 53, 67, 51, 49, 53, 101, 88, 98, 121, 79, 68, 47, 53, 89, 68, 88, 67, 50, 79, 103, 47, 122, 79, 104, 10, 68, 55, 111, 115, 70, 82, 88, 113, 108, 55, 80, 83, 111, 114, 87, 43, 56, 111, 121, 87, 72, 104, 113, 80, 72, 87, 121, 107, 89, 84, 101, 53, 104, 110, 77, 122, 49, 53, 101, 87, 110, 105, 78, 57, 103, 113, 82, 77, 103, 101, 75, 104, 48, 98, 112, 110, 88, 53, 85, 72, 111, 121, 99, 82, 55, 104, 89, 81, 101, 55, 120, 70, 83, 107, 121, 121, 10, 66, 78, 75, 114, 55, 57, 88, 57, 68, 70, 72, 79, 85, 71, 111, 73, 77, 102, 109, 82, 50, 103, 121, 80, 90, 70, 119, 68, 119, 122, 113, 76, 73, 68, 57, 117, 106, 87, 99, 57, 79, 116, 98, 43, 102, 86, 117, 73, 121, 86, 55, 55, 122, 71, 72, 99, 105, 122, 78, 51, 48, 48, 81, 121, 78, 81, 108, 105, 66, 74, 73, 87, 69, 78, 105, 101, 10, 74, 48, 102, 55, 79, 121, 72, 106, 43, 79, 115, 100, 87, 119, 73, 68, 65, 81, 65, 66, 111, 52, 71, 119, 77, 73, 71, 116, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 67, 119, 89, 68, 86, 82, 48, 80, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 48, 71, 65, 49, 85, 100, 10, 68, 103, 81, 87, 66, 66, 81, 97, 104, 71, 75, 56, 83, 69, 119, 122, 74, 81, 84, 85, 55, 116, 68, 50, 65, 56, 81, 90, 82, 116, 71, 85, 97, 122, 66, 117, 66, 103, 78, 86, 72, 83, 77, 69, 90, 122, 66, 108, 103, 66, 81, 97, 104, 71, 75, 56, 83, 69, 119, 122, 74, 81, 84, 85, 55, 116, 68, 50, 65, 56, 81, 90, 82, 116, 71, 85, 10, 97, 54, 70, 74, 112, 69, 99, 119, 82, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 81, 107, 48, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 111, 84, 69, 70, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 77, 84, 10, 69, 108, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 77, 111, 73, 67, 66, 81, 107, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 73, 66, 65, 68, 52, 75, 70, 107, 50, 102, 66, 108, 117, 111, 114, 110, 70, 100, 76, 119, 85, 118, 10, 90, 43, 89, 84, 82, 89, 80, 69, 78, 118, 98, 122, 119, 67, 89, 77, 68, 98, 86, 72, 90, 70, 51, 52, 116, 72, 76, 74, 82, 113, 85, 68, 71, 67, 100, 86, 105, 88, 104, 57, 100, 117, 113, 87, 78, 73, 65, 88, 73, 78, 122, 110, 103, 47, 105, 78, 47, 65, 101, 52, 50, 108, 57, 78, 76, 109, 101, 121, 104, 80, 51, 90, 82, 80, 120, 51, 10, 85, 73, 72, 109, 102, 76, 84, 74, 68, 81, 116, 121, 85, 47, 104, 50, 66, 119, 100, 66, 82, 53, 89, 77, 43, 43, 67, 67, 74, 112, 78, 86, 106, 80, 52, 105, 72, 50, 66, 108, 102, 70, 47, 110, 74, 114, 80, 51, 77, 112, 67, 89, 85, 78, 81, 51, 99, 86, 88, 50, 107, 105, 70, 52, 57, 53, 86, 53, 43, 118, 103, 116, 74, 111, 100, 109, 10, 86, 106, 66, 51, 112, 106, 100, 52, 77, 49, 73, 81, 87, 75, 52, 47, 89, 89, 55, 121, 97, 114, 72, 118, 71, 72, 53, 75, 87, 87, 80, 75, 106, 97, 74, 87, 49, 97, 99, 118, 118, 70, 89, 102, 122, 122, 110, 66, 52, 118, 115, 75, 113, 66, 85, 115, 102, 85, 49, 54, 89, 56, 90, 115, 108, 48, 81, 56, 48, 109, 47, 68, 83, 104, 99, 75, 10, 43, 74, 68, 83, 86, 54, 73, 90, 85, 97, 85, 116, 108, 48, 72, 97, 66, 48, 43, 112, 85, 78, 113, 81, 106, 90, 82, 71, 52, 84, 55, 119, 108, 80, 48, 81, 65, 68, 106, 49, 79, 43, 104, 65, 52, 98, 82, 117, 86, 104, 111, 103, 122, 71, 57, 89, 106, 101, 48, 117, 82, 89, 47, 87, 54, 90, 77, 47, 53, 55, 69, 115, 51, 122, 114, 87, 10, 73, 111, 122, 99, 104, 76, 115, 105, 98, 57, 68, 52, 53, 77, 89, 53, 54, 81, 83, 73, 80, 77, 79, 54, 54, 49, 86, 54, 98, 89, 67, 90, 74, 80, 86, 115, 65, 102, 118, 52, 108, 55, 67, 85, 87, 43, 118, 57, 48, 109, 47, 120, 100, 50, 103, 78, 78, 87, 81, 106, 114, 76, 104, 86, 111, 81, 80, 82, 84, 85, 73, 90, 51, 80, 104, 49, 10, 87, 86, 97, 106, 43, 97, 104, 74, 101, 102, 105, 118, 68, 114, 107, 82, 111, 72, 121, 51, 97, 117, 48, 48, 48, 76, 89, 109, 89, 106, 103, 97, 104, 119, 122, 52, 54, 80, 48, 117, 48, 53, 66, 47, 66, 53, 69, 113, 72, 100, 90, 43, 88, 73, 87, 68, 109, 98, 65, 52, 67, 68, 47, 112, 88, 118, 107, 49, 66, 43, 84, 74, 89, 109, 53, 88, 10, 102, 54, 100, 81, 108, 102, 101, 54, 121, 74, 118, 109, 106, 113, 73, 66, 120, 100, 90, 109, 118, 51, 108, 104, 56, 122, 119, 99, 52, 98, 109, 67, 88, 70, 50, 103, 119, 43, 110, 89, 83, 76, 48, 90, 111, 104, 69, 85, 71, 87, 54, 121, 104, 104, 116, 111, 80, 107, 103, 51, 71, 111, 105, 51, 88, 90, 90, 101, 110, 77, 102, 118, 74, 50, 73, 73, 10, 52, 112, 69, 90, 88, 78, 76, 120, 73, 100, 50, 54, 70, 48, 75, 67, 108, 51, 71, 66, 85, 122, 71, 112, 110, 47, 90, 57, 89, 114, 57, 121, 52, 97, 79, 84, 72, 99, 121, 75, 74, 108, 111, 74, 79, 78, 68, 79, 49, 119, 50, 65, 70, 114, 82, 52, 112, 84, 113, 72, 84, 73, 50, 75, 112, 100, 86, 71, 108, 47, 73, 115, 69, 76, 109, 56, 10, 86, 67, 76, 65, 65, 86, 66, 112, 81, 53, 55, 48, 115, 117, 57, 116, 43, 79, 122, 97, 56, 101, 79, 120, 55, 57, 43, 82, 106, 49, 81, 113, 67, 121, 88, 66, 74, 104, 110, 69, 85, 104, 65, 70, 90, 100, 87, 67, 69, 79, 114, 67, 77, 99, 48, 117, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 81, 117, 111, 86, 97, 100, 105, 115, 32, 82, 111, 111, 116, 32, 67, 65, 32, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 71, 110, 84, 67, 67, 66, 73, 87, 103, 65, 119, 73, 66, 65, 103, 73, 67, 66, 99, 89, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 82, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 81, 107, 48, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 111, 84, 10, 69, 70, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 77, 84, 69, 108, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 77, 122, 65, 101, 70, 119, 48, 119, 78, 106, 69, 120, 77, 106, 81, 120, 10, 79, 84, 69, 120, 77, 106, 78, 97, 70, 119, 48, 122, 77, 84, 69, 120, 77, 106, 81, 120, 79, 84, 65, 50, 78, 68, 82, 97, 77, 69, 85, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 74, 78, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 75, 69, 120, 66, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 77, 10, 97, 87, 49, 112, 100, 71, 86, 107, 77, 82, 115, 119, 71, 81, 89, 68, 86, 81, 81, 68, 69, 120, 74, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 68, 77, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 10, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 68, 77, 86, 48, 73, 87, 86, 74, 122, 109, 109, 78, 80, 84, 84, 101, 55, 43, 55, 99, 101, 102, 81, 122, 108, 75, 90, 98, 80, 111, 70, 111, 103, 48, 50, 119, 49, 90, 107, 88, 84, 80, 107, 114, 103, 69, 81, 75, 48, 67, 83, 122, 71, 114, 118, 73, 50, 82, 97, 78, 103, 103, 10, 68, 104, 111, 66, 52, 104, 112, 55, 84, 104, 100, 100, 52, 111, 113, 51, 80, 53, 107, 97, 122, 101, 116, 104, 113, 56, 74, 108, 112, 104, 43, 51, 116, 55, 50, 51, 106, 47, 122, 57, 99, 73, 56, 76, 111, 71, 101, 43, 65, 97, 74, 90, 122, 51, 72, 109, 68, 121, 108, 50, 47, 55, 70, 87, 101, 85, 85, 114, 72, 53, 53, 54, 86, 79, 105, 106, 10, 75, 84, 86, 111, 112, 65, 70, 80, 68, 54, 81, 117, 78, 43, 56, 98, 118, 43, 79, 80, 69, 75, 104, 121, 113, 49, 104, 88, 53, 49, 83, 71, 121, 77, 110, 122, 87, 57, 111, 115, 50, 108, 50, 79, 98, 106, 121, 106, 80, 116, 114, 55, 103, 117, 88, 100, 56, 108, 121, 121, 66, 84, 78, 118, 105, 106, 98, 79, 48, 66, 78, 79, 47, 55, 57, 75, 10, 68, 68, 82, 77, 112, 115, 77, 104, 118, 86, 65, 69, 86, 101, 117, 120, 117, 53, 51, 55, 82, 82, 53, 107, 70, 100, 53, 86, 65, 89, 119, 67, 100, 114, 88, 76, 111, 84, 57, 67, 97, 98, 119, 118, 118, 87, 104, 68, 70, 108, 97, 74, 75, 106, 100, 104, 107, 102, 50, 109, 114, 107, 55, 65, 121, 120, 82, 108, 108, 68, 100, 76, 107, 103, 98, 118, 10, 66, 78, 68, 73, 110, 73, 106, 98, 67, 51, 117, 66, 114, 55, 69, 57, 75, 115, 82, 108, 79, 110, 105, 50, 55, 116, 121, 65, 115, 100, 76, 84, 109, 90, 119, 54, 55, 109, 116, 97, 97, 55, 79, 78, 116, 57, 88, 79, 110, 77, 75, 43, 112, 85, 115, 118, 70, 114, 71, 101, 97, 68, 115, 71, 98, 54, 53, 57, 110, 47, 106, 101, 55, 77, 119, 112, 10, 112, 53, 105, 106, 74, 85, 77, 118, 55, 47, 70, 102, 74, 117, 71, 73, 84, 102, 104, 101, 98, 116, 102, 90, 70, 71, 52, 90, 77, 50, 109, 110, 79, 52, 83, 74, 107, 56, 82, 84, 86, 82, 79, 104, 85, 88, 104, 65, 43, 76, 106, 74, 111, 117, 53, 55, 117, 108, 74, 67, 103, 53, 52, 85, 55, 81, 86, 83, 87, 108, 108, 87, 112, 53, 102, 56, 10, 110, 84, 56, 75, 75, 100, 106, 99, 84, 53, 69, 79, 69, 55, 122, 101, 108, 97, 84, 102, 105, 53, 109, 43, 114, 74, 115, 122, 105, 79, 43, 49, 103, 97, 56, 98, 120, 105, 74, 84, 121, 80, 98, 72, 55, 112, 99, 85, 115, 77, 86, 56, 101, 70, 76, 73, 56, 77, 53, 117, 100, 50, 67, 69, 112, 117, 107, 113, 100, 105, 68, 116, 87, 65, 69, 88, 10, 77, 74, 80, 112, 71, 111, 118, 103, 99, 50, 80, 90, 97, 112, 75, 85, 83, 85, 54, 48, 114, 85, 113, 70, 120, 75, 77, 105, 77, 80, 119, 74, 55, 87, 103, 105, 99, 54, 97, 73, 68, 70, 85, 104, 87, 77, 88, 104, 79, 112, 56, 113, 51, 99, 114, 104, 107, 79, 68, 90, 99, 54, 116, 115, 103, 76, 106, 111, 67, 50, 83, 84, 111, 74, 121, 77, 10, 71, 102, 43, 122, 48, 103, 122, 115, 107, 83, 97, 72, 105, 114, 79, 105, 52, 88, 67, 80, 76, 65, 114, 108, 122, 87, 49, 111, 85, 101, 118, 97, 80, 119, 86, 47, 105, 122, 76, 109, 69, 49, 120, 114, 47, 108, 57, 65, 52, 105, 76, 73, 116, 76, 82, 107, 84, 57, 97, 54, 102, 85, 103, 43, 113, 71, 107, 77, 49, 55, 117, 71, 99, 99, 108, 122, 10, 117, 68, 56, 55, 110, 83, 86, 76, 50, 118, 57, 65, 54, 119, 73, 68, 65, 81, 65, 66, 111, 52, 73, 66, 108, 84, 67, 67, 65, 90, 69, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 67, 66, 52, 81, 89, 68, 86, 82, 48, 103, 66, 73, 72, 90, 77, 73, 72, 87, 77, 73, 72, 84, 10, 66, 103, 107, 114, 66, 103, 69, 69, 65, 98, 53, 89, 65, 65, 77, 119, 103, 99, 85, 119, 103, 90, 77, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 73, 67, 77, 73, 71, 71, 71, 111, 71, 68, 81, 87, 53, 53, 73, 72, 86, 122, 90, 83, 66, 118, 90, 105, 66, 48, 97, 71, 108, 122, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 10, 89, 88, 82, 108, 73, 71, 78, 118, 98, 110, 78, 48, 97, 88, 82, 49, 100, 71, 86, 122, 73, 71, 70, 106, 89, 50, 86, 119, 100, 71, 70, 117, 89, 50, 85, 103, 98, 50, 89, 103, 100, 71, 104, 108, 73, 70, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 77, 121, 66, 68, 90, 88, 74, 48, 10, 97, 87, 90, 112, 89, 50, 70, 48, 90, 83, 66, 81, 98, 50, 120, 112, 89, 51, 107, 103, 76, 121, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 70, 66, 121, 89, 87, 78, 48, 97, 87, 78, 108, 73, 70, 78, 48, 89, 88, 82, 108, 98, 87, 86, 117, 100, 67, 52, 119, 76, 81, 89, 73, 75, 119, 89, 66, 10, 66, 81, 85, 72, 65, 103, 69, 87, 73, 87, 104, 48, 100, 72, 65, 54, 76, 121, 57, 51, 100, 51, 99, 117, 99, 88, 86, 118, 100, 109, 70, 107, 97, 88, 78, 110, 98, 71, 57, 105, 89, 87, 119, 117, 89, 50, 57, 116, 76, 50, 78, 119, 99, 122, 65, 76, 66, 103, 78, 86, 72, 81, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 10, 86, 82, 48, 79, 66, 66, 89, 69, 70, 80, 76, 65, 69, 43, 67, 67, 81, 122, 55, 55, 55, 105, 57, 110, 77, 112, 89, 49, 88, 78, 117, 52, 121, 119, 76, 81, 77, 71, 52, 71, 65, 49, 85, 100, 73, 119, 82, 110, 77, 71, 87, 65, 70, 80, 76, 65, 69, 43, 67, 67, 81, 122, 55, 55, 55, 105, 57, 110, 77, 112, 89, 49, 88, 78, 117, 52, 10, 121, 119, 76, 81, 111, 85, 109, 107, 82, 122, 66, 70, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 67, 84, 84, 69, 90, 77, 66, 99, 71, 65, 49, 85, 69, 67, 104, 77, 81, 85, 88, 86, 118, 86, 109, 70, 107, 97, 88, 77, 103, 84, 71, 108, 116, 97, 88, 82, 108, 90, 68, 69, 98, 77, 66, 107, 71, 65, 49, 85, 69, 10, 65, 120, 77, 83, 85, 88, 86, 118, 86, 109, 70, 107, 97, 88, 77, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 122, 103, 103, 73, 70, 120, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 103, 69, 65, 84, 54, 50, 103, 76, 69, 122, 54, 119, 80, 74, 118, 57, 50, 90, 86, 10, 113, 121, 77, 48, 55, 117, 99, 112, 50, 115, 78, 98, 116, 114, 67, 68, 50, 100, 68, 81, 52, 105, 72, 55, 56, 50, 67, 110, 79, 49, 49, 103, 85, 121, 101, 105, 109, 47, 89, 73, 73, 105, 114, 110, 118, 54, 66, 121, 53, 90, 119, 107, 97, 106, 71, 120, 107, 72, 111, 110, 50, 52, 81, 82, 105, 83, 101, 109, 100, 49, 111, 52, 49, 55, 43, 115, 10, 104, 118, 122, 117, 88, 89, 79, 56, 66, 115, 98, 82, 100, 50, 115, 80, 98, 83, 81, 118, 83, 51, 112, 115, 112, 119, 101, 87, 121, 117, 79, 69, 110, 54, 50, 73, 105, 120, 50, 114, 70, 111, 49, 98, 90, 104, 102, 90, 70, 118, 83, 76, 103, 78, 76, 100, 43, 76, 74, 50, 119, 47, 119, 52, 69, 54, 111, 77, 51, 107, 74, 112, 75, 50, 55, 122, 10, 80, 79, 117, 65, 74, 57, 118, 49, 112, 107, 81, 78, 110, 49, 112, 86, 87, 81, 118, 86, 68, 86, 74, 73, 120, 97, 54, 102, 56, 105, 43, 65, 120, 101, 111, 121, 85, 68, 85, 83, 108, 121, 55, 66, 52, 102, 47, 120, 73, 52, 104, 82, 79, 74, 47, 121, 90, 108, 90, 50, 53, 119, 57, 82, 108, 54, 86, 83, 68, 69, 49, 74, 85, 90, 85, 50, 10, 80, 98, 43, 105, 83, 119, 119, 81, 72, 89, 97, 90, 84, 75, 114, 122, 99, 104, 71, 84, 53, 79, 114, 50, 109, 57, 113, 111, 88, 97, 100, 78, 116, 53, 52, 67, 114, 110, 77, 65, 121, 78, 111, 106, 65, 43, 106, 53, 54, 104, 108, 48, 89, 103, 67, 85, 121, 121, 73, 103, 118, 112, 83, 110, 87, 98, 87, 67, 97, 114, 54, 90, 101, 88, 113, 112, 10, 56, 107, 111, 107, 85, 118, 100, 48, 47, 98, 112, 79, 53, 113, 103, 100, 65, 109, 54, 120, 68, 89, 66, 69, 119, 97, 55, 84, 73, 122, 100, 102, 117, 52, 86, 56, 75, 53, 73, 117, 54, 72, 54, 108, 105, 57, 50, 90, 52, 98, 56, 110, 98, 121, 49, 100, 113, 110, 117, 72, 47, 103, 114, 100, 83, 47, 121, 79, 57, 83, 98, 107, 98, 110, 66, 67, 10, 98, 106, 80, 115, 77, 90, 53, 55, 107, 56, 72, 107, 121, 87, 107, 97, 80, 99, 66, 114, 84, 105, 74, 116, 55, 113, 116, 89, 84, 99, 98, 81, 81, 99, 69, 114, 54, 107, 56, 83, 104, 49, 55, 114, 82, 100, 104, 115, 57, 90, 103, 67, 48, 54, 68, 89, 86, 89, 111, 71, 109, 82, 109, 105, 111, 72, 102, 82, 77, 74, 54, 115, 122, 72, 88, 117, 10, 103, 47, 87, 119, 89, 106, 110, 80, 98, 70, 102, 105, 84, 78, 75, 82, 67, 119, 53, 49, 75, 66, 117, 97, 118, 47, 48, 97, 81, 47, 72, 75, 100, 47, 115, 55, 106, 50, 71, 52, 97, 83, 103, 87, 81, 103, 82, 101, 99, 67, 111, 99, 73, 100, 105, 80, 52, 98, 48, 106, 87, 121, 49, 48, 81, 74, 76, 90, 89, 120, 107, 78, 99, 57, 49, 112, 10, 118, 71, 74, 72, 118, 79, 66, 48, 75, 55, 76, 114, 102, 98, 53, 66, 71, 55, 88, 65, 82, 115, 87, 104, 73, 115, 116, 102, 84, 115, 69, 111, 107, 116, 52, 89, 117, 116, 85, 113, 75, 76, 115, 82, 105, 120, 101, 84, 109, 74, 108, 103, 108, 70, 119, 106, 122, 49, 111, 110, 108, 49, 52, 76, 66, 81, 97, 84, 78, 120, 52, 55, 97, 84, 98, 114, 10, 113, 90, 53, 104, 72, 89, 56, 121, 50, 111, 52, 77, 49, 110, 81, 43, 101, 119, 107, 107, 50, 103, 70, 51, 82, 56, 81, 55, 122, 84, 83, 77, 109, 102, 88, 75, 52, 83, 86, 104, 77, 55, 74, 90, 71, 43, 74, 117, 49, 122, 100, 88, 116, 103, 50, 112, 69, 116, 111, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 101, 99, 117, 114, 105, 116, 121, 32, 67, 111, 109, 109, 117, 110, 105, 99, 97, 116, 105, 111, 110, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 87, 106, 67, 67, 65, 107, 75, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 81, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 75, 85, 68, 69, 89, 77, 66, 89, 71, 65, 49, 85, 69, 67, 104, 77, 80, 10, 85, 48, 86, 68, 84, 48, 48, 103, 86, 72, 74, 49, 99, 51, 81, 117, 98, 109, 86, 48, 77, 83, 99, 119, 74, 81, 89, 68, 86, 81, 81, 76, 69, 120, 53, 84, 90, 87, 78, 49, 99, 109, 108, 48, 101, 83, 66, 68, 98, 50, 49, 116, 100, 87, 53, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 70, 74, 118, 98, 51, 82, 68, 81, 84, 69, 119, 10, 72, 104, 99, 78, 77, 68, 77, 119, 79, 84, 77, 119, 77, 68, 81, 121, 77, 68, 81, 53, 87, 104, 99, 78, 77, 106, 77, 119, 79, 84, 77, 119, 77, 68, 81, 121, 77, 68, 81, 53, 87, 106, 66, 81, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 75, 85, 68, 69, 89, 77, 66, 89, 71, 65, 49, 85, 69, 67, 104, 77, 80, 10, 85, 48, 86, 68, 84, 48, 48, 103, 86, 72, 74, 49, 99, 51, 81, 117, 98, 109, 86, 48, 77, 83, 99, 119, 74, 81, 89, 68, 86, 81, 81, 76, 69, 120, 53, 84, 90, 87, 78, 49, 99, 109, 108, 48, 101, 83, 66, 68, 98, 50, 49, 116, 100, 87, 53, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 70, 74, 118, 98, 51, 82, 68, 81, 84, 69, 119, 10, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 122, 115, 47, 53, 47, 48, 50, 50, 120, 55, 120, 90, 56, 86, 54, 85, 77, 98, 88, 97, 75, 76, 48, 117, 47, 90, 80, 116, 77, 55, 111, 114, 119, 10, 56, 121, 108, 56, 57, 102, 47, 117, 75, 117, 68, 112, 54, 98, 112, 98, 90, 67, 75, 97, 109, 109, 56, 115, 79, 105, 90, 112, 85, 81, 87, 90, 74, 116, 122, 86, 72, 71, 112, 120, 120, 112, 112, 57, 72, 112, 51, 100, 102, 71, 122, 71, 106, 71, 100, 110, 83, 106, 55, 52, 99, 98, 65, 90, 74, 54, 107, 74, 68, 75, 97, 86, 118, 48, 117, 77, 10, 68, 80, 112, 86, 109, 68, 118, 89, 54, 67, 75, 104, 83, 51, 69, 52, 101, 97, 121, 88, 107, 109, 109, 122, 105, 88, 55, 113, 73, 87, 103, 71, 109, 66, 83, 87, 104, 57, 74, 104, 78, 114, 120, 116, 74, 49, 97, 101, 86, 43, 55, 65, 119, 70, 98, 57, 77, 115, 43, 107, 50, 89, 55, 67, 73, 57, 101, 78, 113, 80, 80, 89, 74, 97, 121, 88, 10, 53, 72, 65, 52, 57, 76, 89, 54, 116, 74, 48, 55, 108, 121, 90, 68, 111, 54, 71, 56, 83, 86, 108, 121, 84, 67, 77, 119, 104, 119, 70, 89, 57, 107, 54, 43, 72, 71, 104, 87, 90, 113, 47, 78, 81, 86, 51, 73, 115, 48, 48, 113, 86, 85, 97, 114, 72, 57, 111, 101, 52, 107, 65, 57, 50, 56, 49, 57, 117, 90, 75, 65, 110, 68, 102, 100, 10, 68, 74, 90, 107, 110, 100, 119, 105, 57, 50, 83, 76, 51, 50, 72, 101, 70, 90, 82, 83, 70, 97, 66, 57, 85, 115, 108, 76, 113, 67, 72, 74, 120, 114, 72, 116, 121, 56, 79, 86, 89, 78, 69, 80, 56, 75, 116, 119, 43, 78, 47, 76, 84, 88, 55, 115, 49, 118, 113, 114, 50, 98, 49, 47, 86, 80, 75, 108, 54, 88, 110, 54, 50, 100, 90, 50, 10, 74, 67, 104, 122, 65, 103, 77, 66, 65, 65, 71, 106, 80, 122, 65, 57, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 83, 103, 99, 48, 109, 90, 97, 78, 121, 70, 87, 50, 88, 106, 109, 121, 103, 118, 86, 53, 43, 57, 77, 55, 119, 72, 83, 68, 65, 76, 66, 103, 78, 86, 72, 81, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 10, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 97, 69, 67, 112, 113, 76, 118, 107, 84, 49, 49, 53, 115, 119, 87, 49, 70, 55, 78, 103, 69, 43, 118, 71, 107, 108, 51, 103, 10, 48, 100, 78, 113, 47, 118, 117, 43, 109, 50, 50, 47, 120, 119, 86, 116, 87, 83, 68, 69, 72, 80, 67, 51, 50, 111, 82, 89, 65, 109, 80, 54, 83, 66, 98, 118, 84, 54, 85, 76, 57, 48, 113, 89, 56, 106, 43, 101, 71, 54, 49, 72, 97, 50, 80, 79, 67, 69, 102, 114, 85, 106, 57, 52, 110, 75, 57, 78, 114, 118, 106, 86, 84, 56, 43, 97, 10, 109, 67, 111, 81, 81, 84, 108, 83, 120, 78, 51, 90, 109, 119, 55, 118, 107, 119, 71, 117, 115, 105, 55, 75, 97, 69, 73, 107, 81, 109, 121, 119, 115, 122, 111, 43, 122, 101, 110, 97, 83, 77, 81, 86, 121, 43, 110, 53, 66, 119, 43, 83, 85, 69, 109, 75, 51, 84, 71, 88, 88, 56, 110, 112, 78, 54, 111, 55, 87, 87, 87, 88, 108, 68, 76, 74, 10, 115, 53, 56, 43, 79, 109, 74, 89, 120, 85, 109, 116, 89, 103, 53, 120, 112, 84, 75, 113, 76, 56, 97, 74, 100, 107, 78, 65, 69, 120, 78, 110, 80, 97, 74, 85, 74, 82, 68, 76, 56, 84, 114, 121, 50, 102, 114, 98, 83, 86, 97, 55, 112, 118, 54, 110, 81, 84, 88, 68, 52, 73, 104, 104, 121, 89, 106, 72, 51, 122, 89, 81, 73, 112, 104, 90, 10, 54, 114, 66, 75, 43, 49, 89, 87, 99, 50, 54, 115, 84, 102, 99, 105, 111, 85, 43, 116, 72, 88, 111, 116, 82, 83, 102, 108, 77, 77, 70, 101, 56, 116, 111, 84, 121, 121, 86, 67, 85, 90, 86, 72, 65, 52, 120, 115, 73, 99, 120, 48, 81, 117, 49, 84, 47, 122, 79, 76, 106, 119, 57, 88, 65, 82, 89, 118, 122, 54, 98, 117, 121, 88, 65, 105, 10, 70, 76, 51, 57, 118, 109, 119, 76, 65, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 111, 110, 101, 114, 97, 32, 67, 108, 97, 115, 115, 32, 50, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 73, 68, 67, 67, 65, 103, 105, 103, 65, 119, 73, 66, 65, 103, 73, 66, 72, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 65, 53, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 71, 83, 84, 69, 80, 77, 65, 48, 71, 65, 49, 85, 69, 67, 104, 77, 71, 10, 85, 50, 57, 117, 90, 88, 74, 104, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 68, 69, 120, 66, 84, 98, 50, 53, 108, 99, 109, 69, 103, 81, 50, 120, 104, 99, 51, 77, 121, 73, 69, 78, 66, 77, 66, 52, 88, 68, 84, 65, 120, 77, 68, 81, 119, 78, 106, 65, 51, 77, 106, 107, 48, 77, 70, 111, 88, 68, 84, 73, 120, 77, 68, 81, 119, 10, 78, 106, 65, 51, 77, 106, 107, 48, 77, 70, 111, 119, 79, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 107, 107, 120, 68, 122, 65, 78, 66, 103, 78, 86, 66, 65, 111, 84, 66, 108, 78, 118, 98, 109, 86, 121, 89, 84, 69, 90, 77, 66, 99, 71, 65, 49, 85, 69, 65, 120, 77, 81, 85, 50, 57, 117, 90, 88, 74, 104, 10, 73, 69, 78, 115, 89, 88, 78, 122, 77, 105, 66, 68, 81, 84, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 74, 65, 88, 83, 106, 87, 100, 121, 118, 65, 78, 108, 115, 100, 69, 43, 104, 89, 51, 10, 47, 69, 105, 57, 118, 88, 43, 65, 76, 84, 85, 55, 52, 87, 43, 111, 90, 54, 109, 47, 65, 120, 120, 78, 106, 71, 56, 121, 82, 57, 86, 66, 97, 75, 81, 84, 66, 77, 69, 49, 68, 74, 113, 69, 81, 47, 120, 99, 72, 102, 43, 74, 115, 43, 103, 88, 71, 77, 50, 82, 88, 47, 117, 74, 52, 43, 113, 47, 84, 108, 49, 56, 71, 121, 98, 84, 10, 100, 88, 110, 116, 53, 111, 84, 106, 86, 43, 87, 116, 75, 99, 84, 48, 79, 105, 106, 110, 112, 88, 117, 69, 78, 109, 109, 122, 47, 86, 53, 50, 118, 97, 77, 116, 109, 100, 79, 81, 84, 105, 77, 111, 102, 82, 104, 106, 56, 86, 81, 55, 74, 112, 49, 50, 87, 53, 100, 67, 115, 118, 43, 117, 56, 69, 55, 115, 51, 84, 109, 86, 84, 111, 77, 71, 10, 102, 43, 100, 74, 81, 77, 106, 70, 65, 98, 74, 85, 87, 109, 89, 100, 80, 102, 122, 53, 54, 84, 119, 75, 110, 111, 71, 52, 99, 80, 65, 66, 105, 43, 81, 106, 86, 72, 122, 73, 114, 118, 105, 81, 72, 103, 67, 87, 99, 116, 82, 85, 122, 50, 69, 106, 118, 79, 114, 55, 110, 81, 75, 86, 48, 98, 97, 53, 99, 84, 112, 112, 67, 68, 56, 80, 10, 116, 79, 70, 67, 120, 52, 106, 49, 80, 53, 105, 111, 112, 55, 111, 99, 52, 72, 70, 120, 55, 49, 104, 88, 103, 86, 66, 54, 88, 71, 116, 48, 82, 103, 54, 68, 65, 53, 106, 68, 106, 113, 104, 117, 56, 110, 89, 121, 98, 105, 101, 68, 119, 110, 80, 122, 51, 66, 106, 111, 116, 74, 80, 113, 100, 85, 82, 114, 66, 71, 65, 103, 99, 86, 101, 72, 10, 110, 102, 79, 43, 111, 74, 65, 106, 80, 89, 111, 107, 52, 100, 111, 104, 50, 56, 77, 67, 65, 119, 69, 65, 65, 97, 77, 122, 77, 68, 69, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 82, 66, 103, 78, 86, 72, 81, 52, 69, 67, 103, 81, 73, 83, 113, 67, 113, 87, 73, 84, 84, 10, 88, 106, 119, 119, 67, 119, 89, 68, 86, 82, 48, 80, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 66, 65, 81, 66, 97, 122, 111, 102, 53, 70, 110, 73, 86, 86, 48, 115, 100, 50, 90, 118, 110, 111, 105, 89, 119, 55, 74, 78, 110, 51, 57, 89, 116, 10, 48, 106, 83, 118, 57, 122, 105, 108, 122, 113, 115, 87, 117, 97, 115, 118, 102, 68, 88, 76, 114, 78, 65, 80, 116, 69, 119, 114, 47, 73, 68, 118, 97, 52, 121, 82, 88, 122, 90, 50, 57, 57, 117, 122, 71, 120, 110, 113, 57, 76, 73, 82, 47, 87, 70, 120, 82, 76, 56, 111, 115, 122, 111, 100, 118, 55, 78, 68, 54, 74, 43, 47, 51, 68, 69, 73, 10, 99, 98, 67, 100, 106, 100, 89, 48, 82, 122, 75, 81, 120, 109, 85, 107, 57, 54, 66, 75, 102, 65, 82, 122, 106, 122, 108, 118, 70, 52, 120, 121, 116, 98, 49, 76, 121, 72, 114, 52, 101, 52, 80, 68, 75, 69, 54, 99, 67, 101, 112, 110, 80, 55, 74, 110, 66, 66, 118, 68, 70, 78, 114, 52, 53, 48, 107, 107, 107, 100, 65, 100, 97, 118, 112, 104, 10, 79, 101, 57, 114, 53, 121, 70, 49, 66, 103, 102, 89, 69, 114, 81, 104, 73, 72, 66, 67, 99, 89, 72, 97, 80, 74, 111, 50, 118, 113, 90, 98, 68, 87, 112, 115, 109, 104, 43, 82, 101, 47, 110, 53, 55, 48, 75, 54, 84, 107, 54, 101, 122, 65, 121, 78, 108, 78, 122, 90, 82, 90, 120, 101, 55, 69, 74, 81, 89, 54, 55, 48, 88, 99, 83, 120, 10, 69, 116, 122, 75, 79, 54, 103, 117, 110, 82, 82, 97, 66, 88, 87, 51, 55, 78, 100, 106, 52, 114, 111, 49, 116, 103, 81, 73, 107, 101, 106, 97, 110, 90, 122, 50, 90, 114, 85, 89, 114, 65, 113, 109, 86, 67, 89, 48, 77, 57, 73, 98, 119, 100, 82, 47, 71, 106, 113, 79, 67, 54, 111, 121, 98, 116, 118, 56, 84, 121, 87, 102, 50, 84, 76, 72, 10, 108, 108, 112, 119, 114, 78, 57, 77, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 85, 84, 78, 32, 85, 83, 69, 82, 70, 105, 114, 115, 116, 32, 72, 97, 114, 100, 119, 97, 114, 101, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 100, 68, 67, 67, 65, 49, 121, 103, 65, 119, 73, 66, 65, 103, 73, 81, 82, 76, 52, 77, 105, 49, 65, 65, 74, 76, 81, 82, 48, 122, 89, 113, 47, 109, 85, 75, 47, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 66, 108, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 86, 86, 77, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 103, 84, 65, 108, 86, 85, 77, 82, 99, 119, 70, 81, 89, 68, 86, 81, 81, 72, 69, 119, 53, 84, 89, 87, 120, 48, 73, 69, 120, 104, 97, 50, 85, 103, 81, 50, 108, 48, 101, 84, 69, 101, 77, 66, 119, 71, 65, 49, 85, 69, 67, 104, 77, 86, 86, 71, 104, 108, 10, 73, 70, 86, 84, 82, 86, 74, 85, 85, 108, 86, 84, 86, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 77, 83, 69, 119, 72, 119, 89, 68, 86, 81, 81, 76, 69, 120, 104, 111, 100, 72, 82, 119, 79, 105, 56, 118, 100, 51, 100, 51, 76, 110, 86, 122, 90, 88, 74, 48, 99, 110, 86, 122, 100, 67, 53, 106, 98, 50, 48, 120, 72, 122, 65, 100, 10, 66, 103, 78, 86, 66, 65, 77, 84, 70, 108, 86, 85, 84, 105, 49, 86, 85, 48, 86, 83, 82, 109, 108, 121, 99, 51, 81, 116, 83, 71, 70, 121, 90, 72, 100, 104, 99, 109, 85, 119, 72, 104, 99, 78, 79, 84, 107, 119, 78, 122, 65, 53, 77, 84, 103, 120, 77, 68, 81, 121, 87, 104, 99, 78, 77, 84, 107, 119, 78, 122, 65, 53, 77, 84, 103, 120, 10, 79, 84, 73, 121, 87, 106, 67, 66, 108, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 103, 84, 65, 108, 86, 85, 77, 82, 99, 119, 70, 81, 89, 68, 86, 81, 81, 72, 69, 119, 53, 84, 89, 87, 120, 48, 73, 69, 120, 104, 97, 50, 85, 103, 81, 50, 108, 48, 10, 101, 84, 69, 101, 77, 66, 119, 71, 65, 49, 85, 69, 67, 104, 77, 86, 86, 71, 104, 108, 73, 70, 86, 84, 82, 86, 74, 85, 85, 108, 86, 84, 86, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 77, 83, 69, 119, 72, 119, 89, 68, 86, 81, 81, 76, 69, 120, 104, 111, 100, 72, 82, 119, 79, 105, 56, 118, 100, 51, 100, 51, 76, 110, 86, 122, 10, 90, 88, 74, 48, 99, 110, 86, 122, 100, 67, 53, 106, 98, 50, 48, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 77, 84, 70, 108, 86, 85, 84, 105, 49, 86, 85, 48, 86, 83, 82, 109, 108, 121, 99, 51, 81, 116, 83, 71, 70, 121, 90, 72, 100, 104, 99, 109, 85, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 10, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 120, 57, 56, 77, 52, 80, 55, 83, 111, 102, 56, 56, 53, 103, 108, 70, 110, 48, 71, 50, 102, 48, 118, 57, 89, 56, 43, 101, 102, 75, 43, 119, 78, 105, 86, 83, 90, 117, 84, 105, 90, 70, 118, 102, 103, 73, 88, 108, 73, 10, 119, 114, 116, 104, 100, 66, 75, 87, 72, 84, 120, 113, 99, 116, 85, 56, 69, 71, 99, 54, 79, 101, 48, 114, 69, 56, 49, 109, 54, 53, 85, 74, 77, 54, 82, 115, 108, 55, 72, 111, 120, 117, 122, 66, 100, 88, 109, 99, 82, 108, 54, 78, 113, 57, 66, 113, 47, 98, 107, 113, 86, 82, 99, 81, 86, 76, 77, 90, 56, 74, 114, 50, 56, 98, 70, 100, 10, 116, 113, 100, 116, 43, 43, 66, 120, 70, 50, 117, 105, 105, 80, 115, 65, 51, 47, 52, 97, 77, 88, 99, 77, 109, 103, 70, 54, 115, 84, 76, 106, 75, 119, 69, 72, 79, 71, 55, 68, 112, 86, 52, 106, 118, 69, 87, 98, 101, 49, 68, 66, 121, 84, 67, 80, 50, 43, 85, 114, 101, 116, 78, 98, 43, 122, 78, 65, 72, 113, 68, 86, 109, 66, 101, 56, 10, 105, 52, 102, 68, 105, 100, 78, 100, 111, 73, 54, 121, 113, 113, 114, 50, 106, 109, 109, 73, 66, 115, 88, 54, 105, 83, 72, 122, 67, 74, 49, 112, 76, 103, 107, 122, 109, 121, 107, 78, 82, 103, 43, 77, 122, 69, 107, 48, 115, 71, 108, 82, 118, 102, 107, 71, 122, 87, 105, 116, 90, 107, 121, 56, 80, 113, 120, 104, 118, 81, 113, 73, 68, 115, 106, 102, 10, 80, 101, 53, 56, 66, 69, 121, 100, 67, 108, 53, 114, 107, 100, 98, 117, 120, 43, 48, 111, 106, 97, 116, 78, 104, 52, 108, 122, 48, 71, 54, 107, 48, 66, 52, 87, 105, 120, 84, 104, 100, 107, 81, 68, 102, 50, 79, 115, 53, 77, 49, 74, 110, 77, 87, 83, 57, 75, 115, 121, 111, 85, 104, 98, 65, 103, 77, 66, 65, 65, 71, 106, 103, 98, 107, 119, 10, 103, 98, 89, 119, 67, 119, 89, 68, 86, 82, 48, 80, 66, 65, 81, 68, 65, 103, 72, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 75, 70, 121, 88, 121, 89, 98, 75, 74, 104, 68, 108, 86, 48, 72, 78, 57, 87, 70, 10, 108, 112, 49, 76, 48, 115, 78, 70, 77, 69, 81, 71, 65, 49, 85, 100, 72, 119, 81, 57, 77, 68, 115, 119, 79, 97, 65, 51, 111, 68, 87, 71, 77, 50, 104, 48, 100, 72, 65, 54, 76, 121, 57, 106, 99, 109, 119, 117, 100, 88, 78, 108, 99, 110, 82, 121, 100, 88, 78, 48, 76, 109, 78, 118, 98, 83, 57, 86, 86, 69, 52, 116, 86, 86, 78, 70, 10, 85, 107, 90, 112, 99, 110, 78, 48, 76, 85, 104, 104, 99, 109, 82, 51, 89, 88, 74, 108, 76, 109, 78, 121, 98, 68, 65, 120, 66, 103, 78, 86, 72, 83, 85, 69, 75, 106, 65, 111, 66, 103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 68, 65, 81, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 119, 85, 71, 67, 67, 115, 71, 65, 81, 85, 70, 10, 66, 119, 77, 71, 66, 103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 68, 66, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 82, 120, 107, 80, 51, 110, 84, 71, 109, 90, 101, 118, 47, 75, 48, 111, 88, 110, 87, 79, 54, 121, 49, 110, 55, 107, 53, 55, 75, 57, 99, 77, 10, 47, 47, 98, 101, 121, 49, 87, 105, 67, 117, 70, 77, 86, 71, 87, 84, 89, 71, 117, 102, 69, 112, 121, 116, 88, 111, 77, 115, 54, 49, 113, 117, 119, 79, 81, 116, 57, 65, 66, 106, 72, 98, 106, 65, 98, 80, 76, 80, 83, 98, 116, 78, 107, 50, 56, 71, 112, 103, 111, 105, 115, 107, 108, 105, 67, 69, 55, 47, 121, 77, 103, 85, 115, 111, 103, 87, 10, 88, 101, 99, 66, 53, 66, 75, 86, 53, 85, 85, 48, 115, 52, 116, 112, 118, 99, 43, 48, 104, 89, 57, 49, 85, 90, 53, 57, 79, 106, 103, 54, 70, 69, 103, 83, 120, 118, 117, 110, 79, 120, 113, 78, 68, 89, 74, 65, 66, 43, 103, 69, 67, 74, 67, 104, 105, 99, 115, 90, 85, 78, 47, 75, 72, 65, 71, 56, 72, 81, 81, 90, 101, 120, 66, 50, 10, 108, 122, 118, 117, 107, 74, 68, 75, 120, 65, 52, 102, 70, 109, 53, 49, 55, 122, 80, 52, 48, 50, 57, 98, 72, 112, 98, 106, 52, 72, 82, 51, 100, 72, 117, 75, 111, 109, 52, 116, 51, 88, 98, 87, 79, 84, 67, 67, 56, 75, 117, 99, 85, 118, 73, 113, 120, 54, 57, 74, 88, 110, 55, 72, 97, 79, 87, 67, 103, 99, 104, 113, 74, 47, 107, 110, 10, 105, 67, 114, 86, 87, 70, 67, 86, 72, 47, 65, 55, 72, 70, 101, 55, 102, 82, 81, 53, 89, 105, 117, 97, 121, 90, 83, 83, 75, 113, 77, 105, 68, 80, 43, 74, 74, 110, 49, 102, 73, 121, 116, 72, 49, 120, 85, 100, 113, 87, 113, 101, 85, 81, 48, 113, 85, 90, 54, 66, 43, 100, 81, 55, 88, 110, 65, 83, 102, 120, 65, 121, 110, 66, 54, 55, 10, 110, 102, 104, 109, 113, 65, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 97, 109, 101, 114, 102, 105, 114, 109, 97, 32, 67, 104, 97, 109, 98, 101, 114, 115, 32, 111, 102, 32, 67, 111, 109, 109, 101, 114, 99, 101, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 118, 84, 67, 67, 65, 54, 87, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 47, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 70, 86, 84, 69, 110, 77, 67, 85, 71, 65, 49, 85, 69, 67, 104, 77, 101, 10, 81, 85, 77, 103, 81, 50, 70, 116, 90, 88, 74, 109, 97, 88, 74, 116, 89, 83, 66, 84, 81, 83, 66, 68, 83, 85, 89, 103, 81, 84, 103, 121, 78, 122, 81, 122, 77, 106, 103, 51, 77, 83, 77, 119, 73, 81, 89, 68, 86, 81, 81, 76, 69, 120, 112, 111, 100, 72, 82, 119, 79, 105, 56, 118, 100, 51, 100, 51, 76, 109, 78, 111, 89, 87, 49, 105, 10, 90, 88, 74, 122, 97, 87, 100, 117, 76, 109, 57, 121, 90, 122, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 65, 120, 77, 90, 81, 50, 104, 104, 98, 87, 74, 108, 99, 110, 77, 103, 98, 50, 89, 103, 81, 50, 57, 116, 98, 87, 86, 121, 89, 50, 85, 103, 85, 109, 57, 118, 100, 68, 65, 101, 70, 119, 48, 119, 77, 122, 65, 53, 77, 122, 65, 120, 10, 78, 106, 69, 122, 78, 68, 78, 97, 70, 119, 48, 122, 78, 122, 65, 53, 77, 122, 65, 120, 78, 106, 69, 122, 78, 68, 82, 97, 77, 72, 56, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 86, 86, 77, 83, 99, 119, 74, 81, 89, 68, 86, 81, 81, 75, 69, 120, 53, 66, 81, 121, 66, 68, 89, 87, 49, 108, 99, 109, 90, 112, 10, 99, 109, 49, 104, 73, 70, 78, 66, 73, 69, 78, 74, 82, 105, 66, 66, 79, 68, 73, 51, 78, 68, 77, 121, 79, 68, 99, 120, 73, 122, 65, 104, 66, 103, 78, 86, 66, 65, 115, 84, 71, 109, 104, 48, 100, 72, 65, 54, 76, 121, 57, 51, 100, 51, 99, 117, 89, 50, 104, 104, 98, 87, 74, 108, 99, 110, 78, 112, 90, 50, 52, 117, 98, 51, 74, 110, 10, 77, 83, 73, 119, 73, 65, 89, 68, 86, 81, 81, 68, 69, 120, 108, 68, 97, 71, 70, 116, 89, 109, 86, 121, 99, 121, 66, 118, 90, 105, 66, 68, 98, 50, 49, 116, 90, 88, 74, 106, 90, 83, 66, 83, 98, 50, 57, 48, 77, 73, 73, 66, 73, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 10, 65, 81, 48, 65, 77, 73, 73, 66, 67, 65, 75, 67, 65, 81, 69, 65, 116, 122, 90, 86, 53, 97, 86, 100, 71, 68, 68, 103, 50, 111, 108, 85, 107, 102, 122, 73, 120, 49, 76, 52, 76, 49, 68, 90, 55, 55, 70, 49, 99, 50, 86, 72, 102, 82, 116, 98, 117, 110, 88, 70, 47, 75, 71, 73, 74, 80, 111, 118, 55, 99, 111, 73, 83, 106, 108, 85, 10, 120, 70, 70, 54, 116, 100, 112, 103, 54, 106, 103, 56, 103, 98, 76, 76, 56, 98, 118, 90, 107, 83, 77, 47, 83, 65, 70, 119, 100, 97, 107, 70, 75, 113, 48, 102, 99, 102, 80, 74, 86, 68, 48, 100, 66, 109, 112, 65, 80, 114, 77, 77, 104, 101, 53, 99, 71, 51, 110, 67, 89, 115, 83, 52, 78, 111, 52, 49, 88, 81, 69, 77, 73, 119, 82, 72, 10, 78, 97, 113, 98, 89, 69, 54, 103, 90, 106, 51, 76, 74, 103, 113, 99, 81, 75, 72, 48, 88, 90, 105, 47, 99, 97, 117, 108, 65, 71, 103, 113, 55, 89, 78, 54, 68, 54, 73, 85, 116, 100, 81, 105, 115, 52, 67, 119, 80, 65, 120, 97, 85, 87, 107, 116, 87, 66, 105, 80, 55, 90, 109, 101, 56, 97, 55, 105, 108, 101, 98, 50, 82, 54, 106, 87, 10, 68, 65, 43, 119, 87, 70, 106, 98, 119, 50, 89, 51, 110, 112, 117, 82, 86, 68, 77, 51, 48, 112, 81, 99, 97, 107, 106, 74, 121, 102, 75, 108, 50, 113, 85, 77, 73, 47, 99, 106, 68, 112, 119, 121, 86, 86, 53, 120, 110, 73, 81, 70, 85, 90, 111, 116, 47, 101, 90, 79, 75, 106, 82, 97, 51, 115, 112, 65, 78, 50, 99, 77, 86, 67, 70, 86, 10, 100, 57, 111, 75, 68, 77, 121, 88, 114, 111, 68, 99, 108, 68, 90, 75, 57, 68, 55, 79, 78, 104, 77, 101, 85, 43, 83, 115, 84, 106, 111, 70, 55, 78, 117, 117, 99, 112, 119, 52, 105, 57, 65, 53, 79, 52, 107, 75, 80, 110, 102, 43, 100, 81, 73, 66, 65, 54, 79, 67, 65, 85, 81, 119, 103, 103, 70, 65, 77, 66, 73, 71, 65, 49, 85, 100, 10, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 119, 119, 80, 65, 89, 68, 86, 82, 48, 102, 66, 68, 85, 119, 77, 122, 65, 120, 111, 67, 43, 103, 76, 89, 89, 114, 97, 72, 82, 48, 99, 68, 111, 118, 76, 50, 78, 121, 98, 67, 53, 106, 97, 71, 70, 116, 89, 109, 86, 121, 99, 50, 108, 110, 98, 105, 53, 118, 10, 99, 109, 99, 118, 89, 50, 104, 104, 98, 87, 74, 108, 99, 110, 78, 121, 98, 50, 57, 48, 76, 109, 78, 121, 98, 68, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 52, 53, 84, 49, 115, 85, 51, 112, 50, 54, 69, 112, 87, 49, 101, 76, 84, 88, 89, 71, 100, 117, 72, 82, 111, 111, 111, 119, 68, 103, 89, 68, 86, 82, 48, 80, 10, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 69, 71, 67, 87, 67, 71, 83, 65, 71, 71, 43, 69, 73, 66, 65, 81, 81, 69, 65, 119, 73, 65, 66, 122, 65, 110, 66, 103, 78, 86, 72, 82, 69, 69, 73, 68, 65, 101, 103, 82, 120, 106, 97, 71, 70, 116, 89, 109, 86, 121, 99, 51, 74, 118, 98, 51, 82, 65, 89, 50, 104, 104, 10, 98, 87, 74, 108, 99, 110, 78, 112, 90, 50, 52, 117, 98, 51, 74, 110, 77, 67, 99, 71, 65, 49, 85, 100, 69, 103, 81, 103, 77, 66, 54, 66, 72, 71, 78, 111, 89, 87, 49, 105, 90, 88, 74, 122, 99, 109, 57, 118, 100, 69, 66, 106, 97, 71, 70, 116, 89, 109, 86, 121, 99, 50, 108, 110, 98, 105, 53, 118, 99, 109, 99, 119, 87, 65, 89, 68, 10, 86, 82, 48, 103, 66, 70, 69, 119, 84, 122, 66, 78, 66, 103, 115, 114, 66, 103, 69, 69, 65, 89, 71, 72, 76, 103, 111, 68, 65, 84, 65, 43, 77, 68, 119, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 73, 66, 70, 106, 66, 111, 100, 72, 82, 119, 79, 105, 56, 118, 89, 51, 66, 122, 76, 109, 78, 111, 89, 87, 49, 105, 90, 88, 74, 122, 10, 97, 87, 100, 117, 76, 109, 57, 121, 90, 121, 57, 106, 99, 72, 77, 118, 89, 50, 104, 104, 98, 87, 74, 108, 99, 110, 78, 121, 98, 50, 57, 48, 76, 109, 104, 48, 98, 87, 119, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 65, 120, 66, 108, 56, 73, 97, 104, 115, 65, 105, 10, 102, 74, 47, 55, 107, 80, 77, 97, 48, 81, 79, 120, 55, 120, 80, 53, 73, 86, 56, 69, 110, 78, 114, 74, 112, 89, 48, 110, 98, 74, 97, 72, 107, 98, 53, 66, 107, 65, 70, 121, 107, 43, 99, 101, 102, 86, 47, 50, 105, 99, 90, 100, 112, 48, 65, 74, 80, 97, 120, 74, 82, 85, 88, 99, 76, 111, 48, 119, 97, 76, 73, 74, 117, 118, 118, 68, 10, 76, 56, 121, 54, 67, 57, 56, 47, 100, 51, 116, 71, 102, 84, 111, 83, 74, 73, 54, 87, 106, 122, 119, 70, 67, 109, 47, 83, 108, 67, 103, 100, 98, 81, 122, 65, 76, 111, 103, 105, 49, 100, 106, 80, 72, 82, 80, 72, 56, 69, 106, 88, 49, 119, 87, 110, 122, 56, 100, 72, 110, 106, 115, 56, 78, 77, 105, 65, 84, 57, 81, 85, 117, 47, 119, 78, 10, 85, 80, 102, 54, 115, 43, 120, 67, 88, 54, 110, 100, 98, 99, 106, 48, 100, 99, 57, 55, 119, 88, 73, 109, 115, 81, 69, 99, 88, 67, 122, 57, 101, 107, 54, 48, 65, 99, 85, 70, 86, 55, 110, 110, 80, 75, 111, 70, 50, 89, 106, 112, 66, 48, 90, 66, 122, 117, 57, 66, 103, 97, 53, 89, 51, 52, 79, 105, 114, 115, 114, 88, 100, 120, 47, 110, 10, 65, 68, 121, 100, 98, 52, 55, 107, 77, 103, 107, 100, 84, 88, 103, 48, 101, 68, 81, 56, 108, 74, 115, 109, 55, 85, 57, 120, 120, 104, 108, 54, 118, 83, 65, 105, 83, 70, 114, 43, 83, 51, 48, 68, 116, 43, 100, 89, 118, 115, 89, 121, 84, 110, 81, 101, 97, 78, 50, 111, 97, 70, 117, 122, 80, 117, 53, 105, 102, 100, 109, 65, 54, 65, 112, 49, 10, 101, 114, 102, 117, 116, 71, 87, 97, 73, 90, 68, 103, 113, 116, 67, 89, 118, 68, 105, 49, 99, 122, 121, 76, 43, 78, 119, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 97, 109, 101, 114, 102, 105, 114, 109, 97, 32, 71, 108, 111, 98, 97, 108, 32, 67, 104, 97, 109, 98, 101, 114, 115, 105, 103, 110, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 120, 84, 67, 67, 65, 54, 50, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 57, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 70, 86, 84, 69, 110, 77, 67, 85, 71, 65, 49, 85, 69, 67, 104, 77, 101, 10, 81, 85, 77, 103, 81, 50, 70, 116, 90, 88, 74, 109, 97, 88, 74, 116, 89, 83, 66, 84, 81, 83, 66, 68, 83, 85, 89, 103, 81, 84, 103, 121, 78, 122, 81, 122, 77, 106, 103, 51, 77, 83, 77, 119, 73, 81, 89, 68, 86, 81, 81, 76, 69, 120, 112, 111, 100, 72, 82, 119, 79, 105, 56, 118, 100, 51, 100, 51, 76, 109, 78, 111, 89, 87, 49, 105, 10, 90, 88, 74, 122, 97, 87, 100, 117, 76, 109, 57, 121, 90, 122, 69, 103, 77, 66, 52, 71, 65, 49, 85, 69, 65, 120, 77, 88, 82, 50, 120, 118, 89, 109, 70, 115, 73, 69, 78, 111, 89, 87, 49, 105, 90, 88, 74, 122, 97, 87, 100, 117, 73, 70, 74, 118, 98, 51, 81, 119, 72, 104, 99, 78, 77, 68, 77, 119, 79, 84, 77, 119, 77, 84, 89, 120, 10, 78, 68, 69, 52, 87, 104, 99, 78, 77, 122, 99, 119, 79, 84, 77, 119, 77, 84, 89, 120, 78, 68, 69, 52, 87, 106, 66, 57, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 70, 86, 84, 69, 110, 77, 67, 85, 71, 65, 49, 85, 69, 67, 104, 77, 101, 81, 85, 77, 103, 81, 50, 70, 116, 90, 88, 74, 109, 97, 88, 74, 116, 10, 89, 83, 66, 84, 81, 83, 66, 68, 83, 85, 89, 103, 81, 84, 103, 121, 78, 122, 81, 122, 77, 106, 103, 51, 77, 83, 77, 119, 73, 81, 89, 68, 86, 81, 81, 76, 69, 120, 112, 111, 100, 72, 82, 119, 79, 105, 56, 118, 100, 51, 100, 51, 76, 109, 78, 111, 89, 87, 49, 105, 90, 88, 74, 122, 97, 87, 100, 117, 76, 109, 57, 121, 90, 122, 69, 103, 10, 77, 66, 52, 71, 65, 49, 85, 69, 65, 120, 77, 88, 82, 50, 120, 118, 89, 109, 70, 115, 73, 69, 78, 111, 89, 87, 49, 105, 90, 88, 74, 122, 97, 87, 100, 117, 73, 70, 74, 118, 98, 51, 81, 119, 103, 103, 69, 103, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 81, 65, 119, 10, 103, 103, 69, 73, 65, 111, 73, 66, 65, 81, 67, 105, 99, 75, 76, 81, 110, 48, 75, 117, 87, 120, 102, 72, 50, 72, 51, 80, 70, 73, 80, 56, 84, 56, 109, 104, 116, 120, 79, 118, 105, 116, 101, 101, 80, 103, 81, 75, 107, 111, 116, 103, 86, 118, 113, 48, 77, 105, 43, 73, 84, 97, 70, 103, 67, 80, 83, 51, 67, 85, 54, 103, 83, 83, 57, 74, 10, 49, 116, 80, 102, 110, 90, 100, 97, 110, 53, 81, 69, 99, 79, 119, 47, 87, 100, 109, 51, 122, 71, 97, 76, 109, 70, 73, 111, 67, 81, 76, 102, 120, 83, 43, 69, 106, 88, 113, 88, 100, 55, 47, 115, 81, 74, 48, 108, 99, 113, 117, 49, 80, 122, 75, 89, 43, 55, 101, 51, 47, 72, 75, 69, 53, 84, 87, 72, 43, 86, 88, 54, 111, 120, 56, 79, 10, 98, 121, 52, 111, 51, 87, 109, 103, 50, 85, 73, 81, 120, 118, 105, 49, 82, 77, 76, 81, 81, 51, 47, 98, 118, 79, 83, 105, 80, 71, 112, 86, 101, 65, 112, 51, 113, 100, 106, 113, 71, 84, 75, 51, 76, 47, 53, 99, 80, 120, 118, 117, 115, 90, 106, 115, 121, 113, 49, 54, 97, 85, 88, 106, 108, 103, 57, 86, 57, 117, 98, 116, 100, 101, 112, 108, 10, 54, 68, 74, 87, 107, 48, 97, 74, 113, 67, 87, 75, 90, 81, 98, 117, 97, 55, 57, 53, 66, 57, 68, 120, 116, 54, 47, 116, 76, 69, 50, 83, 117, 56, 67, 111, 88, 54, 100, 110, 102, 81, 84, 121, 70, 81, 104, 119, 114, 74, 76, 87, 102, 81, 84, 83, 77, 47, 116, 77, 116, 103, 115, 76, 43, 120, 114, 74, 120, 73, 48, 68, 113, 88, 53, 99, 10, 56, 108, 67, 114, 69, 113, 87, 104, 122, 48, 104, 81, 112, 101, 47, 83, 121, 66, 111, 84, 43, 114, 66, 47, 115, 89, 73, 99, 100, 50, 111, 80, 88, 57, 119, 76, 108, 89, 47, 118, 81, 51, 55, 109, 82, 81, 107, 108, 65, 103, 69, 68, 111, 52, 73, 66, 85, 68, 67, 67, 65, 85, 119, 119, 69, 103, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 10, 66, 65, 103, 119, 66, 103, 69, 66, 47, 119, 73, 66, 68, 68, 65, 47, 66, 103, 78, 86, 72, 82, 56, 69, 79, 68, 65, 50, 77, 68, 83, 103, 77, 113, 65, 119, 104, 105, 53, 111, 100, 72, 82, 119, 79, 105, 56, 118, 89, 51, 74, 115, 76, 109, 78, 111, 89, 87, 49, 105, 90, 88, 74, 122, 97, 87, 100, 117, 76, 109, 57, 121, 90, 121, 57, 106, 10, 97, 71, 70, 116, 89, 109, 86, 121, 99, 50, 108, 110, 98, 110, 74, 118, 98, 51, 81, 117, 89, 51, 74, 115, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 68, 110, 68, 97, 102, 115, 74, 52, 119, 84, 99, 98, 79, 88, 54, 48, 81, 113, 43, 85, 68, 112, 102, 113, 112, 70, 68, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 10, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 69, 81, 89, 74, 89, 73, 90, 73, 65, 89, 98, 52, 81, 103, 69, 66, 66, 65, 81, 68, 65, 103, 65, 72, 77, 67, 111, 71, 65, 49, 85, 100, 69, 81, 81, 106, 77, 67, 71, 66, 72, 50, 78, 111, 89, 87, 49, 105, 90, 88, 74, 122, 97, 87, 100, 117, 99, 109, 57, 118, 100, 69, 66, 106, 10, 97, 71, 70, 116, 89, 109, 86, 121, 99, 50, 108, 110, 98, 105, 53, 118, 99, 109, 99, 119, 75, 103, 89, 68, 86, 82, 48, 83, 66, 67, 77, 119, 73, 89, 69, 102, 89, 50, 104, 104, 98, 87, 74, 108, 99, 110, 78, 112, 90, 50, 53, 121, 98, 50, 57, 48, 81, 71, 78, 111, 89, 87, 49, 105, 90, 88, 74, 122, 97, 87, 100, 117, 76, 109, 57, 121, 10, 90, 122, 66, 98, 66, 103, 78, 86, 72, 83, 65, 69, 86, 68, 66, 83, 77, 70, 65, 71, 67, 121, 115, 71, 65, 81, 81, 66, 103, 89, 99, 117, 67, 103, 69, 66, 77, 69, 69, 119, 80, 119, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 103, 69, 87, 77, 50, 104, 48, 100, 72, 65, 54, 76, 121, 57, 106, 99, 72, 77, 117, 89, 50, 104, 104, 10, 98, 87, 74, 108, 99, 110, 78, 112, 90, 50, 52, 117, 98, 51, 74, 110, 76, 50, 78, 119, 99, 121, 57, 106, 97, 71, 70, 116, 89, 109, 86, 121, 99, 50, 108, 110, 98, 110, 74, 118, 98, 51, 81, 117, 97, 72, 82, 116, 98, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 10, 80, 68, 116, 119, 107, 102, 107, 69, 86, 67, 101, 82, 52, 101, 51, 116, 47, 109, 104, 47, 89, 86, 51, 108, 81, 87, 86, 80, 77, 118, 69, 89, 66, 90, 82, 113, 72, 78, 52, 102, 99, 78, 115, 43, 101, 122, 73, 67, 78, 76, 85, 77, 98, 75, 71, 75, 102, 75, 88, 48, 106, 47, 47, 85, 50, 75, 48, 88, 49, 83, 48, 69, 48, 84, 57, 89, 10, 103, 79, 75, 66, 87, 89, 105, 43, 119, 79, 78, 71, 107, 121, 84, 43, 107, 76, 48, 109, 111, 106, 65, 116, 54, 74, 99, 109, 86, 122, 87, 74, 100, 74, 89, 89, 57, 104, 88, 105, 114, 121, 81, 90, 86, 103, 73, 67, 115, 114, 111, 80, 70, 79, 114, 71, 105, 109, 98, 66, 104, 107, 86, 86, 105, 55, 54, 83, 118, 112, 121, 107, 66, 77, 100, 74, 10, 80, 74, 55, 111, 75, 88, 113, 74, 49, 47, 54, 118, 47, 50, 106, 49, 112, 82, 101, 81, 118, 97, 121, 90, 122, 75, 87, 71, 86, 119, 108, 110, 82, 116, 118, 87, 70, 115, 74, 71, 56, 101, 83, 112, 85, 80, 87, 80, 48, 90, 73, 86, 48, 49, 56, 43, 120, 103, 66, 74, 79, 109, 53, 89, 115, 116, 72, 82, 74, 119, 48, 108, 121, 68, 76, 52, 10, 73, 66, 72, 78, 102, 84, 73, 122, 83, 74, 82, 85, 84, 78, 51, 99, 101, 99, 81, 119, 110, 43, 117, 79, 117, 70, 87, 49, 49, 52, 104, 99, 120, 87, 111, 107, 80, 98, 76, 84, 66, 81, 78, 82, 120, 103, 102, 118, 122, 66, 82, 121, 100, 68, 49, 117, 99, 115, 52, 89, 75, 73, 120, 75, 111, 72, 102, 108, 67, 83, 116, 70, 82, 69, 101, 115, 10, 116, 50, 100, 47, 65, 89, 111, 70, 87, 112, 79, 43, 111, 99, 72, 47, 43, 79, 99, 79, 90, 54, 82, 72, 83, 88, 90, 100, 100, 90, 65, 97, 57, 83, 97, 80, 56, 65, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 88, 82, 97, 109, 112, 32, 71, 108, 111, 98, 97, 108, 32, 67, 65, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 77, 68, 67, 67, 65, 120, 105, 103, 65, 119, 73, 66, 65, 103, 73, 81, 85, 74, 82, 115, 55, 66, 106, 113, 49, 90, 120, 78, 49, 90, 102, 118, 100, 89, 43, 103, 114, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 66, 103, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 86, 86, 77, 120, 72, 106, 65, 99, 66, 103, 78, 86, 66, 65, 115, 84, 70, 88, 100, 51, 100, 121, 53, 52, 99, 109, 70, 116, 99, 72, 78, 108, 89, 51, 86, 121, 97, 88, 82, 53, 76, 109, 78, 118, 98, 84, 69, 107, 77, 67, 73, 71, 65, 49, 85, 69, 67, 104, 77, 98, 87, 70, 74, 104, 98, 88, 65, 103, 85, 50, 86, 106, 10, 100, 88, 74, 112, 100, 72, 107, 103, 85, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 103, 83, 87, 53, 106, 77, 83, 48, 119, 75, 119, 89, 68, 86, 81, 81, 68, 69, 121, 82, 89, 85, 109, 70, 116, 99, 67, 66, 72, 98, 71, 57, 105, 89, 87, 119, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 10, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 72, 104, 99, 78, 77, 68, 81, 120, 77, 84, 65, 120, 77, 84, 99, 120, 78, 68, 65, 48, 87, 104, 99, 78, 77, 122, 85, 119, 77, 84, 65, 120, 77, 68, 85, 122, 78, 122, 69, 53, 87, 106, 67, 66, 103, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 10, 72, 106, 65, 99, 66, 103, 78, 86, 66, 65, 115, 84, 70, 88, 100, 51, 100, 121, 53, 52, 99, 109, 70, 116, 99, 72, 78, 108, 89, 51, 86, 121, 97, 88, 82, 53, 76, 109, 78, 118, 98, 84, 69, 107, 77, 67, 73, 71, 65, 49, 85, 69, 67, 104, 77, 98, 87, 70, 74, 104, 98, 88, 65, 103, 85, 50, 86, 106, 100, 88, 74, 112, 100, 72, 107, 103, 10, 85, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 103, 83, 87, 53, 106, 77, 83, 48, 119, 75, 119, 89, 68, 86, 81, 81, 68, 69, 121, 82, 89, 85, 109, 70, 116, 99, 67, 66, 72, 98, 71, 57, 105, 89, 87, 119, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 10, 100, 72, 107, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 89, 74, 66, 54, 57, 70, 98, 83, 54, 51, 56, 101, 77, 112, 83, 101, 50, 79, 65, 116, 112, 56, 55, 90, 79, 113, 67, 119, 117, 10, 73, 82, 49, 99, 82, 78, 56, 104, 88, 88, 52, 106, 100, 80, 53, 101, 102, 114, 82, 75, 116, 54, 97, 116, 72, 54, 55, 103, 66, 104, 98, 105, 109, 49, 118, 90, 90, 51, 82, 114, 88, 89, 67, 80, 75, 90, 50, 71, 71, 57, 109, 99, 68, 90, 104, 116, 100, 104, 65, 111, 87, 79, 82, 108, 115, 72, 57, 75, 109, 72, 109, 102, 52, 77, 77, 120, 10, 102, 111, 65, 114, 116, 89, 122, 65, 81, 68, 115, 82, 104, 116, 68, 76, 111, 111, 89, 50, 89, 75, 84, 86, 77, 73, 74, 116, 50, 87, 55, 81, 68, 120, 73, 69, 77, 53, 100, 102, 84, 50, 70, 97, 56, 79, 84, 53, 107, 97, 118, 110, 72, 84, 117, 56, 54, 77, 47, 48, 97, 121, 48, 48, 102, 79, 74, 73, 89, 82, 121, 79, 56, 50, 70, 69, 10, 122, 71, 43, 103, 83, 113, 109, 85, 115, 69, 51, 97, 53, 54, 107, 48, 101, 110, 73, 52, 113, 69, 72, 77, 80, 74, 81, 82, 102, 101, 118, 73, 112, 111, 121, 51, 104, 115, 118, 75, 77, 122, 118, 90, 80, 84, 101, 76, 43, 51, 111, 43, 104, 105, 122, 110, 99, 57, 99, 75, 86, 54, 120, 107, 109, 120, 110, 114, 57, 65, 56, 69, 67, 73, 113, 115, 10, 65, 120, 99, 90, 90, 80, 82, 97, 74, 83, 75, 78, 78, 67, 121, 121, 57, 109, 103, 100, 69, 109, 51, 84, 105, 104, 52, 85, 50, 115, 83, 80, 112, 117, 73, 106, 104, 100, 86, 54, 68, 98, 49, 113, 52, 79, 110, 115, 55, 66, 101, 55, 81, 104, 116, 110, 113, 105, 88, 116, 82, 89, 77, 104, 47, 77, 72, 74, 102, 78, 86, 105, 80, 118, 114, 121, 10, 120, 83, 51, 84, 47, 100, 82, 108, 65, 103, 77, 66, 65, 65, 71, 106, 103, 90, 56, 119, 103, 90, 119, 119, 69, 119, 89, 74, 75, 119, 89, 66, 66, 65, 71, 67, 78, 120, 81, 67, 66, 65, 89, 101, 66, 65, 66, 68, 65, 69, 69, 119, 67, 119, 89, 68, 86, 82, 48, 80, 66, 65, 81, 68, 65, 103, 71, 71, 77, 65, 56, 71, 65, 49, 85, 100, 10, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 77, 90, 80, 111, 106, 48, 71, 89, 52, 81, 74, 110, 77, 53, 105, 53, 65, 83, 115, 106, 86, 121, 49, 54, 98, 89, 98, 77, 68, 89, 71, 65, 49, 85, 100, 72, 119, 81, 118, 77, 67, 48, 119, 75, 54, 65, 112, 10, 111, 67, 101, 71, 74, 87, 104, 48, 100, 72, 65, 54, 76, 121, 57, 106, 99, 109, 119, 117, 101, 72, 74, 104, 98, 88, 66, 122, 90, 87, 78, 49, 99, 109, 108, 48, 101, 83, 53, 106, 98, 50, 48, 118, 87, 69, 100, 68, 81, 83, 53, 106, 99, 109, 119, 119, 69, 65, 89, 74, 75, 119, 89, 66, 66, 65, 71, 67, 78, 120, 85, 66, 66, 65, 77, 67, 10, 65, 81, 69, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 74, 69, 86, 79, 81, 77, 66, 71, 50, 102, 55, 83, 104, 122, 53, 67, 109, 66, 98, 111, 100, 112, 78, 108, 50, 76, 53, 74, 70, 77, 110, 49, 52, 74, 107, 84, 112, 65, 117, 119, 48, 107, 98, 75, 53, 114, 99, 10, 47, 75, 104, 52, 90, 122, 88, 120, 72, 102, 65, 82, 118, 98, 100, 73, 52, 120, 68, 50, 68, 100, 56, 47, 48, 115, 109, 50, 113, 108, 87, 107, 83, 76, 111, 67, 50, 57, 53, 90, 76, 104, 86, 98, 79, 53, 48, 87, 102, 85, 102, 88, 78, 43, 112, 102, 84, 88, 89, 83, 78, 114, 115, 102, 49, 54, 71, 66, 66, 69, 89, 103, 111, 121, 120, 116, 10, 113, 90, 52, 66, 102, 106, 56, 112, 122, 103, 67, 84, 51, 47, 51, 74, 107, 110, 79, 74, 105, 87, 83, 101, 53, 121, 118, 107, 72, 74, 69, 115, 48, 114, 110, 79, 102, 99, 53, 118, 77, 90, 110, 84, 53, 114, 55, 83, 72, 112, 68, 119, 67, 82, 82, 53, 88, 67, 79, 114, 84, 100, 76, 97, 73, 82, 57, 78, 109, 88, 109, 100, 52, 99, 56, 110, 10, 110, 120, 67, 98, 72, 73, 103, 78, 115, 73, 112, 107, 81, 84, 71, 52, 68, 109, 121, 81, 74, 75, 83, 98, 88, 72, 71, 80, 117, 114, 116, 43, 72, 66, 118, 98, 97, 111, 65, 80, 73, 98, 122, 112, 50, 54, 97, 51, 81, 80, 83, 121, 105, 54, 109, 120, 53, 79, 43, 97, 71, 116, 65, 57, 97, 90, 110, 117, 113, 67, 105, 106, 52, 84, 121, 122, 10, 56, 76, 73, 82, 110, 77, 57, 56, 81, 79, 98, 100, 53, 48, 78, 57, 111, 116, 103, 54, 116, 97, 109, 78, 56, 106, 83, 90, 120, 78, 81, 81, 52, 81, 98, 57, 67, 89, 81, 81, 79, 43, 55, 69, 84, 80, 84, 115, 74, 51, 120, 67, 119, 110, 82, 56, 103, 111, 111, 74, 121, 98, 81, 68, 74, 98, 119, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 111, 32, 68, 97, 100, 100, 121, 32, 67, 108, 97, 115, 115, 32, 50, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 65, 68, 67, 67, 65, 117, 105, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 106, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 104, 77, 66, 56, 71, 65, 49, 85, 69, 67, 104, 77, 89, 10, 86, 71, 104, 108, 73, 69, 100, 118, 73, 69, 82, 104, 90, 71, 82, 53, 73, 69, 100, 121, 98, 51, 86, 119, 76, 67, 66, 74, 98, 109, 77, 117, 77, 84, 69, 119, 76, 119, 89, 68, 86, 81, 81, 76, 69, 121, 104, 72, 98, 121, 66, 69, 89, 87, 82, 107, 101, 83, 66, 68, 98, 71, 70, 122, 99, 121, 65, 121, 73, 69, 78, 108, 99, 110, 82, 112, 10, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 66, 52, 88, 68, 84, 65, 48, 77, 68, 89, 121, 79, 84, 69, 51, 77, 68, 89, 121, 77, 70, 111, 88, 68, 84, 77, 48, 77, 68, 89, 121, 79, 84, 69, 51, 77, 68, 89, 121, 77, 70, 111, 119, 89, 122, 69, 76, 77, 65, 107, 71, 10, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 73, 84, 65, 102, 66, 103, 78, 86, 66, 65, 111, 84, 71, 70, 82, 111, 90, 83, 66, 72, 98, 121, 66, 69, 89, 87, 82, 107, 101, 83, 66, 72, 99, 109, 57, 49, 99, 67, 119, 103, 83, 87, 53, 106, 76, 106, 69, 120, 77, 67, 56, 71, 65, 49, 85, 69, 67, 120, 77, 111, 82, 50, 56, 103, 10, 82, 71, 70, 107, 90, 72, 107, 103, 81, 50, 120, 104, 99, 51, 77, 103, 77, 105, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 84, 67, 67, 65, 83, 65, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 10, 103, 103, 69, 78, 65, 68, 67, 67, 65, 81, 103, 67, 103, 103, 69, 66, 65, 78, 54, 100, 49, 43, 112, 88, 71, 69, 109, 104, 87, 43, 118, 88, 88, 48, 105, 71, 54, 114, 55, 100, 47, 43, 84, 118, 90, 120, 122, 48, 90, 87, 105, 122, 86, 51, 71, 103, 88, 110, 101, 55, 55, 90, 116, 74, 54, 88, 67, 65, 80, 86, 89, 89, 89, 119, 104, 118, 10, 50, 118, 76, 77, 48, 68, 57, 47, 65, 108, 81, 105, 86, 66, 68, 89, 115, 111, 72, 85, 119, 72, 85, 57, 83, 51, 47, 72, 100, 56, 77, 43, 101, 75, 115, 97, 65, 55, 85, 103, 97, 121, 57, 113, 75, 55, 72, 70, 105, 72, 55, 69, 117, 120, 54, 119, 119, 100, 104, 70, 74, 50, 43, 113, 78, 49, 106, 51, 104, 121, 98, 88, 50, 67, 51, 50, 10, 113, 82, 101, 51, 72, 51, 73, 50, 84, 113, 89, 88, 80, 50, 87, 89, 107, 116, 115, 113, 98, 108, 50, 105, 47, 111, 106, 103, 67, 57, 53, 47, 53, 89, 48, 86, 52, 101, 118, 76, 79, 116, 88, 105, 69, 113, 73, 84, 76, 100, 105, 79, 114, 49, 56, 83, 80, 97, 65, 73, 66, 81, 105, 50, 88, 75, 86, 108, 79, 65, 82, 70, 109, 82, 54, 106, 10, 89, 71, 66, 48, 120, 85, 71, 108, 99, 109, 73, 98, 89, 115, 85, 102, 98, 49, 56, 97, 81, 114, 52, 67, 85, 87, 87, 111, 114, 105, 77, 89, 97, 118, 120, 52, 65, 54, 108, 78, 102, 52, 68, 68, 43, 113, 116, 97, 47, 75, 70, 65, 112, 77, 111, 90, 70, 118, 54, 121, 121, 79, 57, 101, 99, 119, 51, 117, 100, 55, 50, 97, 57, 110, 109, 89, 10, 118, 76, 69, 72, 90, 54, 73, 86, 68, 100, 50, 103, 87, 77, 90, 69, 101, 119, 111, 43, 89, 105, 104, 102, 117, 107, 69, 72, 85, 49, 106, 80, 69, 88, 52, 52, 100, 77, 88, 52, 47, 55, 86, 112, 107, 73, 43, 69, 100, 79, 113, 88, 71, 54, 56, 67, 65, 81, 79, 106, 103, 99, 65, 119, 103, 98, 48, 119, 72, 81, 89, 68, 86, 82, 48, 79, 10, 66, 66, 89, 69, 70, 78, 76, 69, 115, 78, 75, 82, 49, 69, 119, 82, 99, 98, 78, 104, 121, 122, 50, 104, 47, 116, 50, 111, 97, 116, 84, 106, 77, 73, 71, 78, 66, 103, 78, 86, 72, 83, 77, 69, 103, 89, 85, 119, 103, 89, 75, 65, 70, 78, 76, 69, 115, 78, 75, 82, 49, 69, 119, 82, 99, 98, 78, 104, 121, 122, 50, 104, 47, 116, 50, 111, 10, 97, 116, 84, 106, 111, 87, 101, 107, 90, 84, 66, 106, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 104, 77, 66, 56, 71, 65, 49, 85, 69, 67, 104, 77, 89, 86, 71, 104, 108, 73, 69, 100, 118, 73, 69, 82, 104, 90, 71, 82, 53, 73, 69, 100, 121, 98, 51, 86, 119, 76, 67, 66, 74, 98, 109, 77, 117, 10, 77, 84, 69, 119, 76, 119, 89, 68, 86, 81, 81, 76, 69, 121, 104, 72, 98, 121, 66, 69, 89, 87, 82, 107, 101, 83, 66, 68, 98, 71, 70, 122, 99, 121, 65, 121, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 103, 103, 69, 65, 77, 65, 119, 71, 10, 65, 49, 85, 100, 69, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 68, 74, 76, 56, 55, 76, 75, 80, 112, 72, 56, 69, 115, 97, 104, 66, 52, 121, 79, 100, 54, 65, 122, 66, 104, 82, 99, 107, 66, 52, 89, 57, 119, 105, 109, 10, 80, 81, 111, 90, 43, 89, 101, 65, 69, 87, 53, 112, 53, 74, 89, 88, 77, 80, 56, 48, 107, 87, 78, 121, 79, 79, 55, 77, 72, 65, 71, 106, 72, 90, 81, 111, 112, 68, 72, 50, 101, 115, 82, 85, 49, 47, 98, 108, 77, 86, 103, 68, 111, 115, 122, 79, 89, 116, 117, 85, 82, 88, 79, 49, 118, 48, 88, 74, 74, 76, 88, 86, 103, 103, 75, 116, 10, 73, 51, 108, 112, 106, 98, 105, 50, 84, 99, 55, 80, 84, 77, 111, 122, 73, 43, 103, 99, 105, 75, 113, 100, 105, 48, 70, 117, 70, 115, 107, 103, 53, 89, 109, 101, 122, 84, 118, 97, 99, 80, 100, 43, 109, 83, 89, 103, 70, 70, 81, 108, 113, 50, 53, 122, 104, 101, 97, 98, 73, 90, 48, 75, 98, 73, 73, 79, 113, 80, 106, 67, 68, 80, 111, 81, 10, 72, 109, 121, 87, 55, 52, 99, 78, 120, 65, 57, 104, 105, 54, 51, 117, 103, 121, 117, 86, 43, 73, 54, 83, 104, 72, 73, 53, 54, 121, 68, 113, 103, 43, 50, 68, 122, 90, 100, 117, 67, 76, 122, 114, 84, 105, 97, 50, 99, 121, 118, 107, 48, 47, 90, 77, 47, 105, 90, 120, 52, 109, 69, 82, 100, 69, 114, 47, 86, 120, 113, 72, 68, 51, 86, 73, 10, 76, 115, 57, 82, 97, 82, 101, 103, 65, 104, 74, 104, 108, 100, 88, 82, 81, 76, 73, 81, 84, 79, 55, 69, 114, 66, 66, 68, 112, 113, 87, 101, 67, 116, 87, 86, 89, 112, 111, 78, 122, 52, 105, 67, 120, 84, 73, 77, 53, 67, 117, 102, 82, 101, 89, 78, 110, 121, 105, 99, 115, 98, 107, 113, 87, 108, 101, 116, 78, 119, 43, 118, 72, 88, 47, 98, 10, 118, 90, 56, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 116, 97, 114, 102, 105, 101, 108, 100, 32, 67, 108, 97, 115, 115, 32, 50, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 68, 122, 67, 67, 65, 118, 101, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 111, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 108, 77, 67, 77, 71, 65, 49, 85, 69, 67, 104, 77, 99, 10, 85, 51, 82, 104, 99, 109, 90, 112, 90, 87, 120, 107, 73, 70, 82, 108, 89, 50, 104, 117, 98, 50, 120, 118, 90, 50, 108, 108, 99, 121, 119, 103, 83, 87, 53, 106, 76, 106, 69, 121, 77, 68, 65, 71, 65, 49, 85, 69, 67, 120, 77, 112, 85, 51, 82, 104, 99, 109, 90, 112, 90, 87, 120, 107, 73, 69, 78, 115, 89, 88, 78, 122, 73, 68, 73, 103, 10, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 72, 104, 99, 78, 77, 68, 81, 119, 78, 106, 73, 53, 77, 84, 99, 122, 79, 84, 69, 50, 87, 104, 99, 78, 77, 122, 81, 119, 78, 106, 73, 53, 77, 84, 99, 122, 79, 84, 69, 50, 87, 106, 66, 111, 10, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 108, 77, 67, 77, 71, 65, 49, 85, 69, 67, 104, 77, 99, 85, 51, 82, 104, 99, 109, 90, 112, 90, 87, 120, 107, 73, 70, 82, 108, 89, 50, 104, 117, 98, 50, 120, 118, 90, 50, 108, 108, 99, 121, 119, 103, 83, 87, 53, 106, 76, 106, 69, 121, 77, 68, 65, 71, 10, 65, 49, 85, 69, 67, 120, 77, 112, 85, 51, 82, 104, 99, 109, 90, 112, 90, 87, 120, 107, 73, 69, 78, 115, 89, 88, 78, 122, 73, 68, 73, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 103, 103, 69, 103, 77, 65, 48, 71, 67, 83, 113, 71, 10, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 81, 65, 119, 103, 103, 69, 73, 65, 111, 73, 66, 65, 81, 67, 51, 77, 115, 106, 43, 54, 88, 71, 109, 66, 73, 87, 116, 68, 66, 70, 107, 51, 56, 53, 78, 55, 56, 103, 68, 71, 73, 99, 47, 111, 97, 118, 55, 80, 75, 97, 102, 56, 77, 79, 104, 50, 116, 84, 89, 10, 98, 105, 116, 84, 107, 80, 115, 107, 112, 68, 54, 69, 56, 74, 55, 111, 88, 43, 122, 108, 74, 48, 84, 49, 75, 75, 89, 47, 101, 57, 55, 103, 75, 118, 68, 73, 114, 49, 77, 118, 110, 115, 111, 70, 65, 90, 77, 101, 106, 50, 89, 99, 79, 97, 100, 78, 43, 108, 113, 50, 99, 119, 81, 108, 90, 117, 116, 51, 102, 43, 100, 90, 120, 107, 113, 90, 10, 74, 82, 82, 85, 54, 121, 98, 72, 56, 51, 56, 90, 49, 84, 66, 119, 106, 54, 43, 119, 82, 105, 114, 47, 114, 101, 115, 112, 55, 100, 101, 102, 113, 103, 83, 72, 111, 57, 84, 53, 105, 97, 85, 48, 88, 57, 116, 68, 107, 89, 73, 50, 50, 87, 89, 56, 115, 98, 105, 53, 103, 118, 50, 99, 79, 106, 52, 81, 121, 68, 118, 118, 66, 109, 86, 109, 10, 101, 112, 115, 90, 71, 68, 51, 47, 99, 86, 69, 56, 77, 67, 53, 102, 118, 106, 49, 51, 99, 55, 74, 100, 66, 109, 122, 68, 73, 49, 97, 97, 75, 52, 85, 109, 107, 104, 121, 110, 65, 114, 80, 107, 80, 119, 50, 118, 67, 72, 109, 67, 117, 68, 89, 57, 54, 112, 122, 84, 78, 98, 79, 56, 97, 99, 114, 49, 122, 74, 51, 111, 47, 87, 83, 78, 10, 70, 52, 65, 122, 98, 108, 53, 75, 88, 90, 110, 74, 72, 111, 101, 48, 110, 82, 114, 65, 49, 87, 52, 84, 78, 83, 78, 101, 51, 53, 116, 102, 80, 101, 47, 87, 57, 51, 98, 67, 54, 106, 54, 55, 101, 65, 48, 99, 81, 109, 100, 114, 66, 78, 106, 52, 49, 116, 112, 118, 105, 47, 74, 69, 111, 65, 71, 114, 65, 103, 69, 68, 111, 52, 72, 70, 10, 77, 73, 72, 67, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 83, 47, 88, 55, 102, 82, 122, 116, 48, 102, 104, 118, 82, 98, 86, 97, 122, 99, 49, 120, 68, 67, 68, 113, 109, 73, 53, 122, 67, 66, 107, 103, 89, 68, 86, 82, 48, 106, 66, 73, 71, 75, 77, 73, 71, 72, 103, 66, 83, 47, 88, 55, 102, 82, 122, 116, 48, 102, 10, 104, 118, 82, 98, 86, 97, 122, 99, 49, 120, 68, 67, 68, 113, 109, 73, 53, 54, 70, 115, 112, 71, 111, 119, 97, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 111, 84, 72, 70, 78, 48, 89, 88, 74, 109, 97, 87, 86, 115, 90, 67, 66, 85, 90, 87, 78, 111, 10, 98, 109, 57, 115, 98, 50, 100, 112, 90, 88, 77, 115, 73, 69, 108, 117, 89, 121, 52, 120, 77, 106, 65, 119, 66, 103, 78, 86, 66, 65, 115, 84, 75, 86, 78, 48, 89, 88, 74, 109, 97, 87, 86, 115, 90, 67, 66, 68, 98, 71, 70, 122, 99, 121, 65, 121, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 10, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 103, 103, 69, 65, 77, 65, 119, 71, 65, 49, 85, 100, 69, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 65, 87, 100, 80, 52, 105, 100, 48, 99, 107, 97, 86, 97, 71, 115, 10, 97, 102, 80, 122, 87, 100, 113, 98, 65, 89, 99, 97, 84, 49, 101, 112, 111, 88, 107, 74, 75, 116, 118, 51, 76, 55, 73, 101, 122, 77, 100, 101, 97, 116, 105, 68, 104, 54, 71, 88, 55, 48, 107, 49, 80, 110, 99, 71, 81, 86, 104, 105, 118, 52, 53, 89, 117, 65, 112, 110, 80, 43, 121, 122, 51, 83, 70, 109, 72, 56, 108, 85, 43, 110, 76, 77, 10, 80, 85, 120, 65, 50, 73, 71, 118, 100, 53, 54, 68, 101, 114, 117, 105, 120, 47, 85, 48, 70, 52, 55, 90, 69, 85, 68, 48, 47, 67, 119, 113, 84, 82, 86, 47, 112, 50, 74, 100, 76, 105, 88, 84, 65, 65, 115, 103, 71, 104, 49, 111, 43, 82, 101, 52, 57, 76, 50, 76, 55, 83, 104, 90, 51, 85, 48, 87, 105, 120, 101, 68, 121, 76, 74, 108, 10, 120, 121, 49, 54, 112, 97, 113, 56, 85, 52, 90, 116, 51, 86, 101, 107, 121, 118, 103, 103, 81, 81, 116, 111, 56, 80, 84, 55, 100, 76, 53, 87, 88, 88, 112, 53, 57, 102, 107, 100, 104, 101, 77, 116, 108, 98, 55, 49, 99, 90, 66, 68, 122, 73, 48, 102, 109, 103, 65, 75, 104, 121, 110, 112, 86, 83, 74, 89, 65, 67, 80, 113, 52, 120, 74, 68, 10, 75, 86, 116, 72, 67, 78, 50, 77, 81, 87, 112, 108, 66, 113, 106, 108, 73, 97, 112, 66, 116, 74, 85, 104, 108, 98, 108, 57, 48, 84, 83, 114, 69, 57, 97, 116, 118, 78, 122, 105, 80, 84, 110, 78, 118, 84, 53, 49, 99, 75, 69, 89, 87, 81, 80, 74, 73, 114, 83, 80, 110, 78, 86, 101, 75, 116, 101, 108, 116, 116, 81, 75, 98, 102, 105, 51, 10, 81, 66, 70, 71, 109, 104, 57, 53, 68, 109, 75, 47, 68, 53, 102, 115, 52, 67, 56, 102, 70, 53, 81, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 116, 97, 114, 116, 67, 111, 109, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 72, 121, 84, 67, 67, 66, 98, 71, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 57, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 74, 84, 68, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 67, 104, 77, 78, 10, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 103, 84, 72, 82, 107, 76, 106, 69, 114, 77, 67, 107, 71, 65, 49, 85, 69, 67, 120, 77, 105, 85, 50, 86, 106, 100, 88, 74, 108, 73, 69, 82, 112, 90, 50, 108, 48, 89, 87, 119, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 85, 103, 85, 50, 108, 110, 98, 109, 108, 117, 10, 90, 122, 69, 112, 77, 67, 99, 71, 65, 49, 85, 69, 65, 120, 77, 103, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 72, 104, 99, 78, 77, 68, 89, 119, 79, 84, 69, 51, 77, 84, 107, 48, 10, 78, 106, 77, 50, 87, 104, 99, 78, 77, 122, 89, 119, 79, 84, 69, 51, 77, 84, 107, 48, 78, 106, 77, 50, 87, 106, 66, 57, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 74, 84, 68, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 67, 104, 77, 78, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 103, 84, 72, 82, 107, 10, 76, 106, 69, 114, 77, 67, 107, 71, 65, 49, 85, 69, 67, 120, 77, 105, 85, 50, 86, 106, 100, 88, 74, 108, 73, 69, 82, 112, 90, 50, 108, 48, 89, 87, 119, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 85, 103, 85, 50, 108, 110, 98, 109, 108, 117, 90, 122, 69, 112, 77, 67, 99, 71, 65, 49, 85, 69, 65, 120, 77, 103, 10, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 10, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 68, 66, 105, 78, 115, 74, 118, 71, 120, 71, 102, 72, 105, 102, 108, 88, 117, 49, 77, 53, 68, 121, 99, 109, 76, 87, 119, 84, 89, 103, 73, 105, 82, 101, 122, 117, 108, 51, 56, 107, 77, 75, 111, 103, 90, 107, 112, 77, 121, 79, 78, 118, 103, 52, 53, 105, 80, 119, 98, 109, 50, 120, 80, 78, 49, 121, 10, 111, 52, 85, 99, 111, 100, 77, 57, 116, 68, 77, 114, 48, 121, 43, 118, 47, 117, 113, 119, 81, 86, 108, 110, 116, 115, 81, 71, 102, 81, 113, 101, 100, 73, 88, 87, 101, 85, 121, 65, 78, 51, 114, 102, 79, 81, 86, 83, 87, 102, 102, 48, 71, 48, 90, 68, 112, 78, 75, 70, 104, 100, 76, 68, 99, 102, 78, 49, 89, 106, 83, 54, 76, 73, 112, 47, 10, 72, 111, 47, 117, 55, 84, 84, 81, 69, 99, 101, 87, 122, 86, 73, 57, 117, 106, 80, 87, 51, 85, 51, 101, 67, 122, 116, 75, 83, 53, 47, 67, 74, 105, 47, 54, 116, 82, 89, 99, 99, 106, 86, 51, 121, 106, 120, 100, 53, 115, 114, 104, 74, 111, 115, 97, 78, 110, 90, 99, 65, 100, 116, 48, 70, 67, 88, 43, 55, 98, 87, 103, 105, 65, 47, 100, 10, 101, 77, 111, 116, 72, 119, 101, 88, 77, 65, 69, 116, 99, 110, 110, 54, 82, 116, 89, 84, 75, 113, 105, 53, 112, 113, 117, 68, 83, 82, 51, 108, 56, 117, 47, 100, 53, 65, 71, 79, 71, 65, 113, 80, 89, 49, 77, 87, 104, 87, 75, 112, 68, 104, 107, 54, 122, 76, 86, 109, 112, 115, 74, 114, 100, 65, 102, 107, 75, 43, 70, 50, 80, 114, 82, 116, 10, 50, 80, 90, 69, 52, 88, 78, 105, 72, 122, 118, 69, 118, 113, 66, 84, 86, 105, 86, 115, 85, 81, 110, 51, 113, 113, 118, 75, 118, 51, 98, 57, 98, 90, 118, 122, 110, 100, 117, 47, 80, 87, 97, 56, 68, 70, 97, 113, 114, 53, 104, 73, 108, 84, 112, 76, 51, 54, 100, 89, 85, 78, 107, 52, 100, 97, 108, 98, 54, 107, 77, 77, 65, 118, 43, 90, 10, 54, 43, 104, 115, 84, 88, 66, 98, 75, 87, 87, 99, 51, 97, 112, 100, 122, 75, 56, 66, 77, 101, 119, 77, 54, 57, 75, 78, 54, 79, 113, 99, 101, 43, 90, 117, 57, 121, 100, 109, 68, 66, 112, 73, 49, 50, 53, 67, 52, 122, 47, 101, 73, 84, 53, 55, 52, 81, 49, 119, 43, 50, 79, 113, 113, 71, 119, 97, 86, 76, 82, 99, 74, 88, 114, 74, 10, 111, 115, 109, 76, 70, 113, 97, 55, 76, 72, 52, 88, 88, 103, 86, 78, 87, 71, 52, 83, 72, 81, 72, 117, 69, 104, 65, 78, 120, 106, 74, 47, 71, 80, 47, 56, 57, 80, 114, 78, 98, 112, 72, 111, 78, 107, 109, 43, 71, 107, 104, 112, 105, 56, 75, 87, 84, 82, 111, 83, 115, 109, 107, 88, 119, 81, 113, 81, 49, 118, 112, 53, 73, 107, 105, 47, 10, 117, 110, 116, 112, 43, 72, 68, 72, 43, 110, 111, 51, 50, 78, 103, 78, 48, 110, 90, 80, 86, 47, 43, 81, 116, 43, 79, 82, 48, 116, 51, 118, 119, 109, 67, 51, 90, 122, 114, 100, 47, 113, 113, 99, 56, 78, 83, 76, 102, 51, 73, 105, 122, 115, 97, 102, 108, 55, 98, 52, 114, 52, 113, 103, 69, 75, 106, 90, 43, 120, 106, 71, 116, 114, 86, 99, 10, 85, 106, 121, 74, 116, 104, 107, 113, 99, 119, 69, 75, 68, 119, 79, 122, 69, 109, 68, 121, 101, 105, 43, 66, 50, 54, 78, 117, 47, 121, 89, 119, 108, 47, 87, 76, 51, 89, 108, 88, 116, 113, 48, 57, 115, 54, 56, 114, 120, 98, 100, 50, 65, 118, 67, 108, 49, 105, 117, 97, 104, 104, 81, 113, 99, 118, 98, 106, 77, 52, 120, 100, 67, 85, 115, 84, 10, 51, 55, 117, 77, 100, 66, 78, 83, 83, 119, 73, 68, 65, 81, 65, 66, 111, 52, 73, 67, 85, 106, 67, 67, 65, 107, 52, 119, 68, 65, 89, 68, 86, 82, 48, 84, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 76, 66, 103, 78, 86, 72, 81, 56, 69, 66, 65, 77, 67, 65, 97, 52, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 10, 70, 69, 52, 76, 55, 120, 113, 107, 81, 70, 117, 108, 70, 50, 109, 72, 77, 77, 111, 48, 97, 69, 80, 81, 81, 97, 55, 121, 77, 71, 81, 71, 65, 49, 85, 100, 72, 119, 82, 100, 77, 70, 115, 119, 76, 75, 65, 113, 111, 67, 105, 71, 74, 109, 104, 48, 100, 72, 65, 54, 76, 121, 57, 106, 90, 88, 74, 48, 76, 110, 78, 48, 89, 88, 74, 48, 10, 89, 50, 57, 116, 76, 109, 57, 121, 90, 121, 57, 122, 90, 110, 78, 106, 89, 83, 49, 106, 99, 109, 119, 117, 89, 51, 74, 115, 77, 67, 117, 103, 75, 97, 65, 110, 104, 105, 86, 111, 100, 72, 82, 119, 79, 105, 56, 118, 89, 51, 74, 115, 76, 110, 78, 48, 89, 88, 74, 48, 89, 50, 57, 116, 76, 109, 57, 121, 90, 121, 57, 122, 90, 110, 78, 106, 10, 89, 83, 49, 106, 99, 109, 119, 117, 89, 51, 74, 115, 77, 73, 73, 66, 88, 81, 89, 68, 86, 82, 48, 103, 66, 73, 73, 66, 86, 68, 67, 67, 65, 86, 65, 119, 103, 103, 70, 77, 66, 103, 115, 114, 66, 103, 69, 69, 65, 89, 71, 49, 78, 119, 69, 66, 65, 84, 67, 67, 65, 84, 115, 119, 76, 119, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 10, 65, 103, 69, 87, 73, 50, 104, 48, 100, 72, 65, 54, 76, 121, 57, 106, 90, 88, 74, 48, 76, 110, 78, 48, 89, 88, 74, 48, 89, 50, 57, 116, 76, 109, 57, 121, 90, 121, 57, 119, 98, 50, 120, 112, 89, 51, 107, 117, 99, 71, 82, 109, 77, 68, 85, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 73, 66, 70, 105, 108, 111, 100, 72, 82, 119, 10, 79, 105, 56, 118, 89, 50, 86, 121, 100, 67, 53, 122, 100, 71, 70, 121, 100, 71, 78, 118, 98, 83, 53, 118, 99, 109, 99, 118, 97, 87, 53, 48, 90, 88, 74, 116, 90, 87, 82, 112, 89, 88, 82, 108, 76, 110, 66, 107, 90, 106, 67, 66, 48, 65, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 103, 73, 119, 103, 99, 77, 119, 74, 120, 89, 103, 10, 85, 51, 82, 104, 99, 110, 81, 103, 81, 50, 57, 116, 98, 87, 86, 121, 89, 50, 108, 104, 98, 67, 65, 111, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 112, 73, 69, 120, 48, 90, 67, 52, 119, 65, 119, 73, 66, 65, 82, 113, 66, 108, 48, 120, 112, 98, 87, 108, 48, 90, 87, 81, 103, 84, 71, 108, 104, 89, 109, 108, 115, 97, 88, 82, 53, 10, 76, 67, 66, 121, 90, 87, 70, 107, 73, 72, 82, 111, 90, 83, 66, 122, 90, 87, 78, 48, 97, 87, 57, 117, 73, 67, 112, 77, 90, 87, 100, 104, 98, 67, 66, 77, 97, 87, 49, 112, 100, 71, 70, 48, 97, 87, 57, 117, 99, 121, 111, 103, 98, 50, 89, 103, 100, 71, 104, 108, 73, 70, 78, 48, 89, 88, 74, 48, 81, 50, 57, 116, 73, 69, 78, 108, 10, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 73, 70, 66, 118, 98, 71, 108, 106, 101, 83, 66, 104, 100, 109, 70, 112, 98, 71, 70, 105, 98, 71, 85, 103, 89, 88, 81, 103, 97, 72, 82, 48, 99, 68, 111, 118, 76, 50, 78, 108, 99, 110, 81, 117, 99, 51, 82, 104, 10, 99, 110, 82, 106, 98, 50, 48, 117, 98, 51, 74, 110, 76, 51, 66, 118, 98, 71, 108, 106, 101, 83, 53, 119, 90, 71, 89, 119, 69, 81, 89, 74, 89, 73, 90, 73, 65, 89, 98, 52, 81, 103, 69, 66, 66, 65, 81, 68, 65, 103, 65, 72, 77, 68, 103, 71, 67, 87, 67, 71, 83, 65, 71, 71, 43, 69, 73, 66, 68, 81, 81, 114, 70, 105, 108, 84, 10, 100, 71, 70, 121, 100, 69, 78, 118, 98, 83, 66, 71, 99, 109, 86, 108, 73, 70, 78, 84, 84, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 10, 65, 103, 69, 65, 70, 109, 121, 90, 57, 71, 89, 77, 78, 80, 88, 81, 104, 86, 53, 57, 67, 117, 122, 97, 69, 69, 52, 52, 72, 70, 55, 102, 112, 105, 85, 70, 83, 53, 69, 121, 119, 101, 103, 55, 56, 84, 51, 100, 82, 65, 108, 98, 66, 48, 109, 75, 75, 99, 116, 109, 65, 114, 101, 120, 109, 118, 99, 108, 109, 65, 107, 56, 106, 104, 118, 104, 10, 51, 84, 97, 72, 75, 48, 117, 55, 97, 78, 77, 53, 90, 106, 50, 103, 74, 115, 102, 121, 79, 90, 69, 100, 85, 97, 117, 67, 101, 51, 55, 86, 122, 108, 114, 107, 52, 103, 78, 88, 99, 71, 109, 88, 67, 80, 108, 101, 87, 75, 89, 75, 51, 52, 119, 71, 109, 107, 85, 87, 70, 106, 103, 75, 88, 108, 102, 50, 89, 115, 100, 54, 65, 103, 88, 109, 10, 118, 66, 54, 49, 56, 112, 55, 48, 113, 83, 109, 68, 43, 76, 73, 85, 52, 50, 52, 111, 104, 48, 84, 68, 107, 66, 114, 101, 79, 75, 107, 56, 114, 69, 78, 78, 90, 69, 88, 79, 51, 83, 105, 112, 88, 80, 74, 122, 101, 119, 84, 52, 70, 43, 105, 114, 115, 102, 77, 117, 88, 71, 82, 117, 99, 122, 69, 54, 69, 114, 105, 56, 115, 120, 72, 107, 10, 102, 89, 43, 66, 85, 90, 111, 55, 106, 89, 110, 48, 84, 90, 78, 109, 101, 122, 119, 68, 55, 100, 79, 97, 72, 90, 114, 122, 90, 86, 68, 49, 111, 78, 66, 49, 110, 121, 43, 118, 56, 79, 113, 67, 81, 53, 106, 52, 97, 90, 121, 74, 101, 99, 82, 68, 106, 107, 90, 121, 52, 50, 81, 50, 69, 113, 47, 51, 74, 82, 52, 52, 105, 90, 66, 51, 10, 102, 115, 78, 114, 97, 114, 110, 68, 121, 48, 82, 76, 114, 72, 105, 81, 105, 43, 102, 72, 76, 66, 53, 76, 69, 85, 84, 73, 78, 70, 73, 110, 122, 81, 112, 100, 110, 52, 88, 66, 105, 100, 85, 97, 101, 80, 75, 86, 69, 70, 77, 121, 51, 89, 67, 69, 90, 110, 88, 90, 116, 87, 103, 111, 43, 50, 69, 117, 118, 111, 83, 111, 79, 77, 67, 90, 10, 69, 111, 97, 108, 72, 109, 100, 107, 114, 81, 89, 117, 76, 54, 108, 119, 104, 99, 101, 87, 68, 51, 121, 74, 90, 102, 87, 79, 81, 49, 81, 79, 113, 57, 50, 108, 103, 68, 109, 85, 89, 77, 65, 48, 121, 90, 90, 119, 76, 75, 77, 83, 57, 82, 57, 73, 101, 55, 48, 99, 102, 109, 117, 51, 110, 90, 68, 48, 73, 106, 117, 117, 43, 80, 119, 113, 10, 121, 118, 113, 67, 85, 113, 68, 118, 114, 48, 116, 86, 107, 43, 118, 66, 116, 102, 65, 105, 105, 54, 119, 48, 84, 105, 89, 105, 66, 75, 71, 72, 76, 72, 86, 75, 116, 43, 86, 57, 69, 57, 101, 52, 68, 71, 84, 65, 78, 116, 76, 74, 76, 52, 89, 83, 106, 67, 77, 74, 119, 82, 117, 67, 79, 51, 78, 74, 111, 50, 112, 88, 104, 53, 84, 108, 10, 49, 110, 106, 70, 109, 85, 78, 106, 52, 48, 51, 103, 100, 121, 51, 104, 90, 90, 108, 121, 97, 81, 81, 97, 82, 119, 110, 109, 68, 119, 70, 87, 74, 80, 115, 102, 118, 119, 53, 53, 113, 86, 103, 117, 117, 99, 81, 74, 65, 88, 54, 86, 117, 109, 48, 65, 66, 106, 54, 121, 54, 107, 111, 81, 79, 100, 106, 81, 75, 47, 87, 47, 55, 72, 87, 47, 10, 108, 119, 76, 70, 67, 82, 115, 73, 51, 70, 85, 51, 52, 111, 72, 55, 78, 52, 82, 68, 89, 105, 68, 75, 53, 49, 90, 76, 90, 101, 114, 43, 98, 77, 69, 107, 107, 121, 83, 104, 78, 79, 115, 70, 47, 53, 111, 105, 114, 112, 116, 57, 80, 47, 70, 108, 85, 81, 113, 109, 77, 71, 113, 122, 57, 73, 103, 99, 103, 65, 51, 56, 99, 111, 114, 111, 10, 103, 49, 52, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 84, 97, 105, 119, 97, 110, 32, 71, 82, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 99, 106, 67, 67, 65, 49, 113, 103, 65, 119, 73, 66, 65, 103, 73, 81, 72, 53, 49, 90, 87, 116, 99, 118, 119, 103, 90, 69, 112, 89, 65, 73, 97, 101, 78, 101, 57, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 65, 47, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 85, 86, 122, 69, 119, 77, 67, 52, 71, 65, 49, 85, 69, 67, 103, 119, 110, 82, 50, 57, 50, 90, 88, 74, 117, 98, 87, 86, 117, 100, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 66, 52, 88, 10, 68, 84, 65, 121, 77, 84, 73, 119, 78, 84, 69, 122, 77, 106, 77, 122, 77, 49, 111, 88, 68, 84, 77, 121, 77, 84, 73, 119, 78, 84, 69, 122, 77, 106, 77, 122, 77, 49, 111, 119, 80, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 70, 99, 120, 77, 68, 65, 117, 66, 103, 78, 86, 66, 65, 111, 77, 74, 48, 100, 118, 10, 100, 109, 86, 121, 98, 109, 49, 108, 98, 110, 81, 103, 85, 109, 57, 118, 100, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 84, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 10, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 74, 111, 108, 117, 79, 122, 77, 111, 110, 87, 111, 101, 47, 102, 79, 87, 49, 109, 75, 121, 100, 71, 71, 69, 103, 104, 85, 55, 74, 122, 121, 53, 48, 98, 50, 105, 80, 78, 56, 54, 97, 88, 102, 84, 69, 99, 50, 112, 66, 115, 66, 72, 72, 56, 101, 86, 52, 113, 78, 10, 119, 56, 88, 82, 73, 101, 80, 97, 74, 68, 57, 73, 75, 47, 117, 102, 76, 113, 71, 85, 53, 121, 119, 99, 107, 57, 71, 47, 71, 119, 71, 72, 85, 53, 110, 79, 112, 47, 85, 75, 73, 88, 90, 51, 47, 54, 109, 51, 120, 110, 79, 85, 84, 48, 98, 51, 69, 69, 107, 51, 43, 113, 104, 90, 83, 86, 49, 113, 103, 81, 100, 87, 56, 111, 114, 53, 10, 66, 116, 68, 51, 99, 67, 74, 78, 116, 76, 100, 66, 117, 84, 75, 52, 115, 102, 67, 120, 119, 53, 119, 47, 99, 80, 49, 84, 51, 89, 71, 113, 50, 71, 78, 52, 57, 116, 104, 84, 98, 113, 71, 115, 97, 111, 81, 107, 99, 108, 83, 71, 120, 116, 75, 121, 121, 104, 119, 79, 101, 89, 72, 87, 116, 88, 66, 105, 67, 65, 69, 117, 84, 107, 56, 79, 10, 49, 82, 71, 118, 113, 97, 47, 108, 109, 114, 47, 99, 122, 73, 100, 116, 74, 117, 84, 74, 86, 54, 76, 55, 108, 118, 110, 77, 52, 84, 57, 84, 106, 71, 120, 77, 102, 112, 116, 84, 67, 65, 116, 115, 70, 47, 116, 110, 121, 77, 75, 116, 115, 99, 50, 65, 116, 74, 102, 99, 100, 103, 69, 87, 70, 101, 108, 113, 49, 54, 84, 104, 101, 69, 102, 79, 10, 104, 116, 88, 55, 77, 102, 80, 54, 77, 98, 52, 48, 113, 105, 106, 55, 99, 69, 119, 100, 83, 99, 101, 118, 76, 74, 49, 116, 90, 113, 97, 50, 106, 87, 82, 43, 116, 83, 66, 113, 110, 84, 117, 66, 116, 111, 57, 65, 65, 71, 100, 76, 105, 89, 97, 52, 122, 71, 88, 43, 70, 86, 80, 112, 66, 77, 72, 87, 88, 120, 49, 69, 49, 119, 111, 118, 10, 74, 53, 112, 71, 102, 97, 69, 78, 100, 97, 49, 85, 104, 104, 88, 99, 83, 84, 118, 120, 108, 115, 52, 80, 109, 54, 68, 115, 111, 51, 112, 100, 118, 116, 85, 113, 100, 85, 76, 108, 101, 57, 54, 108, 116, 113, 113, 118, 75, 75, 121, 115, 107, 75, 119, 52, 116, 57, 86, 111, 78, 83, 90, 54, 51, 80, 99, 55, 56, 47, 49, 70, 109, 57, 71, 55, 10, 81, 51, 104, 117, 98, 47, 70, 67, 86, 71, 113, 89, 56, 65, 50, 116, 108, 43, 108, 83, 88, 117, 110, 86, 97, 110, 76, 101, 97, 118, 99, 98, 89, 66, 84, 48, 112, 101, 83, 50, 99, 87, 101, 113, 72, 43, 114, 105, 84, 99, 70, 67, 81, 80, 53, 110, 82, 104, 99, 52, 76, 48, 99, 47, 99, 90, 121, 117, 53, 83, 72, 75, 89, 83, 49, 116, 10, 66, 54, 105, 69, 102, 67, 51, 117, 85, 83, 88, 120, 89, 53, 67, 101, 47, 101, 70, 88, 105, 71, 118, 118, 105, 105, 78, 116, 115, 101, 97, 57, 80, 54, 51, 82, 80, 90, 89, 76, 104, 89, 51, 78, 97, 121, 101, 55, 116, 119, 87, 98, 55, 76, 117, 82, 113, 81, 111, 72, 69, 103, 75, 88, 84, 105, 67, 81, 56, 80, 56, 78, 72, 117, 74, 66, 10, 79, 57, 78, 65, 79, 117, 101, 78, 88, 100, 112, 109, 53, 65, 75, 119, 66, 49, 75, 89, 88, 65, 54, 79, 77, 53, 122, 67, 112, 112, 88, 55, 86, 82, 108, 117, 84, 73, 54, 117, 83, 119, 43, 57, 119, 84, 104, 78, 88, 111, 43, 69, 72, 87, 98, 78, 120, 87, 67, 87, 116, 70, 74, 97, 66, 89, 109, 79, 108, 88, 113, 89, 119, 90, 69, 56, 10, 108, 83, 79, 121, 68, 118, 82, 53, 116, 77, 108, 56, 119, 85, 111, 104, 65, 103, 77, 66, 65, 65, 71, 106, 97, 106, 66, 111, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 84, 77, 122, 79, 47, 77, 75, 87, 67, 107, 79, 55, 71, 83, 116, 106, 122, 54, 77, 109, 75, 80, 114, 67, 85, 86, 79, 122, 65, 77, 66, 103, 78, 86, 10, 72, 82, 77, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 68, 107, 71, 66, 71, 99, 113, 66, 119, 65, 69, 77, 84, 65, 118, 77, 67, 48, 67, 65, 81, 65, 119, 67, 81, 89, 70, 75, 119, 52, 68, 65, 104, 111, 70, 65, 68, 65, 72, 66, 103, 86, 110, 75, 103, 77, 65, 65, 65, 81, 85, 65, 53, 118, 119, 73, 104, 80, 47, 108, 83, 103, 50, 10, 48, 57, 121, 101, 119, 68, 76, 55, 77, 84, 113, 75, 85, 87, 85, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 73, 66, 65, 69, 67, 65, 83, 118, 111, 109, 121, 99, 53, 101, 77, 78, 49, 80, 104, 110, 82, 50, 87, 80, 87, 117, 115, 52, 77, 122, 101, 75, 82, 54, 100, 66, 99, 90, 10, 84, 117, 108, 83, 116, 98, 110, 103, 67, 110, 82, 105, 113, 109, 106, 75, 101, 75, 66, 77, 109, 111, 52, 115, 73, 121, 55, 86, 97, 104, 73, 107, 118, 57, 82, 111, 48, 52, 114, 81, 50, 74, 121, 102, 116, 66, 56, 77, 51, 106, 104, 43, 86, 122, 106, 56, 106, 101, 74, 80, 88, 103, 121, 102, 113, 122, 118, 83, 47, 51, 87, 88, 121, 54, 84, 106, 10, 90, 119, 106, 47, 53, 99, 65, 87, 116, 85, 103, 66, 102, 101, 110, 53, 67, 118, 56, 98, 53, 87, 112, 112, 118, 51, 103, 104, 113, 77, 75, 110, 73, 54, 109, 71, 113, 51, 90, 87, 54, 65, 52, 77, 57, 104, 80, 100, 75, 109, 97, 75, 90, 69, 107, 57, 71, 104, 105, 72, 107, 65, 83, 102, 81, 108, 75, 51, 84, 56, 118, 43, 82, 48, 70, 50, 10, 78, 101, 47, 47, 65, 72, 89, 50, 82, 84, 75, 98, 120, 107, 97, 70, 88, 101, 73, 107, 115, 66, 55, 106, 83, 74, 97, 89, 86, 48, 101, 85, 86, 88, 111, 80, 81, 98, 70, 69, 74, 80, 80, 66, 47, 104, 112, 114, 118, 52, 106, 57, 119, 97, 98, 97, 107, 50, 66, 101, 103, 85, 113, 90, 73, 74, 120, 73, 90, 104, 109, 49, 65, 72, 108, 85, 10, 68, 55, 103, 115, 76, 48, 117, 56, 113, 86, 49, 98, 89, 72, 43, 77, 104, 54, 88, 103, 85, 109, 77, 113, 118, 116, 103, 55, 104, 85, 65, 86, 47, 104, 54, 50, 90, 84, 47, 70, 83, 57, 112, 43, 116, 88, 111, 49, 75, 97, 77, 117, 101, 112, 104, 103, 73, 113, 80, 48, 102, 83, 100, 79, 76, 101, 113, 48, 100, 68, 122, 112, 68, 54, 81, 122, 10, 68, 120, 65, 82, 118, 66, 77, 66, 49, 117, 85, 79, 48, 55, 43, 49, 69, 113, 76, 104, 82, 83, 80, 65, 122, 65, 104, 117, 89, 98, 101, 74, 113, 52, 80, 106, 74, 66, 55, 109, 88, 81, 102, 110, 72, 121, 65, 43, 122, 50, 102, 73, 53, 54, 119, 119, 98, 83, 100, 76, 97, 71, 53, 76, 75, 108, 119, 67, 67, 68, 84, 98, 43, 72, 98, 107, 10, 90, 54, 77, 109, 110, 68, 43, 105, 77, 115, 74, 75, 120, 89, 69, 89, 77, 82, 66, 87, 113, 111, 84, 118, 76, 81, 114, 47, 117, 66, 57, 51, 48, 114, 43, 108, 87, 75, 66, 105, 53, 78, 100, 76, 107, 88, 87, 78, 105, 89, 67, 89, 102, 109, 51, 76, 85, 48, 53, 101, 114, 47, 97, 121, 108, 52, 87, 88, 117, 100, 112, 86, 66, 114, 107, 107, 10, 55, 116, 102, 71, 79, 66, 53, 106, 71, 120, 73, 55, 108, 101, 70, 89, 114, 80, 76, 102, 104, 78, 86, 102, 109, 83, 56, 78, 86, 86, 118, 109, 79, 78, 115, 117, 80, 51, 76, 112, 83, 73, 88, 76, 117, 121, 107, 84, 106, 120, 52, 52, 86, 98, 110, 122, 115, 115, 81, 119, 109, 83, 78, 79, 88, 102, 74, 73, 111, 82, 73, 77, 51, 66, 75, 81, 10, 67, 90, 66, 85, 107, 81, 77, 56, 82, 43, 88, 86, 121, 87, 88, 103, 116, 48, 116, 57, 55, 69, 102, 84, 115, 119, 115, 43, 114, 90, 55, 81, 100, 65, 65, 79, 54, 55, 49, 82, 114, 99, 68, 101, 76, 77, 68, 68, 97, 118, 55, 118, 51, 65, 117, 110, 43, 107, 98, 102, 89, 78, 117, 99, 112, 108, 108, 81, 100, 83, 78, 112, 99, 53, 79, 121, 10, 43, 102, 119, 67, 48, 48, 102, 109, 99, 99, 52, 81, 65, 117, 52, 110, 106, 73, 84, 47, 114, 69, 85, 78, 69, 49, 121, 68, 77, 117, 65, 108, 112, 89, 89, 115, 102, 80, 81, 83, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 119, 105, 115, 115, 99, 111, 109, 32, 82, 111, 111, 116, 32, 67, 65, 32, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 50, 84, 67, 67, 65, 56, 71, 103, 65, 119, 73, 66, 65, 103, 73, 81, 88, 65, 117, 70, 88, 65, 118, 110, 87, 85, 72, 102, 86, 56, 119, 47, 102, 53, 50, 111, 78, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 107, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 106, 97, 68, 69, 82, 77, 65, 56, 71, 65, 49, 85, 69, 67, 104, 77, 73, 85, 51, 100, 112, 99, 51, 78, 106, 98, 50, 48, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 115, 84, 72, 69, 82, 112, 90, 50, 108, 48, 89, 87, 119, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 85, 103, 85, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 77, 84, 69, 108, 78, 51, 97, 88, 78, 122, 89, 50, 57, 116, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 77, 84, 65, 101, 70, 119, 48, 119, 78, 84, 65, 52, 77, 84, 103, 120, 77, 106, 65, 50, 77, 106, 66, 97, 70, 119, 48, 121, 78, 84, 65, 52, 10, 77, 84, 103, 121, 77, 106, 65, 50, 77, 106, 66, 97, 77, 71, 81, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 109, 78, 111, 77, 82, 69, 119, 68, 119, 89, 68, 86, 81, 81, 75, 69, 119, 104, 84, 100, 50, 108, 122, 99, 50, 78, 118, 98, 84, 69, 108, 77, 67, 77, 71, 65, 49, 85, 69, 67, 120, 77, 99, 82, 71, 108, 110, 10, 97, 88, 82, 104, 98, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 83, 66, 84, 90, 88, 74, 50, 97, 87, 78, 108, 99, 122, 69, 98, 77, 66, 107, 71, 65, 49, 85, 69, 65, 120, 77, 83, 85, 51, 100, 112, 99, 51, 78, 106, 98, 50, 48, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 120, 77, 73, 73, 67, 10, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 103, 56, 65, 77, 73, 73, 67, 67, 103, 75, 67, 65, 103, 69, 65, 48, 76, 109, 119, 113, 65, 122, 90, 117, 122, 56, 104, 43, 66, 118, 86, 77, 53, 79, 65, 70, 109, 85, 103, 100, 98, 73, 57, 109, 50, 66, 116, 82, 115, 105, 77, 10, 77, 87, 56, 88, 119, 47, 113, 97, 98, 70, 98, 116, 80, 77, 87, 82, 86, 56, 80, 78, 113, 53, 90, 74, 107, 67, 111, 90, 83, 120, 54, 106, 98, 86, 102, 100, 56, 83, 116, 105, 75, 72, 86, 70, 88, 113, 114, 87, 87, 47, 111, 76, 74, 100, 105, 104, 70, 118, 107, 99, 120, 67, 55, 109, 108, 83, 112, 110, 122, 78, 65, 112, 98, 106, 121, 70, 10, 78, 68, 104, 104, 83, 98, 69, 65, 110, 57, 89, 54, 99, 86, 57, 78, 98, 99, 53, 102, 117, 97, 110, 107, 105, 88, 57, 113, 85, 118, 114, 75, 109, 47, 76, 99, 113, 102, 109, 100, 109, 85, 99, 47, 84, 105, 108, 102, 116, 75, 97, 78, 88, 88, 115, 76, 109, 82, 69, 68, 65, 47, 55, 110, 50, 57, 117, 106, 47, 120, 50, 108, 122, 90, 65, 101, 10, 65, 82, 56, 49, 115, 72, 56, 65, 50, 53, 66, 118, 120, 110, 53, 55, 48, 101, 53, 54, 101, 113, 101, 113, 68, 70, 100, 118, 112, 71, 51, 70, 69, 122, 117, 119, 112, 100, 110, 116, 77, 104, 121, 48, 88, 109, 101, 76, 86, 78, 120, 122, 104, 43, 88, 84, 70, 51, 120, 109, 85, 72, 74, 100, 49, 66, 112, 89, 119, 100, 110, 80, 50, 73, 107, 67, 10, 98, 54, 100, 74, 116, 68, 90, 100, 48, 75, 84, 101, 66, 121, 121, 50, 100, 98, 99, 111, 107, 100, 97, 88, 118, 105, 106, 49, 109, 66, 55, 113, 87, 121, 98, 74, 118, 98, 67, 88, 99, 57, 113, 117, 107, 83, 98, 114, 97, 77, 72, 53, 79, 82, 88, 87, 90, 48, 115, 75, 98, 85, 47, 76, 122, 55, 68, 107, 81, 110, 71, 77, 85, 51, 110, 110, 10, 55, 117, 72, 98, 72, 97, 66, 117, 72, 89, 119, 97, 100, 122, 86, 99, 70, 104, 52, 114, 85, 120, 56, 48, 105, 57, 70, 115, 47, 80, 74, 110, 66, 51, 114, 49, 114, 101, 51, 87, 109, 113, 117, 104, 115, 85, 118, 104, 122, 68, 100, 102, 47, 88, 47, 78, 84, 97, 54, 52, 72, 53, 120, 68, 43, 83, 112, 89, 86, 85, 78, 70, 118, 74, 98, 78, 10, 99, 65, 55, 56, 121, 101, 78, 109, 117, 107, 54, 78, 79, 52, 72, 76, 70, 87, 82, 55, 117, 90, 84, 111, 88, 84, 78, 83, 104, 88, 69, 117, 84, 52, 54, 105, 66, 104, 70, 82, 121, 101, 80, 76, 111, 87, 52, 120, 67, 71, 81, 77, 119, 116, 73, 56, 57, 84, 98, 111, 49, 57, 65, 79, 101, 67, 77, 103, 107, 99, 107, 107, 75, 109, 85, 112, 10, 87, 121, 76, 51, 73, 99, 54, 68, 88, 113, 84, 122, 51, 107, 118, 84, 97, 73, 57, 71, 100, 86, 121, 68, 67, 87, 52, 112, 97, 56, 82, 119, 106, 80, 87, 100, 49, 121, 65, 118, 47, 48, 98, 83, 75, 122, 106, 67, 76, 51, 85, 99, 80, 88, 55, 97, 112, 101, 56, 101, 89, 73, 86, 112, 81, 116, 80, 77, 43, 71, 80, 43, 72, 107, 77, 53, 10, 104, 97, 97, 50, 89, 48, 69, 81, 115, 51, 77, 101, 118, 78, 80, 54, 121, 110, 48, 87, 82, 43, 75, 110, 49, 100, 67, 106, 105, 103, 111, 73, 108, 109, 74, 87, 98, 106, 84, 98, 50, 81, 75, 53, 77, 72, 88, 106, 66, 78, 76, 110, 106, 56, 75, 119, 69, 85, 65, 75, 114, 78, 86, 120, 65, 109, 75, 76, 77, 98, 55, 100, 120, 105, 78, 89, 10, 77, 85, 74, 68, 76, 88, 84, 53, 120, 112, 54, 109, 105, 103, 47, 112, 47, 114, 43, 68, 53, 107, 78, 88, 74, 76, 114, 118, 82, 106, 83, 113, 49, 120, 73, 66, 79, 79, 48, 67, 65, 119, 69, 65, 65, 97, 79, 66, 104, 106, 67, 66, 103, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 89, 89, 119, 10, 72, 81, 89, 68, 86, 82, 48, 104, 66, 66, 89, 119, 70, 68, 65, 83, 66, 103, 100, 103, 104, 88, 81, 66, 85, 119, 65, 66, 66, 103, 100, 103, 104, 88, 81, 66, 85, 119, 65, 66, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 99, 119, 72, 119, 89, 68, 86, 82, 48, 106, 10, 66, 66, 103, 119, 70, 111, 65, 85, 65, 121, 85, 118, 51, 109, 43, 67, 65, 84, 112, 99, 76, 78, 119, 114, 111, 87, 109, 49, 90, 57, 83, 77, 48, 47, 48, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 65, 77, 108, 76, 57, 53, 118, 103, 103, 69, 54, 88, 67, 122, 99, 75, 54, 70, 112, 116, 87, 102, 85, 106, 78, 80, 57, 10, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 67, 65, 81, 65, 49, 69, 77, 118, 115, 112, 103, 81, 78, 68, 81, 47, 78, 119, 78, 117, 114, 113, 80, 75, 73, 108, 119, 122, 102, 107, 121, 57, 78, 102, 69, 66, 87, 77, 88, 114, 114, 112, 65, 57, 103, 122, 88, 114, 122, 118, 115, 77, 110, 10, 106, 103, 77, 43, 112, 78, 48, 83, 55, 51, 52, 101, 100, 65, 89, 56, 80, 122, 72, 121, 72, 72, 117, 82, 77, 83, 71, 48, 56, 78, 66, 115, 108, 57, 84, 112, 108, 55, 73, 107, 86, 104, 53, 87, 119, 122, 87, 57, 105, 65, 85, 80, 87, 120, 65, 97, 90, 79, 72, 72, 103, 106, 68, 53, 77, 113, 50, 101, 85, 67, 122, 110, 101, 65, 88, 81, 10, 77, 98, 70, 97, 109, 73, 112, 49, 84, 112, 66, 99, 97, 104, 81, 113, 52, 70, 74, 72, 103, 109, 68, 109, 72, 116, 113, 66, 115, 102, 115, 85, 67, 49, 114, 120, 110, 57, 75, 86, 117, 106, 55, 81, 71, 57, 89, 86, 72, 97, 79, 43, 104, 116, 88, 98, 68, 56, 66, 74, 90, 76, 115, 117, 85, 66, 108, 76, 48, 105, 84, 52, 51, 82, 52, 72, 10, 86, 116, 65, 52, 111, 74, 86, 119, 73, 72, 97, 77, 49, 57, 48, 101, 51, 112, 57, 120, 120, 67, 80, 118, 103, 120, 78, 99, 111, 121, 81, 86, 84, 83, 108, 65, 80, 71, 114, 69, 113, 100, 105, 51, 112, 107, 83, 108, 68, 102, 84, 103, 110, 88, 99, 101, 81, 72, 65, 109, 47, 78, 114, 90, 78, 117, 82, 53, 53, 76, 85, 47, 118, 74, 116, 108, 10, 118, 114, 115, 82, 108, 115, 47, 98, 120, 105, 103, 53, 79, 103, 106, 79, 82, 49, 116, 84, 87, 115, 87, 90, 47, 108, 50, 112, 51, 101, 57, 77, 49, 77, 97, 108, 114, 81, 76, 109, 106, 65, 99, 83, 72, 109, 56, 68, 48, 87, 43, 103, 111, 47, 77, 112, 118, 82, 76, 72, 85, 75, 75, 119, 102, 52, 105, 112, 109, 88, 101, 97, 115, 99, 67, 108, 10, 79, 83, 53, 99, 102, 71, 110, 105, 76, 76, 68, 113, 78, 50, 113, 107, 52, 86, 114, 104, 57, 86, 68, 108, 103, 43, 43, 108, 117, 121, 113, 73, 53, 52, 122, 98, 47, 87, 49, 101, 108, 120, 109, 111, 102, 109, 90, 49, 97, 51, 72, 113, 118, 55, 72, 72, 98, 54, 68, 48, 106, 113, 84, 115, 78, 70, 70, 98, 106, 67, 89, 68, 99, 75, 70, 51, 10, 49, 81, 69, 83, 86, 119, 65, 49, 50, 121, 80, 101, 68, 111, 111, 111, 109, 102, 50, 120, 69, 71, 57, 76, 47, 122, 103, 116, 89, 69, 52, 115, 110, 79, 116, 110, 116, 97, 49, 74, 55, 107, 115, 102, 114, 75, 47, 55, 68, 90, 66, 97, 90, 109, 66, 119, 88, 97, 114, 78, 101, 78, 81, 107, 55, 115, 104, 66, 111, 74, 77, 66, 107, 112, 120, 113, 10, 110, 118, 121, 53, 74, 77, 87, 122, 70, 89, 74, 43, 118, 113, 54, 86, 75, 43, 117, 120, 119, 78, 114, 106, 65, 87, 65, 76, 88, 109, 109, 115, 104, 70, 90, 104, 118, 110, 69, 88, 47, 104, 48, 84, 68, 47, 55, 71, 104, 48, 88, 112, 47, 106, 75, 103, 71, 103, 48, 84, 112, 74, 82, 86, 99, 97, 85, 87, 105, 55, 114, 75, 105, 98, 67, 121, 10, 120, 47, 121, 80, 50, 70, 83, 49, 107, 50, 75, 100, 122, 115, 57, 90, 43, 122, 48, 89, 122, 105, 114, 76, 78, 82, 87, 67, 88, 102, 57, 85, 73, 108, 116, 120, 85, 118, 117, 51, 121, 102, 53, 103, 109, 119, 66, 66, 90, 80, 67, 113, 75, 117, 121, 50, 81, 107, 80, 79, 105, 87, 97, 66, 121, 73, 117, 102, 79, 86, 81, 68, 74, 100, 77, 87, 10, 78, 89, 54, 69, 48, 70, 47, 54, 77, 66, 114, 49, 109, 109, 122, 48, 68, 108, 80, 53, 79, 108, 118, 82, 72, 65, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 105, 103, 105, 67, 101, 114, 116, 32, 65, 115, 115, 117, 114, 101, 100, 32, 73, 68, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 116, 122, 67, 67, 65, 112, 43, 103, 65, 119, 73, 66, 65, 103, 73, 81, 68, 79, 102, 103, 53, 82, 102, 89, 82, 118, 54, 80, 53, 87, 68, 56, 71, 47, 65, 119, 79, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 108, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 87, 53, 106, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 76, 69, 120, 66, 51, 100, 51, 99, 117, 90, 71, 108, 110, 97, 87, 78, 108, 99, 110, 81, 117, 89, 50, 57, 116, 77, 83, 81, 119, 10, 73, 103, 89, 68, 86, 81, 81, 68, 69, 120, 116, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 66, 99, 51, 78, 49, 99, 109, 86, 107, 73, 69, 108, 69, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 119, 72, 104, 99, 78, 77, 68, 89, 120, 77, 84, 69, 119, 77, 68, 65, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 122, 69, 120, 10, 77, 84, 69, 119, 77, 68, 65, 119, 77, 68, 65, 119, 87, 106, 66, 108, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 87, 53, 106, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 76, 10, 69, 120, 66, 51, 100, 51, 99, 117, 90, 71, 108, 110, 97, 87, 78, 108, 99, 110, 81, 117, 89, 50, 57, 116, 77, 83, 81, 119, 73, 103, 89, 68, 86, 81, 81, 68, 69, 120, 116, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 66, 99, 51, 78, 49, 99, 109, 86, 107, 73, 69, 108, 69, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 119, 10, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 116, 68, 104, 88, 79, 53, 69, 79, 65, 88, 76, 71, 72, 56, 55, 100, 103, 43, 88, 69, 83, 112, 97, 55, 99, 74, 112, 83, 73, 113, 118, 84, 79, 10, 57, 83, 65, 53, 75, 70, 104, 103, 68, 80, 105, 65, 50, 113, 107, 86, 108, 84, 74, 104, 80, 76, 87, 120, 75, 73, 83, 75, 105, 116, 121, 102, 67, 103, 121, 68, 70, 51, 113, 80, 107, 75, 121, 75, 53, 51, 108, 84, 88, 68, 71, 69, 75, 118, 89, 80, 109, 68, 73, 50, 100, 115, 122, 101, 51, 84, 121, 111, 111, 117, 57, 113, 43, 121, 72, 121, 10, 85, 109, 72, 102, 110, 121, 68, 88, 72, 43, 75, 120, 50, 102, 52, 89, 90, 78, 73, 83, 87, 49, 47, 53, 87, 66, 103, 49, 118, 69, 102, 78, 111, 84, 98, 53, 97, 51, 47, 85, 115, 68, 103, 43, 119, 82, 118, 68, 106, 68, 80, 90, 50, 67, 56, 89, 47, 105, 103, 80, 115, 54, 101, 68, 49, 115, 78, 117, 82, 77, 66, 104, 78, 90, 89, 87, 10, 47, 108, 109, 99, 105, 51, 90, 116, 49, 47, 71, 105, 83, 119, 48, 114, 47, 119, 116, 121, 50, 112, 53, 103, 48, 73, 54, 81, 78, 99, 90, 52, 86, 89, 99, 103, 111, 99, 47, 108, 98, 81, 114, 73, 83, 88, 119, 120, 109, 68, 78, 115, 73, 117, 109, 72, 48, 68, 74, 97, 111, 114, 111, 84, 103, 104, 72, 116, 79, 82, 101, 100, 109, 84, 112, 121, 10, 111, 101, 98, 54, 112, 78, 110, 86, 70, 122, 70, 49, 114, 111, 86, 57, 73, 113, 52, 47, 65, 85, 97, 71, 57, 105, 104, 53, 121, 76, 72, 97, 53, 70, 99, 88, 120, 72, 52, 99, 68, 114, 67, 48, 107, 113, 90, 87, 115, 55, 50, 121, 108, 43, 50, 113, 112, 47, 67, 51, 120, 97, 103, 47, 108, 82, 98, 81, 47, 54, 71, 87, 54, 119, 104, 102, 10, 71, 72, 100, 80, 65, 103, 77, 66, 65, 65, 71, 106, 89, 122, 66, 104, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 104, 106, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 70, 10, 54, 54, 75, 118, 57, 74, 76, 76, 103, 106, 69, 116, 85, 89, 117, 110, 112, 121, 71, 100, 56, 50, 51, 73, 68, 122, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 82, 70, 54, 54, 75, 118, 57, 74, 76, 76, 103, 106, 69, 116, 85, 89, 117, 110, 112, 121, 71, 100, 56, 50, 51, 73, 68, 122, 65, 78, 66, 103, 107, 113, 10, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 111, 103, 54, 56, 51, 43, 76, 116, 56, 79, 78, 121, 99, 51, 112, 107, 108, 76, 47, 51, 99, 109, 98, 89, 77, 117, 82, 67, 100, 87, 75, 117, 104, 43, 118, 121, 49, 100, 110, 101, 86, 114, 79, 102, 122, 77, 52, 85, 75, 76, 107, 78, 108, 50, 66, 99, 10, 69, 107, 120, 89, 53, 78, 77, 57, 103, 48, 108, 70, 87, 74, 99, 49, 97, 82, 113, 111, 82, 43, 112, 87, 120, 110, 109, 114, 69, 116, 104, 110, 103, 89, 84, 102, 102, 119, 107, 56, 108, 79, 97, 52, 74, 105, 119, 103, 118, 84, 50, 122, 75, 73, 110, 51, 88, 47, 56, 105, 52, 112, 101, 69, 72, 43, 108, 108, 55, 52, 102, 103, 51, 56, 70, 110, 10, 83, 98, 78, 100, 54, 55, 73, 74, 75, 117, 115, 109, 55, 88, 105, 43, 102, 84, 56, 114, 56, 55, 99, 109, 78, 87, 49, 102, 105, 81, 71, 50, 83, 86, 117, 102, 65, 81, 87, 98, 113, 122, 48, 108, 119, 99, 121, 50, 102, 56, 76, 120, 98, 52, 98, 71, 43, 109, 82, 111, 54, 52, 69, 116, 108, 79, 116, 67, 116, 47, 113, 77, 72, 116, 49, 105, 10, 56, 98, 53, 81, 90, 55, 100, 115, 118, 102, 80, 120, 72, 50, 115, 77, 78, 103, 99, 87, 102, 122, 100, 56, 113, 86, 116, 116, 101, 118, 69, 83, 82, 109, 67, 68, 49, 121, 99, 69, 118, 107, 118, 79, 108, 55, 55, 68, 90, 121, 112, 111, 69, 100, 43, 65, 53, 119, 119, 122, 90, 114, 56, 84, 68, 82, 82, 117, 56, 51, 56, 102, 89, 120, 65, 101, 10, 43, 111, 48, 98, 74, 87, 49, 115, 106, 54, 87, 51, 89, 81, 71, 120, 48, 113, 77, 109, 111, 82, 66, 120, 110, 97, 51, 105, 119, 47, 110, 68, 109, 86, 71, 51, 75, 119, 99, 73, 122, 105, 55, 109, 85, 76, 75, 110, 43, 103, 112, 70, 76, 54, 76, 119, 56, 103, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 105, 103, 105, 67, 101, 114, 116, 32, 71, 108, 111, 98, 97, 108, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 114, 122, 67, 67, 65, 112, 101, 103, 65, 119, 73, 66, 65, 103, 73, 81, 67, 68, 118, 103, 86, 112, 66, 67, 82, 114, 71, 104, 100, 87, 114, 74, 87, 90, 72, 72, 83, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 104, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 87, 53, 106, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 76, 69, 120, 66, 51, 100, 51, 99, 117, 90, 71, 108, 110, 97, 87, 78, 108, 99, 110, 81, 117, 89, 50, 57, 116, 77, 83, 65, 119, 10, 72, 103, 89, 68, 86, 81, 81, 68, 69, 120, 100, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 72, 98, 71, 57, 105, 89, 87, 119, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 84, 65, 101, 70, 119, 48, 119, 78, 106, 69, 120, 77, 84, 65, 119, 77, 68, 65, 119, 77, 68, 66, 97, 70, 119, 48, 122, 77, 84, 69, 120, 77, 84, 65, 119, 10, 77, 68, 65, 119, 77, 68, 66, 97, 77, 71, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 85, 119, 69, 119, 89, 68, 86, 81, 81, 75, 69, 119, 120, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 74, 98, 109, 77, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 115, 84, 69, 72, 100, 51, 10, 100, 121, 53, 107, 97, 87, 100, 112, 89, 50, 86, 121, 100, 67, 53, 106, 98, 50, 48, 120, 73, 68, 65, 101, 66, 103, 78, 86, 66, 65, 77, 84, 70, 48, 82, 112, 90, 50, 108, 68, 90, 88, 74, 48, 73, 69, 100, 115, 98, 50, 74, 104, 98, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 10, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 52, 106, 118, 104, 69, 88, 76, 101, 113, 75, 84, 84, 111, 49, 101, 113, 85, 75, 75, 80, 67, 51, 101, 81, 121, 97, 75, 108, 55, 104, 76, 79, 108, 108, 115, 66, 67, 83, 68, 77, 65, 90, 79, 110, 10, 84, 106, 67, 51, 85, 47, 100, 68, 120, 71, 107, 65, 86, 53, 51, 105, 106, 83, 76, 100, 104, 119, 90, 65, 65, 73, 69, 74, 122, 115, 52, 98, 103, 55, 47, 102, 122, 84, 116, 120, 82, 117, 76, 87, 90, 115, 99, 70, 115, 51, 89, 110, 70, 111, 57, 55, 110, 104, 54, 86, 102, 101, 54, 51, 83, 75, 77, 73, 50, 116, 97, 118, 101, 103, 119, 53, 10, 66, 109, 86, 47, 83, 108, 48, 102, 118, 66, 102, 52, 113, 55, 55, 117, 75, 78, 100, 48, 102, 51, 112, 52, 109, 86, 109, 70, 97, 71, 53, 99, 73, 122, 74, 76, 118, 48, 55, 65, 54, 70, 112, 116, 52, 51, 67, 47, 100, 120, 67, 47, 47, 65, 72, 50, 104, 100, 109, 111, 82, 66, 66, 89, 77, 113, 108, 49, 71, 78, 88, 82, 111, 114, 53, 72, 10, 52, 105, 100, 113, 57, 74, 111, 122, 43, 69, 107, 73, 89, 73, 118, 85, 88, 55, 81, 54, 104, 76, 43, 104, 113, 107, 112, 77, 102, 84, 55, 80, 84, 49, 57, 115, 100, 108, 54, 103, 83, 122, 101, 82, 110, 116, 119, 105, 53, 109, 51, 79, 70, 66, 113, 79, 97, 115, 118, 43, 122, 98, 77, 85, 90, 66, 102, 72, 87, 121, 109, 101, 77, 114, 47, 121, 10, 55, 118, 114, 84, 67, 48, 76, 85, 113, 55, 100, 66, 77, 116, 111, 77, 49, 79, 47, 52, 103, 100, 87, 55, 106, 86, 103, 47, 116, 82, 118, 111, 83, 83, 105, 105, 99, 78, 111, 120, 66, 78, 51, 51, 115, 104, 98, 121, 84, 65, 112, 79, 66, 54, 106, 116, 83, 106, 49, 101, 116, 88, 43, 106, 107, 77, 79, 118, 74, 119, 73, 68, 65, 81, 65, 66, 10, 111, 50, 77, 119, 89, 84, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 89, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 65, 57, 53, 81, 78, 86, 98, 82, 84, 76, 116, 109, 10, 56, 75, 80, 105, 71, 120, 118, 68, 108, 55, 73, 57, 48, 86, 85, 119, 72, 119, 89, 68, 86, 82, 48, 106, 66, 66, 103, 119, 70, 111, 65, 85, 65, 57, 53, 81, 78, 86, 98, 82, 84, 76, 116, 109, 56, 75, 80, 105, 71, 120, 118, 68, 108, 55, 73, 57, 48, 86, 85, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 10, 66, 81, 65, 68, 103, 103, 69, 66, 65, 77, 117, 99, 78, 54, 112, 73, 69, 120, 73, 75, 43, 116, 49, 69, 110, 69, 57, 83, 115, 80, 84, 102, 114, 103, 84, 49, 101, 88, 107, 73, 111, 121, 81, 89, 47, 69, 115, 114, 104, 77, 65, 116, 117, 100, 88, 72, 47, 118, 84, 66, 72, 49, 106, 76, 117, 71, 50, 99, 101, 110, 84, 110, 109, 67, 109, 114, 10, 69, 98, 88, 106, 99, 75, 67, 104, 122, 85, 121, 73, 109, 90, 79, 77, 107, 88, 68, 105, 113, 119, 56, 99, 118, 112, 79, 112, 47, 50, 80, 86, 53, 65, 100, 103, 48, 54, 79, 47, 110, 86, 115, 74, 56, 100, 87, 79, 52, 49, 80, 48, 106, 109, 80, 54, 80, 54, 102, 98, 116, 71, 98, 102, 89, 109, 98, 87, 48, 87, 53, 66, 106, 102, 73, 116, 10, 116, 101, 112, 51, 83, 112, 43, 100, 87, 79, 73, 114, 87, 99, 66, 65, 73, 43, 48, 116, 75, 73, 74, 70, 80, 110, 108, 85, 107, 105, 97, 89, 52, 73, 66, 73, 113, 68, 102, 118, 56, 78, 90, 53, 89, 66, 98, 101, 114, 79, 103, 79, 122, 87, 54, 115, 82, 66, 99, 52, 76, 48, 110, 97, 52, 85, 85, 43, 75, 114, 107, 50, 85, 56, 56, 54, 10, 85, 65, 98, 51, 76, 117, 106, 69, 86, 48, 108, 115, 89, 83, 69, 89, 49, 81, 83, 116, 101, 68, 119, 115, 79, 111, 66, 114, 112, 43, 117, 118, 70, 82, 84, 112, 50, 73, 110, 66, 117, 84, 104, 115, 52, 112, 70, 115, 105, 118, 57, 107, 117, 88, 99, 108, 86, 122, 68, 65, 71, 121, 83, 106, 52, 100, 122, 112, 51, 48, 100, 56, 116, 98, 81, 107, 10, 67, 65, 85, 119, 55, 67, 50, 57, 67, 55, 57, 70, 118, 49, 67, 53, 113, 102, 80, 114, 109, 65, 69, 83, 114, 99, 105, 73, 120, 112, 103, 48, 88, 52, 48, 75, 80, 77, 98, 112, 49, 90, 87, 86, 98, 100, 52, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 105, 103, 105, 67, 101, 114, 116, 32, 72, 105, 103, 104, 32, 65, 115, 115, 117, 114, 97, 110, 99, 101, 32, 69, 86, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 120, 84, 67, 67, 65, 113, 50, 103, 65, 119, 73, 66, 65, 103, 73, 81, 65, 113, 120, 99, 74, 109, 111, 76, 81, 74, 117, 80, 67, 51, 110, 121, 114, 107, 89, 108, 100, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 115, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 87, 53, 106, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 76, 69, 120, 66, 51, 100, 51, 99, 117, 90, 71, 108, 110, 97, 87, 78, 108, 99, 110, 81, 117, 89, 50, 57, 116, 77, 83, 115, 119, 10, 75, 81, 89, 68, 86, 81, 81, 68, 69, 121, 74, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 73, 97, 87, 100, 111, 73, 69, 70, 122, 99, 51, 86, 121, 89, 87, 53, 106, 90, 83, 66, 70, 86, 105, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 66, 52, 88, 68, 84, 65, 50, 77, 84, 69, 120, 77, 68, 65, 119, 77, 68, 65, 119, 10, 77, 70, 111, 88, 68, 84, 77, 120, 77, 84, 69, 120, 77, 68, 65, 119, 77, 68, 65, 119, 77, 70, 111, 119, 98, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 84, 65, 84, 66, 103, 78, 86, 66, 65, 111, 84, 68, 69, 82, 112, 90, 50, 108, 68, 90, 88, 74, 48, 73, 69, 108, 117, 89, 122, 69, 90, 10, 77, 66, 99, 71, 65, 49, 85, 69, 67, 120, 77, 81, 100, 51, 100, 51, 76, 109, 82, 112, 90, 50, 108, 106, 90, 88, 74, 48, 76, 109, 78, 118, 98, 84, 69, 114, 77, 67, 107, 71, 65, 49, 85, 69, 65, 120, 77, 105, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 71, 108, 110, 97, 67, 66, 66, 99, 51, 78, 49, 99, 109, 70, 117, 10, 89, 50, 85, 103, 82, 86, 89, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 84, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 77, 98, 77, 53, 88, 80, 109, 43, 57, 83, 55, 53, 83, 48, 116, 10, 77, 113, 98, 102, 53, 89, 69, 47, 121, 99, 48, 108, 83, 98, 90, 120, 75, 115, 80, 86, 108, 68, 82, 110, 111, 103, 111, 99, 115, 70, 57, 112, 112, 107, 67, 120, 120, 76, 101, 121, 106, 57, 67, 89, 112, 75, 108, 66, 87, 84, 114, 84, 51, 74, 84, 87, 80, 78, 116, 48, 79, 75, 82, 75, 122, 69, 48, 108, 103, 118, 100, 75, 112, 86, 77, 83, 10, 79, 79, 55, 122, 83, 87, 49, 120, 107, 88, 53, 106, 116, 113, 117, 109, 88, 56, 79, 107, 104, 80, 104, 80, 89, 108, 71, 43, 43, 77, 88, 115, 50, 122, 105, 83, 52, 119, 98, 108, 67, 74, 69, 77, 120, 67, 104, 66, 86, 102, 118, 76, 87, 111, 107, 86, 102, 110, 72, 111, 78, 98, 57, 78, 99, 103, 107, 57, 118, 106, 111, 52, 85, 70, 116, 51, 10, 77, 82, 117, 78, 115, 56, 99, 107, 82, 90, 113, 110, 114, 71, 48, 65, 70, 70, 111, 69, 116, 55, 111, 84, 54, 49, 69, 75, 109, 69, 70, 66, 73, 107, 53, 108, 89, 89, 101, 66, 81, 86, 67, 109, 101, 86, 121, 74, 51, 104, 108, 75, 86, 57, 85, 117, 53, 108, 48, 99, 85, 121, 120, 43, 109, 77, 48, 97, 66, 104, 97, 107, 97, 72, 80, 81, 10, 78, 65, 81, 84, 88, 75, 70, 120, 48, 49, 112, 56, 86, 100, 116, 101, 90, 79, 69, 51, 104, 122, 66, 87, 66, 79, 85, 82, 116, 67, 109, 65, 69, 118, 70, 53, 79, 89, 105, 105, 65, 104, 70, 56, 74, 50, 97, 51, 105, 76, 100, 52, 56, 115, 111, 75, 113, 68, 105, 114, 67, 109, 84, 67, 118, 50, 90, 100, 108, 89, 84, 66, 111, 83, 85, 101, 10, 104, 49, 48, 97, 85, 65, 115, 103, 69, 115, 120, 66, 117, 50, 52, 76, 85, 84, 105, 52, 83, 56, 115, 67, 65, 119, 69, 65, 65, 97, 78, 106, 77, 71, 69, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 71, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 10, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 76, 69, 43, 119, 50, 107, 68, 43, 76, 57, 72, 65, 100, 83, 89, 74, 104, 111, 73, 65, 117, 57, 106, 90, 67, 118, 68, 77, 66, 56, 71, 65, 49, 85, 100, 73, 119, 81, 89, 77, 66, 97, 65, 70, 76, 69, 43, 119, 50, 107, 68, 43, 76, 57, 72, 65, 100, 83, 89, 10, 74, 104, 111, 73, 65, 117, 57, 106, 90, 67, 118, 68, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 66, 65, 81, 65, 99, 71, 103, 97, 88, 51, 78, 101, 99, 110, 122, 121, 73, 90, 103, 89, 73, 86, 121, 72, 98, 73, 85, 102, 52, 75, 109, 101, 113, 118, 120, 103, 121, 100, 107, 65, 81, 10, 86, 56, 71, 75, 56, 51, 114, 90, 69, 87, 87, 79, 78, 102, 113, 101, 47, 69, 87, 49, 110, 116, 108, 77, 77, 85, 117, 52, 107, 101, 104, 68, 76, 73, 54, 122, 101, 77, 55, 98, 52, 49, 78, 53, 99, 100, 98, 108, 73, 90, 81, 66, 50, 108, 87, 72, 109, 105, 82, 107, 57, 111, 112, 109, 122, 78, 54, 99, 78, 56, 50, 111, 78, 76, 70, 112, 10, 109, 121, 80, 73, 110, 110, 103, 105, 75, 51, 66, 68, 52, 49, 86, 72, 77, 87, 69, 90, 55, 49, 106, 70, 104, 83, 57, 79, 77, 80, 97, 103, 77, 82, 89, 106, 121, 79, 102, 105, 90, 82, 89, 122, 121, 55, 56, 97, 71, 54, 65, 57, 43, 77, 112, 101, 105, 122, 71, 76, 89, 65, 105, 74, 76, 81, 119, 71, 88, 70, 75, 51, 120, 80, 107, 75, 10, 109, 78, 69, 86, 88, 53, 56, 83, 118, 110, 119, 50, 89, 122, 105, 57, 82, 75, 82, 47, 53, 67, 89, 114, 67, 115, 83, 88, 97, 81, 51, 112, 106, 79, 76, 65, 69, 70, 101, 52, 121, 72, 89, 83, 107, 86, 88, 121, 83, 71, 110, 89, 118, 67, 111, 67, 87, 119, 57, 69, 49, 67, 65, 120, 50, 47, 83, 54, 99, 67, 90, 100, 107, 71, 67, 101, 10, 118, 69, 115, 88, 67, 83, 43, 48, 121, 120, 53, 68, 97, 77, 107, 72, 74, 56, 72, 83, 88, 80, 102, 113, 73, 98, 108, 111, 69, 112, 119, 56, 110, 76, 43, 101, 47, 73, 66, 99, 109, 50, 80, 78, 55, 69, 101, 113, 74, 83, 100, 110, 111, 68, 102, 122, 65, 73, 74, 57, 86, 78, 101, 112, 43, 79, 107, 117, 69, 54, 78, 51, 54, 66, 57, 75, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 101, 114, 116, 112, 108, 117, 115, 32, 67, 108, 97, 115, 115, 32, 50, 32, 80, 114, 105, 109, 97, 114, 121, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 107, 106, 67, 67, 65, 110, 113, 103, 65, 119, 73, 66, 65, 103, 73, 82, 65, 73, 87, 57, 83, 47, 80, 89, 50, 117, 78, 112, 57, 112, 84, 88, 88, 56, 79, 108, 82, 67, 77, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 80, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 82, 108, 73, 120, 69, 84, 65, 80, 66, 103, 78, 86, 66, 65, 111, 84, 67, 69, 78, 108, 99, 110, 82, 119, 98, 72, 86, 122, 77, 82, 115, 119, 71, 81, 89, 68, 86, 81, 81, 68, 69, 120, 74, 68, 98, 71, 70, 122, 99, 121, 65, 121, 73, 70, 66, 121, 97, 87, 49, 104, 99, 110, 107, 103, 81, 48, 69, 119, 72, 104, 99, 78, 10, 79, 84, 107, 119, 78, 122, 65, 51, 77, 84, 99, 119, 78, 84, 65, 119, 87, 104, 99, 78, 77, 84, 107, 119, 78, 122, 65, 50, 77, 106, 77, 49, 79, 84, 85, 53, 87, 106, 65, 57, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 71, 85, 106, 69, 82, 77, 65, 56, 71, 65, 49, 85, 69, 67, 104, 77, 73, 81, 50, 86, 121, 10, 100, 72, 66, 115, 100, 88, 77, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 77, 84, 69, 107, 78, 115, 89, 88, 78, 122, 73, 68, 73, 103, 85, 72, 74, 112, 98, 87, 70, 121, 101, 83, 66, 68, 81, 84, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 10, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 78, 120, 81, 108, 116, 65, 83, 43, 68, 88, 83, 67, 72, 104, 54, 116, 108, 74, 119, 47, 87, 47, 117, 122, 55, 107, 82, 121, 49, 49, 51, 52, 101, 122, 112, 102, 103, 83, 78, 49, 115, 120, 118, 99, 48, 78, 88, 89, 75, 119, 122, 67, 107, 84, 115, 65, 49, 56, 99, 103, 67, 83, 82, 10, 53, 97, 105, 82, 86, 104, 75, 67, 57, 43, 65, 114, 57, 78, 117, 117, 89, 83, 54, 74, 69, 73, 49, 114, 98, 76, 113, 122, 65, 114, 51, 86, 78, 115, 86, 73, 78, 121, 80, 105, 56, 70, 111, 51, 85, 106, 77, 88, 69, 117, 76, 82, 89, 69, 50, 43, 76, 48, 69, 82, 52, 47, 89, 88, 74, 81, 121, 76, 107, 99, 65, 98, 109, 88, 117, 90, 10, 86, 103, 50, 118, 55, 116, 75, 56, 82, 49, 102, 106, 101, 85, 108, 55, 78, 73, 107, 110, 74, 73, 84, 101, 115, 101, 122, 112, 87, 69, 55, 43, 84, 116, 57, 97, 118, 107, 71, 116, 114, 65, 106, 70, 71, 65, 55, 118, 48, 108, 80, 117, 98, 78, 67, 100, 69, 103, 69, 84, 106, 100, 121, 65, 89, 118, 101, 86, 113, 85, 83, 73, 83, 110, 70, 79, 10, 89, 70, 87, 101, 50, 121, 77, 90, 101, 86, 89, 72, 68, 68, 57, 106, 67, 49, 121, 119, 52, 114, 53, 43, 70, 102, 121, 85, 77, 49, 104, 66, 79, 72, 84, 69, 52, 89, 43, 76, 51, 121, 97, 115, 72, 55, 87, 76, 79, 55, 100, 68, 87, 87, 117, 119, 74, 75, 90, 116, 107, 73, 118, 69, 99, 117, 112, 100, 77, 53, 105, 51, 121, 57, 53, 101, 10, 101, 43, 43, 85, 56, 82, 115, 43, 121, 115, 107, 104, 119, 99, 87, 89, 65, 113, 113, 105, 57, 108, 116, 51, 109, 47, 86, 43, 108, 108, 85, 48, 72, 71, 100, 112, 119, 80, 70, 67, 52, 48, 101, 115, 47, 67, 103, 99, 90, 108, 85, 67, 65, 119, 69, 65, 65, 97, 79, 66, 106, 68, 67, 66, 105, 84, 65, 80, 66, 103, 78, 86, 72, 82, 77, 69, 10, 67, 68, 65, 71, 65, 81, 72, 47, 65, 103, 69, 75, 77, 65, 115, 71, 65, 49, 85, 100, 68, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 52, 51, 77, 116, 51, 56, 115, 79, 75, 65, 122, 101, 51, 98, 79, 107, 121, 110, 109, 52, 106, 114, 118, 111, 77, 73, 107, 119, 69, 81, 89, 74, 10, 89, 73, 90, 73, 65, 89, 98, 52, 81, 103, 69, 66, 66, 65, 81, 68, 65, 103, 69, 71, 77, 68, 99, 71, 65, 49, 85, 100, 72, 119, 81, 119, 77, 67, 52, 119, 76, 75, 65, 113, 111, 67, 105, 71, 74, 109, 104, 48, 100, 72, 65, 54, 76, 121, 57, 51, 100, 51, 99, 117, 89, 50, 86, 121, 100, 72, 66, 115, 100, 88, 77, 117, 89, 50, 57, 116, 10, 76, 48, 78, 83, 84, 67, 57, 106, 98, 71, 70, 122, 99, 122, 73, 117, 89, 51, 74, 115, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 66, 65, 81, 67, 110, 86, 77, 43, 73, 82, 66, 110, 76, 51, 57, 82, 47, 65, 78, 57, 87, 77, 50, 75, 49, 57, 49, 69, 66, 107, 79, 118, 68, 10, 80, 57, 71, 73, 82, 79, 107, 107, 88, 101, 47, 110, 70, 76, 48, 103, 116, 53, 111, 56, 65, 80, 53, 116, 110, 57, 117, 81, 51, 78, 102, 48, 89, 116, 97, 76, 99, 70, 51, 110, 53, 81, 82, 73, 113, 87, 104, 56, 121, 102, 70, 67, 56, 50, 120, 47, 120, 88, 112, 56, 72, 86, 71, 73, 117, 116, 73, 75, 80, 105, 100, 100, 51, 105, 49, 82, 10, 84, 116, 77, 84, 90, 71, 110, 107, 76, 117, 80, 84, 53, 53, 115, 74, 109, 97, 98, 103, 108, 90, 118, 79, 71, 116, 100, 47, 118, 106, 122, 79, 85, 114, 77, 82, 70, 99, 69, 80, 70, 56, 48, 68, 117, 53, 119, 108, 70, 98, 113, 105, 100, 111, 110, 56, 66, 118, 69, 89, 48, 74, 78, 76, 68, 110, 121, 67, 116, 54, 88, 48, 57, 108, 47, 43, 10, 55, 85, 67, 109, 110, 89, 82, 48, 79, 98, 110, 99, 72, 111, 85, 87, 50, 105, 107, 98, 104, 105, 77, 65, 121, 98, 117, 74, 102, 109, 54, 65, 105, 66, 52, 118, 70, 76, 81, 68, 74, 75, 103, 121, 98, 119, 79, 97, 82, 121, 119, 119, 118, 108, 98, 71, 112, 48, 73, 67, 99, 66, 118, 113, 81, 78, 105, 54, 66, 81, 78, 119, 66, 54, 83, 87, 10, 47, 47, 49, 73, 77, 119, 114, 104, 51, 75, 87, 66, 107, 74, 116, 78, 51, 88, 51, 110, 53, 55, 76, 78, 88, 77, 104, 113, 108, 102, 105, 108, 57, 111, 51, 69, 88, 88, 103, 73, 118, 110, 115, 71, 49, 107, 110, 80, 71, 84, 90, 81, 73, 121, 52, 73, 53, 112, 52, 70, 84, 85, 99, 89, 49, 82, 98, 112, 115, 100, 97, 50, 69, 78, 87, 55, 10, 108, 55, 43, 105, 106, 114, 82, 85, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 83, 84, 32, 82, 111, 111, 116, 32, 67, 65, 32, 88, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 83, 106, 67, 67, 65, 106, 75, 103, 65, 119, 73, 66, 65, 103, 73, 81, 82, 75, 43, 119, 103, 78, 97, 106, 74, 55, 113, 74, 77, 68, 109, 71, 76, 118, 104, 65, 97, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 65, 47, 77, 83, 81, 119, 73, 103, 89, 68, 86, 81, 81, 75, 10, 69, 120, 116, 69, 97, 87, 100, 112, 100, 71, 70, 115, 73, 70, 78, 112, 90, 50, 53, 104, 100, 72, 86, 121, 90, 83, 66, 85, 99, 110, 86, 122, 100, 67, 66, 68, 98, 121, 52, 120, 70, 122, 65, 86, 66, 103, 78, 86, 66, 65, 77, 84, 68, 107, 82, 84, 86, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 70, 103, 122, 77, 66, 52, 88, 10, 68, 84, 65, 119, 77, 68, 107, 122, 77, 68, 73, 120, 77, 84, 73, 120, 79, 86, 111, 88, 68, 84, 73, 120, 77, 68, 107, 122, 77, 68, 69, 48, 77, 68, 69, 120, 78, 86, 111, 119, 80, 122, 69, 107, 77, 67, 73, 71, 65, 49, 85, 69, 67, 104, 77, 98, 82, 71, 108, 110, 97, 88, 82, 104, 98, 67, 66, 84, 97, 87, 100, 117, 89, 88, 82, 49, 10, 99, 109, 85, 103, 86, 72, 74, 49, 99, 51, 81, 103, 81, 50, 56, 117, 77, 82, 99, 119, 70, 81, 89, 68, 86, 81, 81, 68, 69, 119, 53, 69, 85, 49, 81, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 66, 89, 77, 122, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 10, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 78, 43, 118, 54, 90, 100, 81, 67, 73, 78, 88, 116, 77, 120, 105, 90, 102, 97, 81, 103, 117, 122, 72, 48, 121, 120, 114, 77, 77, 112, 98, 55, 78, 110, 68, 102, 99, 100, 65, 119, 82, 103, 85, 105, 43, 68, 111, 77, 51, 90, 74, 75, 117, 77, 47, 73, 85, 109, 84, 10, 114, 69, 52, 79, 114, 122, 53, 73, 121, 50, 88, 117, 47, 78, 77, 104, 68, 50, 88, 83, 75, 116, 107, 121, 106, 52, 122, 108, 57, 51, 101, 119, 69, 110, 117, 49, 108, 99, 67, 74, 111, 54, 109, 54, 55, 88, 77, 117, 101, 103, 119, 71, 77, 111, 79, 105, 102, 111, 111, 85, 77, 77, 48, 82, 111, 79, 69, 113, 79, 76, 108, 53, 67, 106, 72, 57, 10, 85, 76, 50, 65, 90, 100, 43, 51, 85, 87, 79, 68, 121, 79, 75, 73, 89, 101, 112, 76, 89, 89, 72, 115, 85, 109, 117, 53, 111, 117, 74, 76, 71, 105, 105, 102, 83, 75, 79, 101, 68, 78, 111, 74, 106, 106, 52, 88, 76, 104, 55, 100, 73, 78, 57, 98, 120, 105, 113, 75, 113, 121, 54, 57, 99, 75, 51, 70, 67, 120, 111, 108, 107, 72, 82, 121, 10, 120, 88, 116, 113, 113, 122, 84, 87, 77, 73, 110, 47, 53, 87, 103, 84, 101, 49, 81, 76, 121, 78, 97, 117, 55, 70, 113, 99, 107, 104, 52, 57, 90, 76, 79, 77, 120, 116, 43, 47, 121, 85, 70, 119, 55, 66, 90, 121, 49, 83, 98, 115, 79, 70, 85, 53, 81, 57, 68, 56, 47, 82, 104, 99, 81, 80, 71, 88, 54, 57, 87, 97, 109, 52, 48, 100, 10, 117, 116, 111, 108, 117, 99, 98, 89, 51, 56, 69, 86, 65, 106, 113, 114, 50, 109, 55, 120, 80, 105, 55, 49, 88, 65, 105, 99, 80, 78, 97, 68, 97, 101, 81, 81, 109, 120, 107, 113, 116, 105, 108, 88, 52, 43, 85, 57, 109, 53, 47, 119, 65, 108, 48, 67, 65, 119, 69, 65, 65, 97, 78, 67, 77, 69, 65, 119, 68, 119, 89, 68, 86, 82, 48, 84, 10, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 77, 83, 110, 115, 97, 82, 55, 76, 72, 72, 54, 50, 43, 70, 76, 107, 72, 88, 47, 120, 66, 86, 103, 104, 89, 107, 81, 10, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 66, 65, 81, 67, 106, 71, 105, 121, 98, 70, 119, 66, 99, 113, 82, 55, 117, 75, 71, 89, 51, 79, 114, 43, 68, 120, 122, 57, 76, 119, 119, 109, 103, 108, 83, 66, 100, 52, 57, 108, 90, 82, 78, 73, 43, 68, 84, 54, 57, 105, 107, 117, 103, 10, 100, 66, 47, 79, 69, 73, 75, 99, 100, 66, 111, 100, 102, 112, 103, 97, 51, 99, 115, 84, 83, 55, 77, 103, 82, 79, 83, 82, 54, 99, 122, 56, 102, 97, 88, 98, 97, 117, 88, 43, 53, 118, 51, 103, 84, 116, 50, 51, 65, 68, 113, 49, 99, 69, 109, 118, 56, 117, 88, 114, 65, 118, 72, 82, 65, 111, 115, 90, 121, 53, 81, 54, 88, 107, 106, 69, 10, 71, 66, 53, 89, 71, 86, 56, 101, 65, 108, 114, 119, 68, 80, 71, 120, 114, 97, 110, 99, 87, 89, 97, 76, 98, 117, 109, 82, 57, 89, 98, 75, 43, 114, 108, 109, 77, 54, 112, 90, 87, 56, 55, 105, 112, 120, 90, 122, 82, 56, 115, 114, 122, 74, 109, 119, 78, 48, 106, 80, 52, 49, 90, 76, 57, 99, 56, 80, 68, 72, 73, 121, 104, 56, 98, 119, 10, 82, 76, 116, 84, 99, 109, 49, 68, 57, 83, 90, 73, 109, 108, 74, 110, 116, 49, 105, 114, 47, 109, 100, 50, 99, 88, 106, 98, 68, 97, 74, 87, 70, 66, 77, 53, 74, 68, 71, 70, 111, 113, 103, 67, 87, 106, 66, 72, 52, 100, 49, 81, 66, 55, 119, 67, 67, 90, 65, 65, 54, 50, 82, 106, 89, 74, 115, 87, 118, 73, 106, 74, 69, 117, 98, 83, 10, 102, 90, 71, 76, 43, 84, 48, 121, 106, 87, 87, 48, 54, 88, 121, 120, 86, 51, 98, 113, 120, 98, 89, 111, 79, 98, 56, 86, 90, 82, 122, 73, 57, 110, 101, 87, 97, 103, 113, 78, 100, 119, 118, 89, 107, 81, 115, 69, 106, 103, 102, 98, 75, 98, 89, 75, 55, 112, 50, 67, 78, 84, 85, 81, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 83, 84, 32, 65, 67, 69, 83, 32, 67, 65, 32, 88, 54, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 67, 84, 67, 67, 65, 118, 71, 103, 65, 119, 73, 66, 65, 103, 73, 81, 68, 86, 54, 90, 67, 116, 97, 100, 116, 51, 106, 115, 50, 65, 100, 87, 79, 52, 89, 86, 50, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 98, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 103, 77, 66, 52, 71, 65, 49, 85, 69, 67, 104, 77, 88, 82, 71, 108, 110, 97, 88, 82, 104, 98, 67, 66, 84, 97, 87, 100, 117, 89, 88, 82, 49, 99, 109, 85, 103, 86, 72, 74, 49, 99, 51, 81, 120, 69, 84, 65, 80, 66, 103, 78, 86, 66, 65, 115, 84, 67, 69, 82, 84, 86, 67, 66, 66, 81, 48, 86, 84, 10, 77, 82, 99, 119, 70, 81, 89, 68, 86, 81, 81, 68, 69, 119, 53, 69, 85, 49, 81, 103, 81, 85, 78, 70, 85, 121, 66, 68, 81, 83, 66, 89, 78, 106, 65, 101, 70, 119, 48, 119, 77, 122, 69, 120, 77, 106, 65, 121, 77, 84, 69, 53, 78, 84, 104, 97, 70, 119, 48, 120, 78, 122, 69, 120, 77, 106, 65, 121, 77, 84, 69, 53, 78, 84, 104, 97, 10, 77, 70, 115, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 83, 65, 119, 72, 103, 89, 68, 86, 81, 81, 75, 69, 120, 100, 69, 97, 87, 100, 112, 100, 71, 70, 115, 73, 70, 78, 112, 90, 50, 53, 104, 100, 72, 86, 121, 90, 83, 66, 85, 99, 110, 86, 122, 100, 68, 69, 82, 77, 65, 56, 71, 65, 49, 85, 69, 10, 67, 120, 77, 73, 82, 70, 78, 85, 73, 69, 70, 68, 82, 86, 77, 120, 70, 122, 65, 86, 66, 103, 78, 86, 66, 65, 77, 84, 68, 107, 82, 84, 86, 67, 66, 66, 81, 48, 86, 84, 73, 69, 78, 66, 73, 70, 103, 50, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 10, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 117, 84, 51, 49, 76, 77, 109, 85, 51, 72, 87, 75, 108, 86, 49, 106, 54, 73, 82, 51, 100, 109, 97, 53, 87, 90, 70, 99, 82, 116, 50, 83, 80, 112, 47, 53, 68, 103, 79, 48, 80, 87, 71, 83, 118, 83, 77, 109, 116, 87, 80, 117, 107, 116, 75, 101, 49, 106, 122, 73, 10, 68, 90, 66, 102, 90, 73, 71, 120, 113, 65, 103, 78, 84, 78, 106, 53, 48, 119, 85, 111, 85, 114, 81, 66, 74, 99, 87, 86, 72, 65, 120, 43, 80, 104, 67, 69, 100, 99, 47, 66, 71, 90, 70, 106, 122, 43, 105, 111, 107, 89, 105, 53, 81, 49, 75, 55, 103, 76, 70, 86, 105, 89, 115, 120, 43, 116, 67, 51, 100, 114, 53, 66, 80, 84, 67, 97, 10, 112, 67, 73, 108, 70, 51, 80, 111, 72, 117, 76, 84, 114, 67, 113, 57, 87, 122, 103, 104, 49, 83, 112, 76, 49, 49, 86, 57, 52, 122, 112, 86, 118, 100, 100, 116, 97, 119, 74, 88, 97, 43, 90, 72, 102, 65, 106, 73, 103, 114, 114, 101, 112, 52, 99, 57, 111, 87, 50, 52, 77, 70, 98, 67, 115, 119, 75, 66, 88, 121, 51, 49, 52, 112, 111, 119, 10, 71, 67, 105, 52, 90, 116, 80, 76, 65, 90, 90, 118, 54, 111, 112, 70, 86, 100, 98, 103, 110, 102, 57, 110, 75, 120, 99, 67, 112, 107, 52, 97, 97, 104, 69, 76, 102, 114, 100, 55, 53, 53, 106, 87, 106, 72, 90, 118, 119, 84, 118, 98, 85, 74, 78, 43, 53, 100, 67, 79, 72, 122, 101, 52, 118, 98, 114, 71, 110, 50, 122, 112, 102, 68, 80, 121, 10, 77, 106, 119, 109, 82, 47, 111, 110, 74, 65, 76, 74, 102, 104, 49, 98, 105, 69, 73, 84, 97, 106, 86, 56, 102, 84, 88, 112, 76, 109, 97, 82, 99, 112, 80, 86, 77, 105, 98, 69, 100, 80, 86, 84, 111, 55, 78, 100, 109, 118, 89, 74, 121, 119, 73, 68, 65, 81, 65, 66, 111, 52, 72, 73, 77, 73, 72, 70, 77, 65, 56, 71, 65, 49, 85, 100, 10, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 72, 71, 77, 66, 56, 71, 65, 49, 85, 100, 69, 81, 81, 89, 77, 66, 97, 66, 70, 72, 66, 114, 97, 83, 49, 118, 99, 72, 78, 65, 100, 72, 74, 49, 99, 51, 82, 107, 99, 51, 81, 117, 10, 89, 50, 57, 116, 77, 71, 73, 71, 65, 49, 85, 100, 73, 65, 82, 98, 77, 70, 107, 119, 86, 119, 89, 75, 89, 73, 90, 73, 65, 87, 85, 68, 65, 103, 69, 66, 65, 84, 66, 74, 77, 69, 99, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 73, 66, 70, 106, 116, 111, 100, 72, 82, 119, 79, 105, 56, 118, 100, 51, 100, 51, 76, 110, 82, 121, 10, 100, 88, 78, 48, 90, 72, 78, 48, 76, 109, 78, 118, 98, 83, 57, 106, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 88, 77, 118, 99, 71, 57, 115, 97, 87, 78, 53, 76, 48, 70, 68, 82, 86, 77, 116, 97, 87, 53, 107, 90, 88, 103, 117, 97, 72, 82, 116, 98, 68, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 10, 67, 88, 73, 71, 84, 104, 104, 68, 68, 43, 88, 87, 122, 77, 78, 113, 105, 122, 70, 55, 101, 73, 43, 111, 103, 55, 103, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 75, 80, 89, 106, 116, 97, 121, 50, 56, 52, 70, 53, 122, 76, 78, 65, 100, 77, 69, 65, 43, 86, 50, 10, 53, 70, 89, 114, 110, 74, 109, 81, 54, 65, 103, 119, 98, 78, 57, 57, 80, 101, 55, 108, 118, 55, 85, 107, 81, 73, 82, 74, 52, 100, 69, 111, 114, 115, 84, 67, 79, 108, 77, 119, 105, 80, 72, 49, 100, 50, 53, 82, 121, 118, 114, 47, 109, 97, 56, 107, 88, 120, 117, 103, 47, 102, 75, 115, 104, 77, 114, 102, 113, 102, 66, 102, 66, 67, 54, 116, 10, 70, 114, 56, 104, 108, 120, 67, 66, 80, 101, 80, 47, 104, 52, 48, 121, 51, 74, 84, 108, 82, 52, 112, 101, 97, 104, 80, 74, 108, 74, 85, 57, 48, 117, 55, 73, 78, 74, 88, 81, 103, 78, 83, 116, 77, 103, 105, 65, 86, 68, 122, 103, 118, 86, 74, 84, 49, 49, 74, 56, 115, 109, 107, 47, 102, 51, 114, 80, 97, 110, 84, 75, 43, 103, 81, 113, 10, 110, 69, 120, 97, 66, 113, 88, 112, 73, 75, 49, 70, 90, 103, 57, 112, 56, 100, 50, 47, 54, 101, 77, 121, 105, 47, 114, 103, 119, 89, 90, 78, 99, 106, 119, 117, 50, 74, 78, 52, 67, 105, 114, 52, 50, 78, 73, 110, 80, 82, 109, 74, 88, 49, 112, 55, 105, 106, 118, 77, 68, 78, 112, 82, 114, 115, 99, 76, 57, 121, 117, 119, 78, 119, 88, 115, 10, 118, 70, 99, 106, 52, 106, 106, 83, 109, 50, 106, 122, 86, 104, 75, 73, 84, 48, 74, 56, 117, 68, 72, 69, 116, 100, 118, 107, 121, 67, 69, 48, 54, 85, 103, 82, 78, 101, 55, 54, 120, 53, 74, 88, 120, 90, 56, 48, 53, 77, 102, 50, 57, 119, 52, 76, 84, 74, 120, 111, 101, 72, 116, 120, 77, 99, 102, 114, 72, 117, 66, 110, 81, 102, 79, 51, 10, 111, 75, 102, 78, 53, 88, 111, 122, 78, 109, 114, 54, 109, 105, 115, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 119, 105, 115, 115, 83, 105, 103, 110, 32, 71, 111, 108, 100, 32, 67, 65, 32, 45, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 117, 106, 67, 67, 65, 54, 75, 103, 65, 119, 73, 66, 65, 103, 73, 74, 65, 76, 116, 65, 72, 69, 80, 49, 88, 107, 43, 119, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 77, 69, 85, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 78, 73, 77, 82, 85, 119, 10, 69, 119, 89, 68, 86, 81, 81, 75, 69, 119, 120, 84, 100, 50, 108, 122, 99, 49, 78, 112, 90, 50, 52, 103, 81, 85, 99, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 77, 84, 70, 108, 78, 51, 97, 88, 78, 122, 85, 50, 108, 110, 98, 105, 66, 72, 98, 50, 120, 107, 73, 69, 78, 66, 73, 67, 48, 103, 82, 122, 73, 119, 72, 104, 99, 78, 10, 77, 68, 89, 120, 77, 68, 73, 49, 77, 68, 103, 122, 77, 68, 77, 49, 87, 104, 99, 78, 77, 122, 89, 120, 77, 68, 73, 49, 77, 68, 103, 122, 77, 68, 77, 49, 87, 106, 66, 70, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 68, 83, 68, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 85, 51, 100, 112, 10, 99, 51, 78, 84, 97, 87, 100, 117, 73, 69, 70, 72, 77, 82, 56, 119, 72, 81, 89, 68, 86, 81, 81, 68, 69, 120, 90, 84, 100, 50, 108, 122, 99, 49, 78, 112, 90, 50, 52, 103, 82, 50, 57, 115, 90, 67, 66, 68, 81, 83, 65, 116, 73, 69, 99, 121, 77, 73, 73, 67, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 10, 65, 81, 69, 70, 65, 65, 79, 67, 65, 103, 56, 65, 77, 73, 73, 67, 67, 103, 75, 67, 65, 103, 69, 65, 114, 43, 84, 117, 102, 111, 115, 107, 68, 104, 74, 117, 113, 86, 65, 116, 70, 107, 81, 55, 107, 112, 74, 99, 121, 114, 104, 100, 104, 74, 74, 67, 69, 121, 113, 56, 90, 86, 101, 67, 81, 68, 53, 88, 74, 77, 49, 81, 105, 121, 85, 113, 10, 116, 50, 47, 56, 55, 54, 76, 81, 119, 66, 56, 67, 74, 69, 111, 84, 108, 111, 56, 106, 69, 43, 89, 111, 87, 65, 67, 106, 82, 56, 99, 71, 112, 52, 81, 106, 75, 55, 117, 57, 108, 105, 116, 47, 86, 99, 121, 76, 119, 86, 99, 102, 68, 109, 74, 108, 68, 57, 48, 57, 86, 111, 112, 122, 50, 113, 53, 43, 98, 98, 113, 66, 72, 72, 53, 67, 10, 106, 67, 65, 49, 50, 85, 78, 78, 104, 80, 113, 69, 50, 49, 73, 115, 56, 119, 52, 110, 100, 119, 116, 114, 118, 120, 69, 118, 99, 110, 105, 102, 76, 116, 103, 43, 53, 104, 103, 51, 87, 105, 112, 121, 43, 100, 112, 105, 107, 74, 75, 86, 121, 104, 43, 99, 54, 98, 77, 56, 75, 56, 118, 122, 65, 82, 79, 47, 87, 115, 47, 66, 116, 81, 112, 103, 10, 118, 100, 50, 49, 109, 87, 82, 84, 117, 75, 67, 87, 115, 50, 47, 105, 74, 110, 101, 82, 106, 79, 66, 105, 69, 65, 75, 102, 78, 65, 43, 107, 49, 90, 73, 122, 85, 100, 54, 43, 106, 98, 113, 69, 101, 109, 65, 56, 97, 116, 117, 102, 75, 43, 122, 101, 51, 103, 69, 47, 98, 107, 51, 108, 85, 73, 98, 76, 116, 75, 47, 116, 82, 69, 68, 70, 10, 121, 108, 113, 77, 50, 116, 73, 114, 102, 75, 106, 117, 118, 113, 98, 108, 67, 113, 111, 79, 112, 100, 56, 70, 85, 114, 100, 86, 120, 121, 74, 100, 77, 109, 113, 88, 108, 50, 77, 84, 50, 56, 110, 98, 101, 84, 90, 55, 104, 84, 112, 75, 120, 86, 75, 74, 43, 83, 84, 110, 110, 88, 101, 112, 103, 118, 57, 86, 72, 75, 86, 120, 97, 83, 118, 82, 10, 65, 105, 84, 121, 115, 121, 98, 85, 97, 57, 111, 69, 86, 101, 88, 66, 67, 115, 100, 116, 77, 68, 101, 81, 75, 117, 83, 101, 70, 68, 78, 101, 70, 104, 100, 86, 120, 86, 117, 49, 121, 122, 83, 74, 107, 118, 71, 100, 74, 111, 43, 104, 66, 57, 84, 71, 115, 110, 104, 81, 50, 119, 119, 77, 67, 51, 119, 76, 106, 69, 72, 88, 117, 101, 110, 100, 10, 106, 73, 106, 51, 111, 48, 50, 121, 77, 115, 122, 89, 70, 57, 114, 78, 116, 56, 53, 109, 110, 100, 84, 57, 88, 118, 43, 57, 108, 122, 52, 112, 100, 101, 100, 43, 112, 50, 74, 89, 114, 121, 85, 48, 112, 85, 72, 72, 80, 98, 119, 78, 85, 77, 111, 68, 65, 119, 56, 73, 87, 104, 43, 86, 99, 51, 104, 105, 118, 54, 57, 121, 70, 71, 107, 79, 10, 112, 101, 85, 68, 68, 110, 105, 79, 74, 105, 104, 67, 56, 65, 99, 76, 89, 105, 65, 81, 90, 122, 108, 71, 43, 113, 107, 68, 122, 65, 81, 52, 101, 109, 98, 118, 73, 73, 79, 49, 106, 69, 112, 87, 106, 112, 69, 65, 47, 73, 53, 99, 103, 116, 54, 73, 111, 77, 80, 105, 97, 71, 53, 57, 106, 101, 56, 56, 51, 87, 88, 48, 88, 97, 120, 82, 10, 55, 121, 83, 65, 114, 113, 112, 87, 108, 50, 47, 53, 114, 88, 51, 97, 89, 84, 43, 89, 100, 122, 121, 108, 107, 98, 89, 99, 106, 67, 98, 97, 90, 97, 73, 74, 98, 99, 72, 105, 86, 79, 79, 53, 121, 107, 120, 77, 103, 73, 57, 51, 101, 50, 67, 97, 72, 116, 43, 50, 56, 107, 103, 101, 68, 114, 112, 79, 86, 71, 50, 89, 52, 79, 71, 105, 10, 71, 113, 74, 51, 85, 77, 47, 69, 89, 53, 76, 115, 82, 120, 109, 100, 54, 43, 90, 114, 122, 115, 69, 67, 65, 119, 69, 65, 65, 97, 79, 66, 114, 68, 67, 66, 113, 84, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 10, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 87, 121, 86, 55, 108, 113, 82, 108, 85, 88, 54, 52, 79, 102, 80, 65, 101, 71, 90, 101, 54, 68, 114, 110, 56, 79, 52, 119, 72, 119, 89, 68, 86, 82, 48, 106, 66, 66, 103, 119, 70, 111, 65, 85, 87, 121, 86, 55, 108, 113, 82, 108, 85, 88, 54, 52, 10, 79, 102, 80, 65, 101, 71, 90, 101, 54, 68, 114, 110, 56, 79, 52, 119, 82, 103, 89, 68, 86, 82, 48, 103, 66, 68, 56, 119, 80, 84, 65, 55, 66, 103, 108, 103, 104, 88, 81, 66, 87, 81, 69, 67, 65, 81, 69, 119, 76, 106, 65, 115, 66, 103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 67, 65, 82, 89, 103, 97, 72, 82, 48, 99, 68, 111, 118, 10, 76, 51, 74, 108, 99, 71, 57, 122, 97, 88, 82, 118, 99, 110, 107, 117, 99, 51, 100, 112, 99, 51, 78, 122, 97, 87, 100, 117, 76, 109, 78, 118, 98, 83, 56, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 73, 66, 65, 67, 101, 54, 52, 53, 82, 56, 56, 97, 55, 65, 51, 104, 102, 109, 10, 53, 100, 106, 86, 57, 86, 83, 119, 103, 47, 83, 55, 122, 86, 52, 70, 101, 48, 43, 102, 100, 87, 97, 118, 80, 79, 104, 87, 102, 118, 120, 121, 101, 68, 103, 68, 50, 83, 116, 105, 71, 119, 67, 53, 43, 79, 108, 103, 122, 99, 122, 79, 85, 89, 114, 72, 85, 68, 70, 117, 52, 85, 112, 43, 71, 67, 57, 112, 87, 98, 89, 57, 90, 73, 69, 114, 10, 52, 52, 79, 69, 53, 105, 75, 72, 106, 110, 51, 103, 55, 103, 75, 90, 89, 98, 103, 101, 57, 76, 103, 114, 105, 66, 73, 87, 104, 77, 73, 120, 107, 122, 105, 87, 77, 97, 97, 53, 79, 49, 77, 47, 119, 121, 83, 84, 86, 108, 116, 112, 107, 117, 122, 70, 119, 98, 115, 52, 65, 79, 80, 115, 70, 54, 109, 52, 51, 77, 100, 56, 65, 89, 79, 102, 10, 77, 107, 101, 54, 85, 105, 73, 48, 72, 84, 74, 54, 67, 86, 97, 110, 102, 67, 85, 50, 113, 84, 49, 76, 50, 115, 67, 67, 98, 119, 113, 55, 69, 115, 105, 72, 83, 121, 99, 82, 43, 82, 52, 116, 120, 53, 77, 47, 110, 116, 116, 102, 74, 109, 116, 83, 50, 83, 54, 75, 56, 82, 84, 71, 82, 73, 48, 86, 113, 98, 101, 47, 118, 100, 54, 109, 10, 71, 117, 54, 117, 76, 102, 116, 73, 100, 120, 102, 43, 117, 43, 121, 118, 71, 80, 85, 113, 85, 102, 65, 53, 104, 74, 101, 86, 98, 71, 52, 98, 119, 121, 118, 69, 100, 71, 66, 53, 74, 98, 65, 75, 74, 57, 47, 102, 88, 116, 73, 53, 122, 48, 86, 57, 81, 107, 118, 102, 115, 121, 119, 101, 120, 99, 90, 100, 121, 108, 85, 54, 111, 74, 120, 112, 10, 109, 111, 47, 97, 55, 55, 75, 119, 80, 74, 43, 72, 98, 66, 73, 114, 90, 88, 65, 86, 85, 106, 69, 97, 74, 77, 57, 118, 77, 83, 78, 81, 72, 52, 120, 80, 106, 121, 80, 68, 100, 69, 70, 106, 72, 70, 87, 111, 70, 78, 48, 43, 52, 70, 70, 81, 122, 47, 69, 98, 77, 70, 89, 79, 107, 114, 67, 67, 104, 100, 105, 68, 121, 121, 74, 107, 10, 118, 67, 50, 52, 74, 100, 86, 85, 111, 114, 103, 71, 54, 113, 50, 83, 112, 67, 83, 103, 119, 89, 97, 49, 83, 104, 78, 113, 82, 56, 56, 117, 67, 49, 97, 86, 86, 77, 118, 79, 109, 116, 116, 113, 116, 75, 97, 121, 50, 48, 69, 73, 104, 105, 100, 51, 57, 50, 113, 103, 81, 109, 119, 76, 79, 77, 55, 88, 100, 86, 65, 121, 107, 115, 76, 102, 10, 75, 122, 65, 105, 83, 78, 68, 86, 81, 84, 103, 108, 88, 97, 84, 112, 88, 90, 47, 71, 108, 72, 88, 81, 82, 102, 48, 119, 108, 48, 79, 80, 107, 75, 115, 75, 120, 52, 90, 122, 89, 69, 112, 112, 76, 100, 54, 108, 101, 78, 99, 71, 50, 109, 113, 101, 83, 122, 53, 51, 79, 105, 65, 84, 73, 103, 72, 81, 118, 50, 105, 101, 89, 50, 66, 114, 10, 78, 85, 48, 76, 98, 98, 113, 104, 80, 99, 67, 84, 52, 72, 56, 106, 115, 49, 87, 116, 99, 105, 86, 79, 82, 118, 110, 83, 70, 117, 43, 119, 90, 77, 69, 66, 110, 117, 110, 75, 111, 71, 113, 89, 68, 115, 47, 89, 89, 80, 73, 118, 83, 98, 106, 107, 81, 117, 69, 52, 78, 82, 98, 48, 121, 71, 53, 80, 57, 52, 70, 87, 54, 76, 113, 106, 10, 118, 105, 79, 118, 114, 118, 49, 118, 65, 43, 65, 67, 79, 122, 66, 50, 43, 104, 116, 116, 81, 99, 56, 66, 115, 101, 109, 52, 121, 87, 98, 48, 50, 121, 98, 122, 79, 113, 82, 48, 56, 107, 107, 107, 87, 56, 109, 119, 48, 70, 102, 66, 43, 106, 53, 54, 52, 90, 102, 74, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 119, 105, 115, 115, 83, 105, 103, 110, 32, 83, 105, 108, 118, 101, 114, 32, 67, 65, 32, 45, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 118, 84, 67, 67, 65, 54, 87, 103, 65, 119, 73, 66, 65, 103, 73, 73, 84, 120, 118, 85, 76, 49, 83, 55, 76, 48, 115, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 82, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 81, 48, 103, 120, 70, 84, 65, 84, 10, 66, 103, 78, 86, 66, 65, 111, 84, 68, 70, 78, 51, 97, 88, 78, 122, 85, 50, 108, 110, 98, 105, 66, 66, 82, 122, 69, 104, 77, 66, 56, 71, 65, 49, 85, 69, 65, 120, 77, 89, 85, 51, 100, 112, 99, 51, 78, 84, 97, 87, 100, 117, 73, 70, 78, 112, 98, 72, 90, 108, 99, 105, 66, 68, 81, 83, 65, 116, 73, 69, 99, 121, 77, 66, 52, 88, 10, 68, 84, 65, 50, 77, 84, 65, 121, 78, 84, 65, 52, 77, 122, 73, 48, 78, 108, 111, 88, 68, 84, 77, 50, 77, 84, 65, 121, 78, 84, 65, 52, 77, 122, 73, 48, 78, 108, 111, 119, 82, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 81, 48, 103, 120, 70, 84, 65, 84, 66, 103, 78, 86, 66, 65, 111, 84, 68, 70, 78, 51, 10, 97, 88, 78, 122, 85, 50, 108, 110, 98, 105, 66, 66, 82, 122, 69, 104, 77, 66, 56, 71, 65, 49, 85, 69, 65, 120, 77, 89, 85, 51, 100, 112, 99, 51, 78, 84, 97, 87, 100, 117, 73, 70, 78, 112, 98, 72, 90, 108, 99, 105, 66, 68, 81, 83, 65, 116, 73, 69, 99, 121, 77, 73, 73, 67, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 10, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 103, 56, 65, 77, 73, 73, 67, 67, 103, 75, 67, 65, 103, 69, 65, 120, 80, 71, 72, 102, 57, 78, 52, 77, 102, 99, 52, 121, 102, 106, 68, 109, 85, 79, 56, 120, 47, 101, 56, 78, 43, 100, 79, 99, 98, 112, 76, 106, 54, 86, 122, 72, 86, 120, 117, 109, 75, 52, 68, 86, 54, 52, 52, 10, 78, 48, 77, 118, 70, 122, 48, 102, 121, 77, 53, 111, 69, 77, 70, 52, 114, 104, 107, 68, 75, 120, 68, 54, 76, 72, 109, 68, 57, 117, 105, 53, 97, 76, 108, 86, 56, 103, 82, 69, 112, 122, 110, 53, 47, 65, 83, 76, 72, 118, 71, 105, 84, 83, 102, 53, 89, 88, 117, 54, 116, 43, 87, 105, 69, 55, 98, 114, 89, 84, 55, 81, 98, 78, 72, 109, 10, 43, 47, 112, 101, 55, 82, 50, 48, 110, 113, 65, 49, 87, 54, 71, 83, 121, 47, 66, 74, 107, 118, 54, 70, 67, 103, 85, 43, 53, 116, 107, 76, 52, 107, 43, 55, 51, 74, 85, 51, 47, 74, 72, 112, 77, 106, 85, 105, 48, 82, 56, 54, 84, 105, 101, 70, 110, 98, 65, 86, 108, 68, 76, 97, 89, 81, 49, 72, 84, 87, 66, 67, 114, 112, 74, 72, 10, 54, 73, 78, 97, 85, 70, 106, 112, 105, 111, 117, 53, 88, 97, 72, 99, 51, 90, 108, 75, 72, 122, 90, 110, 117, 48, 106, 107, 103, 55, 89, 51, 54, 48, 103, 54, 114, 119, 57, 110, 106, 120, 99, 72, 54, 65, 84, 75, 55, 50, 111, 120, 104, 57, 84, 65, 116, 118, 109, 85, 99, 88, 116, 110, 90, 76, 105, 50, 107, 85, 112, 67, 101, 50, 85, 117, 10, 77, 71, 111, 77, 57, 90, 68, 117, 108, 101, 98, 121, 122, 89, 76, 115, 50, 97, 70, 75, 55, 80, 97, 121, 83, 43, 86, 70, 104, 101, 90, 116, 101, 74, 77, 69, 76, 112, 121, 67, 98, 84, 97, 112, 120, 68, 70, 107, 72, 52, 97, 68, 67, 121, 114, 48, 78, 81, 112, 52, 121, 86, 88, 80, 81, 98, 66, 72, 54, 84, 67, 102, 109, 98, 53, 104, 10, 113, 65, 97, 69, 117, 83, 104, 54, 88, 122, 106, 90, 71, 54, 107, 52, 115, 73, 78, 47, 99, 56, 72, 68, 79, 48, 103, 113, 103, 103, 56, 104, 109, 55, 106, 77, 113, 68, 88, 68, 104, 66, 117, 68, 115, 122, 54, 43, 112, 74, 86, 112, 65, 84, 113, 74, 65, 72, 103, 69, 50, 99, 110, 48, 109, 82, 109, 114, 86, 110, 53, 98, 105, 52, 89, 53, 10, 70, 90, 71, 107, 69, 67, 119, 74, 77, 111, 66, 103, 115, 53, 80, 65, 75, 114, 89, 89, 67, 53, 49, 43, 106, 85, 110, 121, 69, 69, 112, 47, 43, 100, 86, 71, 76, 120, 109, 83, 111, 53, 109, 110, 74, 113, 121, 55, 106, 68, 122, 109, 68, 114, 120, 72, 66, 57, 120, 122, 85, 102, 70, 119, 90, 67, 56, 73, 43, 98, 82, 72, 72, 84, 66, 115, 10, 82, 79, 111, 112, 78, 52, 87, 83, 97, 71, 97, 56, 103, 122, 106, 43, 101, 122, 107, 117, 48, 49, 68, 119, 72, 47, 116, 101, 89, 76, 97, 112, 112, 118, 111, 110, 81, 102, 71, 98, 71, 72, 76, 121, 57, 89, 82, 48, 83, 115, 108, 110, 120, 70, 83, 117, 83, 71, 84, 102, 106, 78, 70, 117, 115, 66, 51, 104, 66, 52, 56, 73, 72, 112, 109, 99, 10, 99, 101, 108, 77, 50, 75, 88, 51, 82, 120, 73, 102, 100, 78, 70, 82, 110, 111, 98, 122, 119, 113, 73, 106, 81, 65, 116, 122, 50, 48, 117, 109, 53, 51, 77, 71, 106, 77, 71, 103, 54, 99, 70, 90, 114, 69, 98, 54, 53, 105, 47, 52, 122, 51, 71, 99, 82, 109, 50, 53, 120, 66, 87, 78, 79, 72, 107, 68, 82, 85, 106, 118, 120, 70, 51, 88, 10, 67, 79, 54, 72, 79, 83, 75, 71, 115, 103, 48, 80, 87, 69, 80, 51, 99, 97, 108, 73, 76, 118, 51, 113, 49, 104, 56, 67, 65, 119, 69, 65, 65, 97, 79, 66, 114, 68, 67, 66, 113, 84, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 10, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 70, 54, 68, 78, 119, 101, 82, 66, 116, 106, 112, 98, 79, 56, 116, 70, 110, 98, 48, 99, 119, 112, 106, 54, 104, 108, 103, 119, 72, 119, 89, 68, 86, 82, 48, 106, 66, 66, 103, 119, 70, 111, 65, 85, 70, 54, 68, 78, 119, 101, 82, 66, 10, 116, 106, 112, 98, 79, 56, 116, 70, 110, 98, 48, 99, 119, 112, 106, 54, 104, 108, 103, 119, 82, 103, 89, 68, 86, 82, 48, 103, 66, 68, 56, 119, 80, 84, 65, 55, 66, 103, 108, 103, 104, 88, 81, 66, 87, 81, 69, 68, 65, 81, 69, 119, 76, 106, 65, 115, 66, 103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 67, 65, 82, 89, 103, 97, 72, 82, 48, 10, 99, 68, 111, 118, 76, 51, 74, 108, 99, 71, 57, 122, 97, 88, 82, 118, 99, 110, 107, 117, 99, 51, 100, 112, 99, 51, 78, 122, 97, 87, 100, 117, 76, 109, 78, 118, 98, 83, 56, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 73, 66, 65, 72, 80, 71, 103, 101, 65, 110, 48, 105, 48, 80, 10, 52, 74, 85, 119, 52, 112, 112, 66, 102, 49, 65, 115, 88, 49, 57, 105, 89, 97, 109, 71, 97, 109, 107, 89, 68, 72, 82, 74, 49, 108, 50, 69, 54, 107, 70, 83, 71, 71, 57, 89, 114, 86, 66, 87, 73, 71, 114, 71, 118, 83, 104, 112, 87, 74, 72, 99, 107, 82, 69, 49, 113, 84, 111, 100, 118, 66, 113, 108, 89, 74, 55, 89, 72, 51, 57, 70, 10, 107, 87, 110, 90, 102, 114, 116, 52, 99, 115, 69, 71, 68, 121, 114, 79, 106, 52, 86, 119, 89, 97, 121, 103, 122, 81, 117, 52, 79, 83, 108, 87, 104, 68, 74, 79, 104, 114, 115, 57, 120, 67, 114, 90, 49, 120, 57, 121, 55, 118, 53, 82, 111, 83, 74, 66, 115, 88, 69, 67, 89, 120, 113, 67, 115, 71, 75, 114, 88, 108, 99, 83, 72, 57, 47, 76, 10, 51, 88, 87, 103, 119, 70, 49, 53, 107, 73, 119, 98, 52, 70, 68, 109, 51, 106, 72, 43, 109, 72, 116, 119, 88, 54, 87, 81, 50, 75, 51, 52, 65, 114, 90, 118, 48, 50, 68, 100, 81, 69, 115, 105, 120, 84, 50, 116, 79, 110, 113, 102, 71, 104, 112, 72, 107, 88, 107, 122, 117, 111, 76, 99, 77, 109, 107, 68, 108, 109, 52, 102, 83, 47, 66, 120, 10, 47, 117, 78, 110, 99, 113, 67, 120, 118, 49, 121, 76, 53, 80, 113, 90, 73, 115, 101, 69, 117, 82, 117, 78, 73, 53, 99, 47, 55, 83, 88, 103, 122, 50, 87, 55, 57, 87, 69, 69, 55, 57, 48, 101, 115, 108, 112, 66, 73, 108, 113, 104, 110, 49, 48, 115, 54, 70, 118, 74, 98, 97, 107, 77, 68, 72, 105, 113, 89, 77, 90, 87, 106, 119, 70, 97, 10, 68, 71, 105, 56, 97, 82, 108, 53, 120, 66, 57, 43, 108, 119, 87, 47, 120, 101, 107, 107, 85, 86, 55, 85, 49, 85, 116, 84, 55, 100, 107, 106, 87, 106, 89, 68, 90, 97, 80, 66, 65, 54, 49, 66, 77, 80, 78, 71, 71, 52, 87, 81, 114, 50, 87, 49, 49, 98, 72, 107, 70, 108, 116, 52, 100, 82, 50, 88, 101, 109, 49, 90, 113, 83, 113, 80, 10, 101, 57, 55, 68, 104, 52, 107, 81, 109, 85, 108, 122, 101, 77, 103, 57, 118, 86, 69, 49, 100, 67, 114, 86, 56, 88, 53, 112, 71, 121, 113, 55, 79, 55, 48, 108, 117, 74, 112, 97, 80, 88, 74, 104, 107, 71, 97, 72, 55, 103, 122, 87, 84, 100, 81, 82, 100, 65, 116, 113, 47, 103, 115, 68, 47, 75, 78, 86, 86, 52, 110, 43, 83, 115, 117, 117, 10, 87, 120, 99, 70, 121, 80, 75, 78, 73, 122, 70, 84, 79, 78, 73, 116, 97, 106, 43, 67, 117, 89, 48, 73, 97, 118, 100, 101, 81, 88, 82, 117, 119, 120, 70, 43, 66, 54, 119, 112, 89, 74, 69, 47, 79, 77, 112, 88, 69, 65, 50, 57, 77, 67, 47, 72, 112, 101, 90, 66, 111, 78, 113, 117, 66, 89, 101, 97, 111, 75, 82, 108, 98, 69, 119, 74, 10, 68, 73, 109, 54, 117, 78, 79, 53, 119, 74, 79, 75, 77, 80, 113, 78, 53, 90, 112, 114, 70, 81, 70, 79, 90, 54, 114, 97, 89, 108, 89, 43, 104, 65, 104, 109, 48, 115, 81, 50, 102, 97, 99, 43, 69, 80, 121, 73, 52, 78, 83, 65, 53, 81, 67, 57, 113, 118, 78, 79, 66, 113, 78, 54, 97, 118, 108, 105, 99, 117, 77, 74, 84, 43, 117, 98, 10, 68, 103, 69, 106, 56, 90, 43, 55, 102, 78, 122, 99, 98, 66, 71, 88, 74, 98, 76, 121, 116, 71, 77, 85, 48, 103, 89, 113, 90, 52, 121, 68, 57, 99, 55, 113, 66, 57, 105, 97, 97, 104, 55, 115, 53, 65, 113, 55, 75, 107, 122, 114, 67, 87, 65, 53, 122, 115, 112, 105, 50, 67, 53, 117, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 101, 111, 84, 114, 117, 115, 116, 32, 80, 114, 105, 109, 97, 114, 121, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 102, 68, 67, 67, 65, 109, 83, 103, 65, 119, 73, 66, 65, 103, 73, 81, 71, 75, 121, 49, 97, 118, 49, 112, 116, 104, 85, 54, 89, 50, 121, 118, 50, 118, 114, 69, 111, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 89, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 67, 104, 77, 78, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 83, 87, 53, 106, 76, 106, 69, 120, 77, 67, 56, 71, 65, 49, 85, 69, 65, 120, 77, 111, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 85, 72, 74, 112, 98, 87, 70, 121, 101, 83, 66, 68, 10, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 84, 65, 101, 70, 119, 48, 119, 78, 106, 69, 120, 77, 106, 99, 119, 77, 68, 65, 119, 77, 68, 66, 97, 70, 119, 48, 122, 78, 106, 65, 51, 77, 84, 89, 121, 77, 122, 85, 53, 78, 84, 108, 97, 77, 70, 103, 120, 10, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 89, 119, 70, 65, 89, 68, 86, 81, 81, 75, 69, 119, 49, 72, 90, 87, 57, 85, 99, 110, 86, 122, 100, 67, 66, 74, 98, 109, 77, 117, 77, 84, 69, 119, 76, 119, 89, 68, 86, 81, 81, 68, 69, 121, 104, 72, 90, 87, 57, 85, 99, 110, 86, 122, 100, 67, 66, 81, 10, 99, 109, 108, 116, 89, 88, 74, 53, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 10, 67, 103, 75, 67, 65, 81, 69, 65, 118, 114, 103, 86, 101, 47, 47, 85, 102, 72, 49, 110, 114, 89, 78, 107, 101, 56, 104, 67, 85, 121, 51, 102, 57, 111, 81, 73, 73, 71, 72, 87, 65, 86, 108, 113, 110, 69, 81, 82, 114, 43, 57, 50, 47, 90, 86, 43, 122, 109, 69, 119, 117, 51, 113, 68, 88, 119, 75, 57, 65, 87, 98, 75, 55, 104, 87, 78, 10, 98, 54, 69, 119, 110, 76, 50, 104, 104, 90, 54, 85, 79, 118, 78, 87, 105, 65, 65, 120, 122, 57, 106, 117, 97, 112, 89, 67, 50, 101, 48, 68, 106, 80, 116, 49, 98, 101, 102, 113, 117, 70, 85, 87, 66, 82, 97, 97, 57, 79, 66, 101, 115, 89, 106, 65, 90, 73, 86, 99, 70, 85, 50, 73, 120, 55, 101, 54, 52, 72, 88, 112, 114, 81, 85, 57, 10, 110, 99, 101, 74, 83, 79, 67, 55, 75, 77, 103, 68, 52, 84, 67, 84, 90, 70, 53, 83, 119, 70, 108, 119, 73, 106, 86, 88, 105, 73, 114, 120, 108, 81, 113, 68, 49, 55, 119, 120, 99, 119, 69, 48, 55, 101, 57, 71, 99, 101, 66, 114, 65, 113, 103, 49, 99, 109, 117, 88, 109, 50, 98, 103, 121, 120, 120, 53, 88, 57, 103, 97, 66, 71, 103, 101, 10, 82, 119, 76, 109, 110, 87, 68, 105, 78, 112, 99, 66, 51, 56, 52, 49, 107, 116, 43, 43, 90, 56, 100, 116, 100, 49, 107, 55, 106, 53, 51, 87, 107, 66, 87, 85, 118, 69, 73, 48, 69, 77, 69, 53, 43, 98, 69, 110, 80, 110, 55, 87, 105, 110, 88, 70, 115, 113, 43, 87, 48, 54, 76, 101, 109, 43, 83, 89, 118, 110, 51, 104, 54, 89, 71, 116, 10, 116, 109, 47, 56, 49, 119, 55, 97, 52, 68, 83, 119, 68, 82, 112, 51, 53, 43, 77, 73, 109, 79, 57, 89, 43, 112, 121, 69, 116, 122, 97, 118, 119, 116, 43, 115, 48, 118, 81, 81, 66, 110, 66, 120, 78, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 10, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 76, 78, 86, 81, 81, 90, 99, 86, 105, 47, 67, 80, 78, 109, 70, 98, 83, 118, 116, 114, 50, 90, 110, 74, 77, 53, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 70, 112, 119, 102, 121, 122, 100, 116, 122, 82, 80, 57, 89, 90, 82, 113, 83, 97, 43, 83, 55, 105, 113, 56, 88, 69, 78, 51, 71, 72, 72, 111, 79, 111, 48, 72, 110, 112, 51, 68, 119, 81, 49, 54, 67, 101, 80, 98, 74, 67, 47, 107, 82, 89, 107, 82, 106, 53, 75, 10, 84, 115, 52, 114, 70, 116, 85, 76, 85, 104, 51, 56, 72, 50, 101, 105, 65, 107, 85, 120, 84, 56, 55, 122, 43, 103, 79, 110, 101, 90, 49, 84, 97, 116, 110, 97, 89, 122, 114, 52, 103, 78, 102, 84, 109, 101, 71, 108, 52, 98, 55, 85, 86, 88, 71, 89, 78, 84, 113, 43, 107, 43, 113, 117, 114, 85, 75, 121, 107, 71, 47, 103, 47, 67, 70, 78, 10, 78, 87, 77, 122, 105, 85, 110, 87, 109, 48, 55, 75, 120, 43, 100, 79, 67, 81, 68, 51, 50, 115, 102, 118, 109, 87, 75, 90, 100, 55, 97, 86, 73, 108, 54, 75, 111, 75, 118, 48, 117, 72, 105, 89, 121, 106, 103, 90, 109, 99, 108, 121, 110, 110, 106, 78, 83, 54, 121, 118, 71, 97, 66, 122, 69, 105, 51, 56, 119, 107, 71, 54, 103, 90, 72, 97, 10, 70, 108, 111, 120, 116, 47, 109, 48, 99, 89, 65, 83, 83, 74, 108, 121, 99, 49, 112, 90, 85, 56, 70, 106, 85, 106, 80, 116, 112, 56, 110, 83, 79, 81, 74, 119, 43, 117, 67, 120, 81, 109, 89, 112, 113, 112, 116, 82, 55, 84, 66, 85, 73, 104, 82, 102, 50, 97, 115, 100, 119, 101, 83, 85, 56, 80, 106, 49, 75, 47, 102, 113, 121, 110, 104, 71, 10, 49, 114, 105, 82, 47, 97, 89, 78, 75, 120, 111, 85, 65, 84, 54, 65, 56, 69, 75, 103, 108, 81, 100, 101, 98, 99, 51, 77, 83, 54, 82, 70, 106, 97, 115, 83, 54, 76, 80, 101, 87, 117, 87, 103, 102, 79, 103, 80, 73, 104, 49, 97, 54, 86, 107, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 116, 104, 97, 119, 116, 101, 32, 80, 114, 105, 109, 97, 114, 121, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 73, 68, 67, 67, 65, 119, 105, 103, 65, 119, 73, 66, 65, 103, 73, 81, 78, 69, 55, 86, 86, 121, 68, 86, 55, 101, 120, 74, 57, 67, 47, 79, 78, 57, 115, 114, 98, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 66, 113, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 86, 86, 77, 120, 70, 84, 65, 84, 66, 103, 78, 86, 66, 65, 111, 84, 68, 72, 82, 111, 89, 88, 100, 48, 90, 83, 119, 103, 83, 87, 53, 106, 76, 106, 69, 111, 77, 67, 89, 71, 65, 49, 85, 69, 67, 120, 77, 102, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 84, 90, 88, 74, 50, 10, 97, 87, 78, 108, 99, 121, 66, 69, 97, 88, 90, 112, 99, 50, 108, 118, 98, 106, 69, 52, 77, 68, 89, 71, 65, 49, 85, 69, 67, 120, 77, 118, 75, 71, 77, 112, 73, 68, 73, 119, 77, 68, 89, 103, 100, 71, 104, 104, 100, 51, 82, 108, 76, 67, 66, 74, 98, 109, 77, 117, 73, 67, 48, 103, 82, 109, 57, 121, 73, 71, 70, 49, 100, 71, 104, 118, 10, 99, 109, 108, 54, 90, 87, 81, 103, 100, 88, 78, 108, 73, 71, 57, 117, 98, 72, 107, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 77, 84, 70, 110, 82, 111, 89, 88, 100, 48, 90, 83, 66, 81, 99, 109, 108, 116, 89, 88, 74, 53, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 119, 72, 104, 99, 78, 77, 68, 89, 120, 77, 84, 69, 51, 10, 77, 68, 65, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 122, 89, 119, 78, 122, 69, 50, 77, 106, 77, 49, 79, 84, 85, 53, 87, 106, 67, 66, 113, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 84, 65, 84, 66, 103, 78, 86, 66, 65, 111, 84, 68, 72, 82, 111, 89, 88, 100, 48, 90, 83, 119, 103, 10, 83, 87, 53, 106, 76, 106, 69, 111, 77, 67, 89, 71, 65, 49, 85, 69, 67, 120, 77, 102, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 84, 90, 88, 74, 50, 97, 87, 78, 108, 99, 121, 66, 69, 97, 88, 90, 112, 99, 50, 108, 118, 98, 106, 69, 52, 77, 68, 89, 71, 65, 49, 85, 69, 67, 120, 77, 118, 10, 75, 71, 77, 112, 73, 68, 73, 119, 77, 68, 89, 103, 100, 71, 104, 104, 100, 51, 82, 108, 76, 67, 66, 74, 98, 109, 77, 117, 73, 67, 48, 103, 82, 109, 57, 121, 73, 71, 70, 49, 100, 71, 104, 118, 99, 109, 108, 54, 90, 87, 81, 103, 100, 88, 78, 108, 73, 71, 57, 117, 98, 72, 107, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 77, 84, 10, 70, 110, 82, 111, 89, 88, 100, 48, 90, 83, 66, 81, 99, 109, 108, 116, 89, 88, 74, 53, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 115, 10, 111, 80, 68, 55, 103, 70, 110, 85, 110, 77, 101, 107, 122, 53, 50, 104, 87, 88, 77, 74, 69, 69, 85, 77, 68, 83, 120, 117, 97, 80, 70, 115, 87, 48, 104, 111, 83, 86, 107, 51, 47, 65, 115, 122, 71, 99, 74, 51, 102, 56, 119, 81, 76, 90, 85, 48, 72, 79, 98, 114, 84, 81, 109, 110, 72, 78, 75, 52, 121, 90, 99, 50, 65, 114, 101, 74, 10, 49, 67, 82, 102, 66, 115, 68, 77, 82, 74, 83, 85, 106, 81, 74, 105, 98, 43, 116, 97, 51, 82, 71, 78, 75, 74, 112, 99, 104, 74, 65, 81, 101, 103, 50, 57, 100, 71, 89, 118, 97, 106, 105, 103, 52, 116, 86, 85, 82, 79, 115, 100, 66, 53, 56, 72, 117, 109, 47, 117, 54, 102, 49, 79, 67, 121, 110, 49, 80, 111, 83, 103, 65, 102, 71, 99, 10, 113, 47, 103, 99, 102, 111, 109, 107, 54, 75, 72, 89, 99, 87, 85, 78, 111, 49, 70, 55, 55, 114, 122, 83, 73, 109, 65, 78, 117, 86, 117, 100, 51, 55, 114, 56, 85, 86, 115, 76, 114, 53, 105, 121, 54, 83, 55, 112, 66, 79, 104, 105, 104, 57, 52, 114, 121, 78, 100, 79, 119, 85, 120, 107, 72, 116, 51, 80, 104, 49, 105, 54, 83, 107, 47, 75, 10, 97, 65, 99, 100, 72, 74, 49, 75, 120, 116, 85, 118, 107, 99, 120, 56, 99, 88, 73, 99, 120, 99, 66, 110, 54, 122, 76, 57, 121, 90, 74, 99, 108, 78, 113, 70, 119, 74, 117, 47, 85, 51, 48, 114, 67, 102, 83, 77, 110, 90, 69, 102, 108, 50, 112, 83, 121, 57, 52, 74, 78, 113, 82, 51, 50, 72, 117, 72, 85, 69, 84, 86, 80, 109, 52, 112, 10, 97, 102, 115, 53, 83, 83, 89, 101, 67, 97, 87, 65, 101, 48, 65, 116, 54, 43, 103, 110, 104, 99, 110, 43, 89, 102, 49, 43, 53, 110, 121, 88, 72, 100, 87, 100, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 10, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 55, 87, 48, 88, 80, 114, 56, 55, 76, 101, 118, 48, 120, 107, 104, 112, 113, 116, 118, 78, 71, 54, 49, 100, 73, 85, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 10, 65, 65, 79, 67, 65, 81, 69, 65, 101, 82, 72, 65, 83, 55, 79, 82, 116, 118, 122, 119, 54, 87, 102, 85, 68, 87, 53, 70, 118, 108, 88, 111, 107, 57, 76, 79, 65, 122, 47, 116, 50, 105, 87, 119, 72, 86, 102, 76, 72, 106, 112, 50, 111, 69, 122, 115, 85, 72, 98, 111, 90, 72, 73, 77, 112, 75, 110, 120, 117, 73, 118, 87, 49, 111, 101, 69, 10, 117, 122, 76, 108, 81, 82, 72, 65, 100, 57, 109, 122, 89, 74, 51, 114, 71, 57, 88, 82, 98, 107, 82, 69, 113, 97, 89, 66, 55, 70, 86, 105, 72, 88, 101, 52, 88, 73, 53, 73, 83, 88, 121, 99, 79, 49, 99, 82, 114, 75, 49, 122, 78, 52, 52, 118, 101, 70, 121, 81, 97, 69, 102, 90, 89, 71, 68, 109, 47, 65, 99, 57, 73, 105, 65, 88, 10, 120, 80, 99, 87, 54, 99, 84, 89, 99, 118, 110, 73, 99, 51, 122, 102, 70, 105, 56, 86, 113, 84, 55, 57, 97, 105, 101, 50, 111, 101, 116, 97, 117, 112, 103, 102, 49, 101, 78, 78, 90, 65, 113, 100, 69, 56, 104, 104, 117, 118, 85, 53, 72, 73, 101, 54, 117, 76, 49, 55, 73, 110, 47, 50, 47, 113, 120, 65, 101, 101, 87, 115, 69, 71, 56, 57, 10, 106, 120, 116, 53, 100, 111, 118, 69, 78, 55, 77, 104, 71, 73, 84, 108, 78, 103, 68, 114, 89, 121, 67, 90, 117, 101, 110, 43, 77, 119, 83, 55, 81, 99, 106, 66, 65, 118, 108, 69, 89, 121, 67, 101, 103, 99, 53, 67, 48, 57, 89, 47, 76, 72, 98, 84, 89, 53, 120, 90, 51, 89, 43, 109, 52, 81, 54, 103, 76, 107, 72, 51, 76, 112, 86, 72, 10, 122, 55, 122, 57, 77, 47, 80, 50, 67, 50, 70, 43, 102, 112, 69, 114, 103, 85, 102, 67, 74, 122, 68, 117, 112, 120, 66, 100, 78, 52, 57, 99, 79, 83, 118, 107, 66, 80, 66, 55, 106, 86, 97, 77, 97, 65, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 86, 101, 114, 105, 83, 105, 103, 110, 32, 67, 108, 97, 115, 115, 32, 51, 32, 80, 117, 98, 108, 105, 99, 32, 80, 114, 105, 109, 97, 114, 121, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 45, 32, 71, 53, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 48, 122, 67, 67, 65, 55, 117, 103, 65, 119, 73, 66, 65, 103, 73, 81, 71, 78, 114, 82, 110, 105, 90, 57, 54, 76, 116, 75, 73, 86, 106, 78, 122, 71, 115, 55, 83, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 66, 121, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 86, 86, 77, 120, 70, 122, 65, 86, 66, 103, 78, 86, 66, 65, 111, 84, 68, 108, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 76, 67, 66, 74, 98, 109, 77, 117, 77, 82, 56, 119, 72, 81, 89, 68, 86, 81, 81, 76, 69, 120, 90, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 66, 85, 99, 110, 86, 122, 100, 67, 66, 79, 10, 90, 88, 82, 51, 98, 51, 74, 114, 77, 84, 111, 119, 79, 65, 89, 68, 86, 81, 81, 76, 69, 122, 69, 111, 89, 121, 107, 103, 77, 106, 65, 119, 78, 105, 66, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 119, 103, 83, 87, 53, 106, 76, 105, 65, 116, 73, 69, 90, 118, 99, 105, 66, 104, 100, 88, 82, 111, 98, 51, 74, 112, 101, 109, 86, 107, 10, 73, 72, 86, 122, 90, 83, 66, 118, 98, 109, 120, 53, 77, 85, 85, 119, 81, 119, 89, 68, 86, 81, 81, 68, 69, 122, 120, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 66, 68, 98, 71, 70, 122, 99, 121, 65, 122, 73, 70, 66, 49, 89, 109, 120, 112, 89, 121, 66, 81, 99, 109, 108, 116, 89, 88, 74, 53, 73, 69, 78, 108, 99, 110, 82, 112, 10, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 73, 67, 48, 103, 82, 122, 85, 119, 72, 104, 99, 78, 77, 68, 89, 120, 77, 84, 65, 52, 77, 68, 65, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 122, 89, 119, 78, 122, 69, 50, 77, 106, 77, 49, 79, 84, 85, 53, 87, 106, 67, 66, 10, 121, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 122, 65, 86, 66, 103, 78, 86, 66, 65, 111, 84, 68, 108, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 76, 67, 66, 74, 98, 109, 77, 117, 77, 82, 56, 119, 72, 81, 89, 68, 86, 81, 81, 76, 69, 120, 90, 87, 90, 88, 74, 112, 85, 50, 108, 110, 10, 98, 105, 66, 85, 99, 110, 86, 122, 100, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 77, 84, 111, 119, 79, 65, 89, 68, 86, 81, 81, 76, 69, 122, 69, 111, 89, 121, 107, 103, 77, 106, 65, 119, 78, 105, 66, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 119, 103, 83, 87, 53, 106, 76, 105, 65, 116, 73, 69, 90, 118, 99, 105, 66, 104, 10, 100, 88, 82, 111, 98, 51, 74, 112, 101, 109, 86, 107, 73, 72, 86, 122, 90, 83, 66, 118, 98, 109, 120, 53, 77, 85, 85, 119, 81, 119, 89, 68, 86, 81, 81, 68, 69, 122, 120, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 66, 68, 98, 71, 70, 122, 99, 121, 65, 122, 73, 70, 66, 49, 89, 109, 120, 112, 89, 121, 66, 81, 99, 109, 108, 116, 10, 89, 88, 74, 53, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 73, 67, 48, 103, 82, 122, 85, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 10, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 118, 74, 65, 103, 73, 75, 88, 111, 49, 110, 109, 65, 77, 113, 117, 100, 76, 79, 48, 55, 99, 102, 76, 119, 56, 82, 82, 121, 55, 75, 43, 68, 43, 75, 81, 76, 53, 86, 119, 105, 106, 90, 73, 85, 86, 74, 47, 88, 120, 114, 99, 103, 120, 105, 86, 48, 105, 54, 67, 113, 113, 112, 107, 75, 122, 10, 106, 47, 105, 53, 86, 98, 101, 120, 116, 48, 117, 122, 47, 111, 57, 43, 66, 49, 102, 115, 55, 48, 80, 98, 90, 109, 73, 86, 89, 99, 57, 103, 68, 97, 84, 89, 51, 118, 106, 103, 119, 50, 73, 73, 80, 86, 81, 84, 54, 48, 110, 75, 87, 86, 83, 70, 74, 117, 85, 114, 106, 120, 117, 102, 54, 47, 87, 104, 107, 99, 73, 122, 83, 100, 104, 68, 10, 89, 50, 112, 83, 83, 57, 75, 80, 54, 72, 66, 82, 84, 100, 71, 74, 97, 88, 118, 72, 99, 80, 97, 122, 51, 66, 74, 48, 50, 51, 116, 100, 83, 49, 98, 84, 108, 114, 56, 86, 100, 54, 71, 119, 57, 75, 73, 108, 56, 113, 56, 99, 107, 109, 99, 89, 53, 102, 81, 71, 66, 79, 43, 81, 117, 101, 81, 65, 53, 78, 48, 54, 116, 82, 110, 47, 10, 65, 114, 114, 48, 80, 79, 55, 103, 105, 43, 115, 51, 105, 43, 122, 48, 49, 54, 122, 121, 57, 118, 65, 57, 114, 57, 49, 49, 107, 84, 77, 90, 72, 82, 120, 65, 121, 51, 81, 107, 71, 83, 71, 84, 50, 82, 84, 43, 114, 67, 112, 83, 120, 52, 47, 86, 66, 69, 110, 107, 106, 87, 78, 72, 105, 68, 120, 112, 103, 56, 118, 43, 82, 55, 48, 114, 10, 102, 107, 47, 70, 108, 97, 52, 79, 110, 100, 84, 82, 81, 56, 66, 110, 99, 43, 77, 85, 67, 72, 55, 108, 80, 53, 57, 122, 117, 68, 77, 75, 122, 49, 48, 47, 78, 73, 101, 87, 105, 117, 53, 84, 54, 67, 85, 86, 65, 103, 77, 66, 65, 65, 71, 106, 103, 98, 73, 119, 103, 97, 56, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 10, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 98, 81, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 81, 119, 69, 89, 84, 66, 102, 111, 86, 50, 103, 87, 122, 66, 90, 77, 70, 99, 119, 86, 82, 89, 74, 97, 87, 49, 104, 90, 50, 85, 118, 10, 90, 50, 108, 109, 77, 67, 69, 119, 72, 122, 65, 72, 66, 103, 85, 114, 68, 103, 77, 67, 71, 103, 81, 85, 106, 43, 88, 84, 71, 111, 97, 115, 106, 89, 53, 114, 119, 56, 43, 65, 97, 116, 82, 73, 71, 67, 120, 55, 71, 83, 52, 119, 74, 82, 89, 106, 97, 72, 82, 48, 99, 68, 111, 118, 76, 50, 120, 118, 90, 50, 56, 117, 100, 109, 86, 121, 10, 97, 88, 78, 112, 90, 50, 52, 117, 89, 50, 57, 116, 76, 51, 90, 122, 98, 71, 57, 110, 98, 121, 53, 110, 97, 87, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 72, 47, 84, 90, 97, 102, 67, 51, 101, 121, 55, 56, 68, 65, 74, 56, 48, 77, 53, 43, 103, 75, 118, 77, 122, 69, 122, 77, 65, 48, 71, 67, 83, 113, 71, 10, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 66, 65, 81, 67, 84, 74, 69, 111, 119, 88, 50, 76, 80, 50, 66, 113, 89, 76, 122, 51, 113, 51, 74, 107, 116, 118, 88, 102, 50, 112, 88, 107, 105, 79, 79, 122, 69, 112, 54, 66, 52, 69, 113, 49, 105, 68, 107, 86, 119, 90, 77, 88, 110, 108, 50, 89, 116, 109, 65, 108, 43, 10, 88, 54, 47, 87, 122, 67, 104, 108, 56, 103, 71, 113, 67, 66, 112, 72, 51, 118, 110, 53, 102, 74, 74, 97, 67, 71, 107, 103, 68, 100, 107, 43, 98, 87, 52, 56, 68, 87, 55, 89, 53, 103, 97, 82, 81, 66, 105, 53, 43, 77, 72, 116, 51, 57, 116, 66, 113, 117, 67, 87, 73, 77, 110, 78, 90, 66, 85, 52, 103, 99, 109, 85, 55, 113, 75, 69, 10, 75, 81, 115, 84, 98, 52, 55, 98, 68, 78, 48, 108, 65, 116, 117, 107, 105, 120, 108, 69, 48, 107, 70, 54, 66, 87, 108, 75, 87, 69, 57, 103, 121, 110, 54, 67, 97, 103, 115, 67, 113, 105, 85, 88, 79, 98, 88, 98, 102, 43, 101, 69, 90, 83, 113, 86, 105, 114, 50, 71, 51, 108, 54, 66, 70, 111, 77, 116, 69, 77, 122, 101, 47, 97, 105, 67, 10, 75, 109, 48, 111, 72, 119, 48, 76, 120, 79, 88, 110, 71, 105, 89, 90, 52, 102, 81, 82, 98, 120, 67, 49, 108, 102, 122, 110, 81, 103, 85, 121, 50, 56, 54, 100, 85, 86, 52, 111, 116, 112, 54, 70, 48, 49, 118, 118, 112, 88, 49, 70, 81, 72, 75, 79, 116, 119, 53, 114, 68, 103, 98, 55, 77, 122, 86, 73, 99, 98, 105, 100, 74, 52, 118, 69, 10, 90, 86, 56, 78, 104, 110, 97, 99, 82, 72, 114, 50, 108, 86, 122, 50, 88, 84, 73, 73, 77, 54, 82, 85, 116, 104, 103, 47, 97, 70, 122, 121, 81, 107, 113, 70, 79, 70, 83, 68, 88, 57, 72, 111, 76, 80, 75, 115, 69, 100, 97, 111, 55, 87, 78, 113, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 101, 99, 117, 114, 101, 84, 114, 117, 115, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 117, 68, 67, 67, 65, 113, 67, 103, 65, 119, 73, 66, 65, 103, 73, 81, 68, 80, 67, 79, 88, 65, 103, 87, 112, 97, 49, 67, 102, 47, 68, 114, 74, 120, 104, 90, 48, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 73, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 103, 77, 66, 52, 71, 65, 49, 85, 69, 67, 104, 77, 88, 85, 50, 86, 106, 100, 88, 74, 108, 86, 72, 74, 49, 99, 51, 81, 103, 81, 50, 57, 121, 99, 71, 57, 121, 89, 88, 82, 112, 98, 50, 52, 120, 70, 122, 65, 86, 66, 103, 78, 86, 66, 65, 77, 84, 68, 108, 78, 108, 89, 51, 86, 121, 90, 86, 82, 121, 10, 100, 88, 78, 48, 73, 69, 78, 66, 77, 66, 52, 88, 68, 84, 65, 50, 77, 84, 69, 119, 78, 122, 69, 53, 77, 122, 69, 120, 79, 70, 111, 88, 68, 84, 73, 53, 77, 84, 73, 122, 77, 84, 69, 53, 78, 68, 65, 49, 78, 86, 111, 119, 83, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 73, 68, 65, 101, 10, 66, 103, 78, 86, 66, 65, 111, 84, 70, 49, 78, 108, 89, 51, 86, 121, 90, 86, 82, 121, 100, 88, 78, 48, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 99, 119, 70, 81, 89, 68, 86, 81, 81, 68, 69, 119, 53, 84, 90, 87, 78, 49, 99, 109, 86, 85, 99, 110, 86, 122, 100, 67, 66, 68, 81, 84, 67, 67, 10, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 75, 117, 107, 103, 101, 87, 86, 122, 102, 88, 50, 70, 73, 55, 67, 84, 56, 114, 85, 52, 110, 105, 86, 87, 74, 120, 66, 52, 81, 50, 90, 81, 67, 81, 88, 10, 79, 90, 69, 122, 90, 117, 109, 43, 52, 89, 79, 118, 89, 108, 121, 74, 48, 102, 119, 107, 87, 50, 71, 122, 52, 66, 69, 82, 81, 82, 119, 100, 98, 118, 67, 52, 117, 47, 106, 101, 112, 52, 71, 54, 112, 107, 106, 71, 110, 120, 50, 57, 118, 111, 54, 112, 81, 84, 54, 52, 108, 79, 48, 112, 71, 116, 83, 79, 48, 103, 77, 100, 65, 43, 57, 116, 10, 68, 87, 99, 99, 86, 57, 99, 71, 114, 99, 114, 73, 57, 102, 52, 79, 114, 50, 89, 108, 83, 65, 83, 87, 67, 49, 50, 106, 117, 104, 98, 68, 67, 69, 47, 82, 82, 118, 103, 85, 88, 80, 76, 73, 88, 103, 71, 90, 98, 102, 50, 73, 122, 73, 97, 111, 119, 87, 56, 120, 81, 109, 120, 83, 80, 109, 106, 76, 56, 120, 107, 48, 51, 55, 117, 72, 10, 71, 70, 97, 65, 74, 115, 84, 81, 51, 77, 66, 118, 51, 57, 54, 103, 119, 112, 69, 87, 111, 71, 81, 82, 83, 48, 83, 56, 72, 118, 98, 110, 43, 109, 80, 101, 90, 113, 120, 50, 112, 72, 71, 106, 55, 68, 97, 85, 97, 72, 112, 51, 112, 76, 72, 110, 68, 105, 43, 66, 101, 117, 75, 49, 99, 111, 98, 118, 111, 109, 117, 76, 56, 65, 47, 98, 10, 48, 49, 107, 47, 117, 110, 75, 56, 82, 67, 83, 99, 52, 51, 79, 122, 57, 54, 57, 88, 76, 48, 73, 109, 110, 97, 108, 48, 117, 103, 66, 83, 56, 107, 118, 78, 85, 51, 120, 72, 67, 122, 97, 70, 68, 109, 97, 112, 67, 74, 99, 87, 78, 70, 102, 66, 90, 118, 101, 65, 52, 43, 49, 119, 86, 77, 101, 84, 52, 67, 52, 111, 70, 86, 109, 72, 10, 117, 114, 115, 67, 65, 119, 69, 65, 65, 97, 79, 66, 110, 84, 67, 66, 109, 106, 65, 84, 66, 103, 107, 114, 66, 103, 69, 69, 65, 89, 73, 51, 70, 65, 73, 69, 66, 104, 52, 69, 65, 69, 77, 65, 81, 84, 65, 76, 66, 103, 78, 86, 72, 81, 56, 69, 66, 65, 77, 67, 65, 89, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 10, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 81, 106, 75, 50, 70, 118, 111, 69, 47, 102, 53, 100, 83, 51, 114, 68, 47, 102, 100, 77, 81, 66, 49, 97, 81, 54, 56, 119, 78, 65, 89, 68, 86, 82, 48, 102, 66, 67, 48, 119, 75, 122, 65, 112, 111, 67, 101, 103, 74, 89, 89, 106, 10, 97, 72, 82, 48, 99, 68, 111, 118, 76, 50, 78, 121, 98, 67, 53, 122, 90, 87, 78, 49, 99, 109, 86, 48, 99, 110, 86, 122, 100, 67, 53, 106, 98, 50, 48, 118, 85, 49, 82, 68, 81, 83, 53, 106, 99, 109, 119, 119, 69, 65, 89, 74, 75, 119, 89, 66, 66, 65, 71, 67, 78, 120, 85, 66, 66, 65, 77, 67, 65, 81, 65, 119, 68, 81, 89, 74, 10, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 68, 68, 116, 84, 48, 114, 104, 87, 68, 112, 83, 99, 108, 117, 49, 112, 113, 78, 108, 71, 75, 97, 55, 85, 84, 116, 51, 54, 90, 51, 113, 48, 53, 57, 99, 52, 69, 86, 108, 101, 119, 51, 75, 87, 43, 74, 119, 85, 76, 75, 85, 66, 82, 83, 117, 10, 83, 99, 101, 78, 81, 81, 99, 83, 99, 53, 82, 43, 68, 67, 77, 104, 47, 98, 119, 81, 102, 50, 65, 81, 87, 110, 76, 49, 109, 65, 54, 115, 55, 76, 108, 47, 51, 88, 112, 118, 88, 100, 77, 99, 57, 80, 43, 73, 66, 87, 108, 67, 113, 81, 86, 120, 121, 76, 101, 115, 74, 117, 103, 117, 116, 73, 120, 113, 47, 51, 72, 99, 117, 76, 72, 102, 10, 109, 98, 120, 56, 73, 86, 81, 114, 53, 70, 105, 105, 117, 49, 99, 112, 114, 112, 54, 112, 111, 120, 107, 109, 68, 53, 107, 117, 67, 76, 68, 118, 47, 87, 110, 80, 109, 82, 111, 74, 106, 101, 79, 110, 110, 121, 118, 74, 78, 106, 82, 55, 74, 76, 78, 52, 84, 74, 85, 88, 112, 65, 89, 109, 72, 114, 90, 107, 85, 106, 90, 102, 89, 71, 102, 90, 10, 110, 77, 85, 70, 100, 65, 118, 110, 90, 121, 80, 83, 67, 80, 121, 73, 54, 97, 54, 76, 102, 43, 69, 119, 57, 68, 100, 43, 47, 99, 89, 121, 50, 105, 50, 101, 82, 68, 65, 119, 98, 79, 52, 72, 51, 116, 73, 48, 47, 78, 76, 47, 81, 80, 90, 76, 57, 71, 90, 71, 66, 108, 83, 109, 56, 106, 73, 75, 89, 121, 89, 119, 97, 53, 118, 82, 10, 51, 73, 116, 72, 117, 117, 71, 53, 49, 87, 76, 81, 111, 113, 68, 48, 90, 119, 86, 52, 75, 87, 77, 97, 98, 119, 84, 87, 43, 77, 90, 77, 111, 53, 113, 120, 78, 55, 83, 78, 53, 83, 104, 76, 72, 90, 52, 115, 119, 114, 104, 111, 118, 79, 48, 67, 55, 106, 69, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 101, 99, 117, 114, 101, 32, 71, 108, 111, 98, 97, 108, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 118, 68, 67, 67, 65, 113, 83, 103, 65, 119, 73, 66, 65, 103, 73, 81, 66, 49, 89, 105, 112, 79, 106, 85, 105, 111, 108, 78, 57, 66, 80, 73, 56, 80, 106, 113, 112, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 75, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 103, 77, 66, 52, 71, 65, 49, 85, 69, 67, 104, 77, 88, 85, 50, 86, 106, 100, 88, 74, 108, 86, 72, 74, 49, 99, 51, 81, 103, 81, 50, 57, 121, 99, 71, 57, 121, 89, 88, 82, 112, 98, 50, 52, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 77, 84, 69, 70, 78, 108, 89, 51, 86, 121, 90, 83, 66, 72, 10, 98, 71, 57, 105, 89, 87, 119, 103, 81, 48, 69, 119, 72, 104, 99, 78, 77, 68, 89, 120, 77, 84, 65, 51, 77, 84, 107, 48, 77, 106, 73, 52, 87, 104, 99, 78, 77, 106, 107, 120, 77, 106, 77, 120, 77, 84, 107, 49, 77, 106, 65, 50, 87, 106, 66, 75, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 103, 10, 77, 66, 52, 71, 65, 49, 85, 69, 67, 104, 77, 88, 85, 50, 86, 106, 100, 88, 74, 108, 86, 72, 74, 49, 99, 51, 81, 103, 81, 50, 57, 121, 99, 71, 57, 121, 89, 88, 82, 112, 98, 50, 52, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 77, 84, 69, 70, 78, 108, 89, 51, 86, 121, 90, 83, 66, 72, 98, 71, 57, 105, 89, 87, 119, 103, 10, 81, 48, 69, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 118, 78, 83, 55, 89, 114, 71, 120, 86, 97, 81, 90, 120, 53, 82, 78, 111, 74, 76, 78, 80, 50, 77, 119, 104, 82, 47, 106, 120, 10, 89, 68, 105, 74, 105, 81, 80, 112, 118, 101, 112, 101, 82, 108, 77, 74, 51, 70, 122, 49, 87, 117, 106, 51, 82, 83, 111, 67, 54, 122, 70, 104, 49, 121, 107, 122, 84, 77, 55, 72, 102, 65, 111, 51, 102, 103, 43, 54, 77, 112, 106, 104, 72, 90, 101, 118, 106, 56, 102, 99, 121, 84, 105, 87, 56, 57, 115, 97, 47, 70, 72, 116, 97, 77, 98, 81, 10, 98, 113, 82, 56, 74, 78, 71, 117, 81, 115, 105, 87, 85, 71, 77, 117, 52, 80, 53, 49, 47, 112, 105, 110, 88, 48, 107, 117, 108, 101, 77, 53, 77, 50, 83, 79, 72, 113, 82, 102, 107, 78, 74, 110, 80, 76, 76, 90, 47, 107, 71, 53, 86, 97, 99, 74, 106, 110, 73, 70, 72, 111, 118, 100, 82, 73, 87, 67, 81, 116, 66, 74, 119, 66, 49, 103, 10, 56, 78, 69, 88, 76, 74, 88, 114, 57, 113, 88, 66, 107, 113, 80, 70, 119, 113, 99, 73, 89, 65, 49, 103, 66, 66, 67, 87, 101, 90, 52, 87, 78, 79, 97, 112, 116, 118, 111, 108, 82, 84, 110, 73, 72, 109, 88, 53, 107, 47, 87, 113, 56, 86, 76, 99, 109, 90, 103, 57, 112, 89, 89, 97, 68, 68, 85, 122, 43, 107, 117, 108, 66, 65, 89, 86, 10, 72, 68, 71, 65, 55, 54, 111, 89, 97, 56, 74, 55, 49, 57, 114, 79, 43, 84, 77, 103, 49, 102, 87, 57, 97, 106, 77, 116, 103, 81, 84, 55, 115, 70, 122, 85, 110, 75, 80, 105, 88, 66, 51, 106, 113, 85, 74, 49, 88, 110, 118, 85, 100, 43, 56, 53, 86, 76, 114, 74, 67, 104, 103, 98, 69, 112, 108, 74, 76, 52, 104, 76, 47, 86, 66, 105, 10, 48, 88, 80, 110, 106, 51, 112, 68, 65, 103, 77, 66, 65, 65, 71, 106, 103, 90, 48, 119, 103, 90, 111, 119, 69, 119, 89, 74, 75, 119, 89, 66, 66, 65, 71, 67, 78, 120, 81, 67, 66, 65, 89, 101, 66, 65, 66, 68, 65, 69, 69, 119, 67, 119, 89, 68, 86, 82, 48, 80, 66, 65, 81, 68, 65, 103, 71, 71, 77, 65, 56, 71, 65, 49, 85, 100, 10, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 75, 57, 69, 66, 77, 74, 66, 102, 107, 105, 68, 50, 48, 52, 53, 65, 117, 122, 115, 104, 72, 114, 109, 122, 115, 109, 107, 77, 68, 81, 71, 65, 49, 85, 100, 72, 119, 81, 116, 77, 67, 115, 119, 75, 97, 65, 110, 10, 111, 67, 87, 71, 73, 50, 104, 48, 100, 72, 65, 54, 76, 121, 57, 106, 99, 109, 119, 117, 99, 50, 86, 106, 100, 88, 74, 108, 100, 72, 74, 49, 99, 51, 81, 117, 89, 50, 57, 116, 76, 49, 78, 72, 81, 48, 69, 117, 89, 51, 74, 115, 77, 66, 65, 71, 67, 83, 115, 71, 65, 81, 81, 66, 103, 106, 99, 86, 65, 81, 81, 68, 65, 103, 69, 65, 10, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 66, 65, 81, 66, 106, 71, 103, 104, 65, 102, 97, 82, 101, 85, 119, 49, 51, 50, 72, 113, 117, 72, 119, 48, 76, 85, 82, 89, 68, 55, 120, 104, 56, 121, 79, 79, 118, 97, 108, 105, 84, 70, 71, 67, 82, 115, 111, 84, 99, 105, 69, 54, 43, 10, 79, 89, 111, 54, 56, 43, 97, 67, 105, 86, 48, 66, 78, 55, 79, 114, 74, 75, 81, 86, 68, 112, 73, 49, 87, 107, 112, 69, 88, 107, 53, 88, 43, 110, 88, 79, 72, 48, 106, 79, 90, 118, 81, 56, 81, 67, 97, 83, 109, 71, 119, 98, 55, 105, 82, 71, 68, 66, 101, 122, 85, 113, 88, 98, 112, 90, 71, 82, 122, 122, 102, 84, 98, 43, 99, 110, 10, 67, 68, 112, 79, 71, 82, 56, 54, 112, 49, 104, 99, 70, 56, 57, 53, 80, 52, 118, 107, 112, 57, 77, 109, 73, 53, 48, 109, 68, 49, 104, 112, 47, 69, 100, 43, 115, 116, 67, 78, 105, 53, 79, 47, 75, 85, 57, 68, 97, 88, 82, 50, 90, 48, 118, 80, 66, 52, 122, 109, 65, 118, 101, 49, 52, 98, 82, 68, 116, 85, 115, 116, 70, 74, 47, 53, 10, 51, 67, 89, 78, 118, 54, 90, 72, 100, 65, 98, 89, 105, 78, 69, 54, 75, 84, 67, 69, 122, 116, 73, 53, 103, 71, 73, 98, 113, 77, 100, 88, 83, 98, 120, 113, 86, 86, 70, 110, 70, 85, 113, 43, 78, 81, 102, 107, 49, 88, 87, 89, 78, 51, 107, 119, 70, 78, 115, 112, 110, 87, 122, 70, 97, 99, 120, 72, 86, 97, 73, 119, 57, 56, 120, 99, 10, 102, 56, 76, 68, 109, 66, 120, 114, 84, 104, 97, 65, 54, 51, 112, 52, 90, 85, 87, 105, 65, 66, 113, 118, 68, 65, 49, 86, 90, 68, 82, 73, 117, 74, 75, 53, 56, 98, 82, 81, 75, 102, 74, 80, 73, 120, 47, 97, 98, 75, 119, 102, 82, 79, 72, 100, 73, 51, 104, 82, 87, 56, 99, 87, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 79, 77, 79, 68, 79, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 72, 84, 67, 67, 65, 119, 87, 103, 65, 119, 73, 66, 65, 103, 73, 81, 84, 111, 69, 116, 105, 111, 74, 108, 52, 65, 115, 67, 55, 106, 52, 49, 65, 107, 98, 108, 80, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 66, 103, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 82, 48, 73, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 103, 84, 69, 107, 100, 121, 90, 87, 70, 48, 90, 88, 73, 103, 84, 87, 70, 117, 89, 50, 104, 108, 99, 51, 82, 108, 99, 106, 69, 81, 77, 65, 52, 71, 65, 49, 85, 69, 66, 120, 77, 72, 85, 50, 70, 115, 90, 109, 57, 121, 90, 68, 69, 97, 77, 66, 103, 71, 10, 65, 49, 85, 69, 67, 104, 77, 82, 81, 48, 57, 78, 84, 48, 82, 80, 73, 69, 78, 66, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 74, 122, 65, 108, 66, 103, 78, 86, 66, 65, 77, 84, 72, 107, 78, 80, 84, 85, 57, 69, 84, 121, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 10, 100, 71, 104, 118, 99, 109, 108, 48, 101, 84, 65, 101, 70, 119, 48, 119, 78, 106, 69, 121, 77, 68, 69, 119, 77, 68, 65, 119, 77, 68, 66, 97, 70, 119, 48, 121, 79, 84, 69, 121, 77, 122, 69, 121, 77, 122, 85, 53, 78, 84, 108, 97, 77, 73, 71, 66, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 72, 81, 106, 69, 98, 10, 77, 66, 107, 71, 65, 49, 85, 69, 67, 66, 77, 83, 82, 51, 74, 108, 89, 88, 82, 108, 99, 105, 66, 78, 89, 87, 53, 106, 97, 71, 86, 122, 100, 71, 86, 121, 77, 82, 65, 119, 68, 103, 89, 68, 86, 81, 81, 72, 69, 119, 100, 84, 89, 87, 120, 109, 98, 51, 74, 107, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 69, 120, 70, 68, 10, 84, 48, 49, 80, 82, 69, 56, 103, 81, 48, 69, 103, 84, 71, 108, 116, 97, 88, 82, 108, 90, 68, 69, 110, 77, 67, 85, 71, 65, 49, 85, 69, 65, 120, 77, 101, 81, 48, 57, 78, 84, 48, 82, 80, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 10, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 48, 69, 67, 76, 105, 51, 76, 106, 107, 82, 118, 51, 85, 99, 69, 98, 86, 65, 83, 89, 48, 54, 109, 47, 119, 101, 97, 75, 88, 84, 117, 72, 10, 43, 55, 117, 73, 122, 103, 51, 106, 76, 122, 56, 71, 108, 118, 67, 105, 75, 86, 67, 90, 114, 116, 115, 55, 111, 86, 101, 119, 100, 70, 70, 120, 122, 101, 49, 67, 107, 85, 49, 66, 47, 113, 110, 73, 50, 71, 113, 71, 100, 48, 83, 55, 87, 87, 97, 88, 85, 70, 54, 48, 49, 67, 120, 119, 82, 77, 47, 97, 78, 53, 86, 67, 97, 84, 119, 119, 10, 120, 72, 71, 122, 85, 118, 65, 104, 84, 97, 72, 89, 117, 106, 108, 56, 72, 74, 54, 106, 74, 74, 51, 121, 103, 120, 97, 89, 113, 104, 90, 56, 81, 53, 115, 86, 87, 55, 101, 117, 78, 74, 72, 43, 49, 71, 73, 109, 71, 69, 97, 97, 80, 43, 118, 66, 43, 102, 71, 81, 86, 43, 117, 115, 101, 103, 50, 76, 50, 51, 73, 119, 97, 109, 98, 86, 10, 52, 69, 97, 106, 99, 78, 120, 111, 50, 102, 56, 69, 83, 73, 108, 51, 51, 114, 88, 112, 43, 50, 100, 116, 81, 101, 109, 56, 79, 98, 48, 121, 50, 87, 73, 67, 56, 98, 71, 111, 80, 87, 52, 51, 110, 79, 73, 118, 52, 116, 79, 105, 74, 111, 118, 71, 117, 70, 86, 68, 105, 79, 69, 106, 80, 113, 88, 83, 74, 68, 108, 113, 82, 54, 115, 65, 10, 49, 75, 71, 122, 113, 83, 88, 43, 68, 84, 43, 110, 72, 98, 114, 84, 85, 99, 69, 76, 112, 78, 113, 115, 79, 79, 57, 86, 85, 67, 81, 70, 90, 85, 97, 84, 78, 69, 56, 116, 106, 97, 51, 71, 49, 67, 69, 90, 48, 111, 55, 75, 66, 87, 70, 120, 66, 51, 78, 72, 53, 89, 111, 90, 69, 114, 48, 69, 84, 99, 53, 79, 110, 75, 86, 73, 10, 114, 76, 115, 109, 57, 119, 73, 68, 65, 81, 65, 66, 111, 52, 71, 79, 77, 73, 71, 76, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 81, 76, 87, 79, 87, 76, 120, 107, 119, 86, 78, 54, 82, 65, 113, 84, 67, 112, 73, 98, 53, 72, 78, 108, 112, 87, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 10, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 66, 74, 66, 103, 78, 86, 72, 82, 56, 69, 81, 106, 66, 65, 77, 68, 54, 103, 80, 75, 65, 54, 104, 106, 104, 111, 100, 72, 82, 119, 79, 105, 56, 118, 89, 51, 74, 115, 76, 109, 78, 118, 98, 87, 57, 107, 10, 98, 50, 78, 104, 76, 109, 78, 118, 98, 83, 57, 68, 84, 48, 49, 80, 82, 69, 57, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 76, 109, 78, 121, 98, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 10, 65, 81, 69, 65, 80, 112, 105, 101, 109, 47, 89, 98, 54, 100, 99, 53, 116, 51, 105, 117, 72, 88, 73, 89, 83, 100, 79, 72, 53, 69, 79, 67, 54, 122, 47, 74, 113, 118, 87, 111, 116, 101, 57, 86, 102, 67, 70, 83, 90, 102, 110, 86, 68, 101, 70, 115, 57, 68, 54, 77, 107, 51, 79, 82, 76, 103, 76, 69, 84, 103, 100, 120, 98, 56, 67, 80, 10, 79, 71, 69, 73, 113, 66, 54, 66, 67, 115, 65, 118, 73, 67, 57, 66, 105, 53, 72, 99, 83, 69, 87, 56, 56, 99, 98, 101, 117, 110, 90, 114, 77, 56, 103, 65, 76, 84, 70, 71, 84, 79, 51, 110, 110, 99, 43, 73, 108, 80, 56, 122, 119, 70, 98, 111, 74, 73, 89, 109, 117, 78, 103, 52, 79, 78, 56, 113, 97, 57, 48, 83, 122, 77, 99, 47, 10, 82, 120, 100, 77, 111, 115, 73, 71, 108, 103, 110, 87, 50, 47, 52, 47, 80, 69, 90, 66, 51, 49, 106, 105, 86, 103, 56, 56, 79, 56, 69, 99, 107, 122, 88, 90, 79, 70, 75, 115, 55, 115, 106, 115, 76, 106, 66, 79, 108, 68, 87, 48, 74, 66, 57, 76, 101, 71, 110, 97, 56, 103, 73, 52, 122, 74, 86, 83, 107, 47, 66, 119, 74, 86, 109, 99, 10, 73, 71, 102, 69, 55, 118, 109, 76, 86, 50, 72, 48, 107, 110, 90, 57, 80, 52, 83, 78, 86, 98, 102, 111, 53, 97, 122, 86, 56, 102, 85, 90, 86, 113, 90, 97, 43, 53, 65, 99, 114, 53, 80, 114, 53, 82, 122, 85, 90, 53, 100, 100, 66, 65, 54, 43, 67, 52, 79, 109, 70, 52, 79, 53, 77, 66, 75, 103, 120, 84, 77, 86, 66, 98, 107, 78, 10, 43, 56, 99, 70, 100, 117, 80, 89, 83, 111, 51, 56, 78, 66, 101, 106, 120, 105, 69, 111, 118, 106, 66, 70, 77, 82, 55, 72, 101, 76, 53, 89, 89, 84, 105, 115, 79, 43, 73, 66, 90, 81, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 78, 101, 116, 119, 111, 114, 107, 32, 83, 111, 108, 117, 116, 105, 111, 110, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 53, 106, 67, 67, 65, 115, 54, 103, 65, 119, 73, 66, 65, 103, 73, 81, 86, 56, 115, 122, 98, 56, 74, 99, 70, 117, 90, 72, 70, 104, 102, 106, 107, 68, 70, 111, 52, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 105, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 104, 77, 66, 56, 71, 65, 49, 85, 69, 67, 104, 77, 89, 84, 109, 86, 48, 100, 50, 57, 121, 97, 121, 66, 84, 98, 50, 120, 49, 100, 71, 108, 118, 98, 110, 77, 103, 84, 67, 53, 77, 76, 107, 77, 117, 77, 84, 65, 119, 76, 103, 89, 68, 86, 81, 81, 68, 69, 121, 100, 79, 90, 88, 82, 51, 98, 51, 74, 114, 10, 73, 70, 78, 118, 98, 72, 86, 48, 97, 87, 57, 117, 99, 121, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 83, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 72, 104, 99, 78, 77, 68, 89, 120, 77, 106, 65, 120, 77, 68, 65, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 106, 107, 120, 77, 106, 77, 120, 10, 77, 106, 77, 49, 79, 84, 85, 53, 87, 106, 66, 105, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 104, 77, 66, 56, 71, 65, 49, 85, 69, 67, 104, 77, 89, 84, 109, 86, 48, 100, 50, 57, 121, 97, 121, 66, 84, 98, 50, 120, 49, 100, 71, 108, 118, 98, 110, 77, 103, 84, 67, 53, 77, 76, 107, 77, 117, 10, 77, 84, 65, 119, 76, 103, 89, 68, 86, 81, 81, 68, 69, 121, 100, 79, 90, 88, 82, 51, 98, 51, 74, 114, 73, 70, 78, 118, 98, 72, 86, 48, 97, 87, 57, 117, 99, 121, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 83, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 103, 103, 69, 105, 77, 65, 48, 71, 10, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 68, 107, 118, 72, 54, 83, 77, 71, 51, 71, 50, 73, 52, 114, 67, 55, 120, 71, 122, 117, 65, 110, 108, 116, 55, 101, 43, 102, 111, 83, 48, 122, 119, 122, 99, 55, 77, 69, 76, 55, 120, 120, 10, 106, 79, 87, 102, 116, 105, 74, 103, 80, 108, 57, 100, 122, 103, 110, 47, 103, 103, 119, 98, 109, 108, 70, 81, 71, 105, 97, 74, 51, 100, 86, 104, 88, 82, 110, 99, 69, 103, 56, 116, 67, 113, 74, 68, 88, 82, 102, 81, 78, 74, 73, 103, 54, 110, 80, 80, 79, 67, 119, 71, 74, 103, 108, 54, 99, 118, 102, 54, 85, 68, 76, 52, 119, 112, 80, 84, 10, 97, 97, 73, 106, 122, 107, 71, 120, 122, 79, 84, 86, 72, 122, 98, 82, 105, 106, 114, 52, 106, 71, 80, 105, 70, 70, 108, 112, 55, 81, 51, 84, 102, 50, 118, 111, 117, 65, 80, 108, 84, 50, 114, 108, 109, 71, 78, 112, 83, 65, 87, 43, 76, 118, 56, 122, 116, 117, 109, 88, 87, 87, 110, 52, 90, 120, 109, 117, 107, 50, 71, 87, 82, 66, 88, 84, 10, 99, 114, 65, 47, 118, 71, 112, 57, 55, 69, 104, 47, 106, 99, 79, 114, 113, 110, 69, 114, 85, 50, 108, 66, 85, 122, 83, 49, 115, 76, 110, 70, 66, 103, 114, 69, 115, 69, 88, 49, 81, 86, 49, 117, 105, 85, 86, 55, 80, 84, 115, 109, 106, 72, 84, 67, 53, 100, 76, 82, 102, 98, 73, 82, 49, 80, 116, 89, 77, 105, 75, 97, 103, 77, 110, 99, 10, 47, 81, 122, 112, 102, 49, 52, 68, 108, 56, 52, 55, 65, 66, 83, 72, 74, 51, 65, 52, 113, 89, 53, 117, 115, 121, 100, 50, 109, 70, 72, 103, 66, 101, 77, 104, 113, 120, 114, 86, 104, 83, 73, 56, 75, 98, 87, 97, 70, 115, 87, 65, 113, 80, 83, 55, 97, 122, 67, 80, 76, 48, 89, 67, 111, 114, 69, 77, 73, 117, 68, 84, 65, 103, 77, 66, 10, 65, 65, 71, 106, 103, 90, 99, 119, 103, 90, 81, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 67, 69, 119, 121, 102, 115, 65, 49, 48, 54, 89, 50, 111, 101, 113, 75, 116, 67, 110, 76, 114, 70, 65, 77, 97, 100, 77, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 80, 10, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 70, 73, 71, 65, 49, 85, 100, 72, 119, 82, 76, 77, 69, 107, 119, 82, 54, 66, 70, 111, 69, 79, 71, 81, 87, 104, 48, 100, 72, 65, 54, 76, 121, 57, 106, 99, 109, 119, 117, 98, 109, 86, 48, 99, 50, 57, 115, 99, 51, 78, 115, 76, 109, 78, 118, 10, 98, 83, 57, 79, 90, 88, 82, 51, 98, 51, 74, 114, 85, 50, 57, 115, 100, 88, 82, 112, 98, 50, 53, 122, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 86, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 117, 89, 51, 74, 115, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 10, 65, 52, 73, 66, 65, 81, 67, 55, 114, 107, 118, 110, 116, 49, 102, 114, 102, 54, 111, 116, 116, 51, 78, 72, 104, 87, 114, 66, 53, 75, 85, 100, 53, 79, 99, 56, 54, 102, 82, 90, 90, 88, 101, 49, 101, 108, 116, 97, 106, 83, 85, 50, 52, 72, 113, 88, 76, 106, 106, 65, 86, 50, 67, 68, 109, 65, 97, 68, 110, 55, 108, 50, 101, 109, 53, 81, 10, 52, 76, 113, 73, 76, 80, 120, 70, 122, 66, 105, 119, 109, 90, 86, 82, 68, 117, 119, 100, 117, 73, 106, 47, 104, 49, 65, 99, 103, 115, 76, 106, 52, 68, 75, 65, 118, 54, 65, 76, 82, 56, 106, 68, 77, 101, 43, 90, 90, 122, 75, 65, 84, 120, 99, 104, 101, 81, 120, 112, 88, 78, 53, 101, 78, 75, 52, 67, 116, 83, 98, 113, 85, 78, 57, 47, 10, 71, 71, 85, 115, 121, 102, 74, 106, 52, 97, 107, 72, 47, 110, 120, 120, 72, 50, 115, 122, 74, 71, 111, 101, 66, 102, 99, 70, 97, 77, 66, 113, 69, 115, 115, 117, 88, 109, 72, 76, 114, 105, 106, 84, 102, 115, 75, 48, 90, 112, 69, 109, 88, 122, 119, 117, 74, 70, 47, 76, 87, 65, 47, 114, 75, 79, 121, 118, 69, 90, 98, 122, 51, 72, 116, 118, 10, 119, 75, 101, 73, 56, 108, 78, 51, 115, 50, 66, 101, 114, 113, 52, 111, 50, 106, 85, 115, 98, 122, 82, 70, 48, 121, 98, 104, 51, 117, 120, 98, 84, 121, 100, 114, 70, 110, 121, 57, 82, 65, 81, 89, 103, 114, 79, 74, 101, 82, 99, 81, 99, 84, 49, 54, 111, 104, 90, 79, 57, 81, 72, 78, 112, 71, 120, 108, 97, 75, 70, 74, 100, 108, 120, 68, 10, 121, 100, 105, 56, 78, 109, 100, 115, 112, 90, 83, 49, 49, 77, 121, 53, 118, 87, 111, 49, 86, 105, 72, 101, 50, 77, 80, 114, 43, 56, 117, 107, 89, 69, 121, 119, 86, 97, 67, 103, 101, 49, 101, 121, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 79, 77, 79, 68, 79, 32, 69, 67, 67, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 105, 84, 67, 67, 65, 103, 43, 103, 65, 119, 73, 66, 65, 103, 73, 81, 72, 48, 101, 118, 113, 109, 73, 65, 99, 70, 66, 85, 84, 65, 71, 101, 109, 50, 79, 90, 75, 106, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 122, 67, 66, 104, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 10, 82, 48, 73, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 103, 84, 69, 107, 100, 121, 90, 87, 70, 48, 90, 88, 73, 103, 84, 87, 70, 117, 89, 50, 104, 108, 99, 51, 82, 108, 99, 106, 69, 81, 77, 65, 52, 71, 65, 49, 85, 69, 66, 120, 77, 72, 85, 50, 70, 115, 90, 109, 57, 121, 90, 68, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 10, 67, 104, 77, 82, 81, 48, 57, 78, 84, 48, 82, 80, 73, 69, 78, 66, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 75, 122, 65, 112, 66, 103, 78, 86, 66, 65, 77, 84, 73, 107, 78, 80, 84, 85, 57, 69, 84, 121, 66, 70, 81, 48, 77, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 10, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 72, 104, 99, 78, 77, 68, 103, 119, 77, 122, 65, 50, 77, 68, 65, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 122, 103, 119, 77, 84, 69, 52, 77, 106, 77, 49, 79, 84, 85, 53, 87, 106, 67, 66, 104, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 48, 73, 120, 10, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 103, 84, 69, 107, 100, 121, 90, 87, 70, 48, 90, 88, 73, 103, 84, 87, 70, 117, 89, 50, 104, 108, 99, 51, 82, 108, 99, 106, 69, 81, 77, 65, 52, 71, 65, 49, 85, 69, 66, 120, 77, 72, 85, 50, 70, 115, 90, 109, 57, 121, 90, 68, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 104, 77, 82, 10, 81, 48, 57, 78, 84, 48, 82, 80, 73, 69, 78, 66, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 75, 122, 65, 112, 66, 103, 78, 86, 66, 65, 77, 84, 73, 107, 78, 80, 84, 85, 57, 69, 84, 121, 66, 70, 81, 48, 77, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 10, 98, 51, 74, 112, 100, 72, 107, 119, 100, 106, 65, 81, 66, 103, 99, 113, 104, 107, 106, 79, 80, 81, 73, 66, 66, 103, 85, 114, 103, 81, 81, 65, 73, 103, 78, 105, 65, 65, 81, 68, 82, 51, 115, 118, 100, 99, 109, 67, 70, 89, 88, 55, 100, 101, 83, 82, 70, 116, 83, 114, 89, 112, 110, 49, 80, 108, 73, 76, 66, 115, 53, 66, 65, 72, 43, 88, 10, 52, 81, 111, 107, 80, 66, 48, 66, 66, 79, 52, 57, 48, 111, 48, 74, 108, 119, 122, 103, 100, 101, 84, 54, 43, 51, 101, 75, 75, 118, 85, 68, 89, 69, 115, 50, 105, 120, 89, 106, 70, 113, 48, 74, 99, 102, 82, 75, 57, 67, 104, 81, 116, 80, 54, 73, 72, 71, 52, 47, 98, 67, 56, 118, 67, 86, 108, 98, 112, 86, 115, 76, 77, 53, 110, 105, 10, 119, 122, 50, 74, 43, 87, 111, 115, 55, 55, 76, 84, 66, 117, 109, 106, 81, 106, 66, 65, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 49, 99, 97, 99, 90, 83, 66, 109, 56, 110, 90, 51, 113, 81, 85, 102, 102, 108, 77, 82, 73, 100, 53, 110, 84, 101, 84, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 10, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 119, 78, 111, 65, 68, 66, 108, 65, 106, 69, 65, 55, 119, 78, 98, 101, 113, 121, 51, 101, 65, 112, 121, 116, 52, 106, 102, 47, 55, 86, 71, 10, 70, 65, 107, 75, 43, 113, 68, 109, 102, 81, 106, 71, 71, 111, 101, 57, 71, 75, 104, 122, 118, 83, 98, 75, 89, 65, 121, 100, 122, 112, 109, 102, 122, 49, 119, 80, 77, 79, 71, 43, 70, 68, 72, 113, 65, 106, 65, 85, 57, 74, 77, 56, 83, 97, 99, 122, 101, 112, 66, 71, 82, 55, 78, 106, 102, 82, 79, 98, 84, 114, 100, 118, 71, 68, 101, 65, 10, 85, 47, 55, 100, 73, 79, 65, 49, 109, 106, 98, 82, 120, 119, 71, 53, 53, 116, 122, 100, 56, 47, 56, 100, 76, 68, 111, 87, 86, 57, 109, 83, 79, 100, 89, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 101, 99, 117, 114, 105, 116, 121, 32, 67, 111, 109, 109, 117, 110, 105, 99, 97, 116, 105, 111, 110, 32, 69, 86, 32, 82, 111, 111, 116, 67, 65, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 102, 84, 67, 67, 65, 109, 87, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 103, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 75, 85, 68, 69, 108, 77, 67, 77, 71, 65, 49, 85, 69, 67, 104, 77, 99, 10, 85, 48, 86, 68, 84, 48, 48, 103, 86, 72, 74, 49, 99, 51, 81, 103, 85, 51, 108, 122, 100, 71, 86, 116, 99, 121, 66, 68, 84, 121, 52, 115, 84, 70, 82, 69, 76, 106, 69, 113, 77, 67, 103, 71, 65, 49, 85, 69, 67, 120, 77, 104, 85, 50, 86, 106, 100, 88, 74, 112, 100, 72, 107, 103, 81, 50, 57, 116, 98, 88, 86, 117, 97, 87, 78, 104, 10, 100, 71, 108, 118, 98, 105, 66, 70, 86, 105, 66, 83, 98, 50, 57, 48, 81, 48, 69, 120, 77, 66, 52, 88, 68, 84, 65, 51, 77, 68, 89, 119, 78, 106, 65, 121, 77, 84, 73, 122, 77, 108, 111, 88, 68, 84, 77, 51, 77, 68, 89, 119, 78, 106, 65, 121, 77, 84, 73, 122, 77, 108, 111, 119, 89, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 83, 108, 65, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 111, 84, 72, 70, 78, 70, 81, 48, 57, 78, 73, 70, 82, 121, 100, 88, 78, 48, 73, 70, 78, 53, 99, 51, 82, 108, 98, 88, 77, 103, 81, 48, 56, 117, 76, 69, 120, 85, 82, 67, 52, 120, 75, 106, 65, 111, 66, 103, 78, 86, 66, 65, 115, 84, 73, 86, 78, 108, 10, 89, 51, 86, 121, 97, 88, 82, 53, 73, 69, 78, 118, 98, 87, 49, 49, 98, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 82, 86, 89, 103, 85, 109, 57, 118, 100, 69, 78, 66, 77, 84, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 10, 65, 81, 111, 67, 103, 103, 69, 66, 65, 76, 120, 47, 55, 70, 101, 98, 74, 79, 68, 43, 110, 76, 112, 67, 101, 97, 109, 73, 105, 118, 113, 65, 52, 80, 85, 72, 75, 85, 80, 113, 106, 103, 111, 48, 78, 111, 48, 99, 43, 113, 101, 49, 79, 88, 106, 47, 108, 51, 88, 51, 76, 43, 83, 113, 97, 119, 83, 69, 82, 77, 113, 109, 52, 109, 105, 79, 10, 47, 86, 86, 81, 89, 103, 43, 107, 99, 81, 55, 79, 66, 122, 103, 116, 81, 111, 86, 81, 114, 84, 121, 87, 98, 52, 118, 86, 111, 103, 55, 80, 51, 107, 109, 74, 80, 100, 90, 107, 76, 106, 106, 108, 72, 109, 121, 49, 86, 52, 113, 101, 55, 48, 103, 79, 122, 88, 112, 112, 70, 111, 100, 69, 116, 90, 68, 107, 66, 112, 50, 117, 111, 81, 83, 88, 10, 87, 72, 110, 118, 73, 69, 113, 67, 97, 52, 119, 105, 118, 43, 119, 102, 68, 43, 109, 69, 99, 101, 51, 120, 68, 117, 83, 52, 71, 66, 80, 77, 86, 106, 90, 100, 48, 90, 111, 101, 85, 87, 115, 53, 98, 109, 66, 50, 105, 68, 81, 76, 56, 55, 80, 82, 115, 74, 51, 75, 89, 101, 74, 107, 72, 99, 70, 71, 66, 55, 104, 106, 51, 82, 52, 122, 10, 90, 98, 79, 79, 67, 86, 86, 83, 80, 98, 87, 57, 47, 119, 102, 114, 114, 87, 70, 86, 71, 67, 121, 112, 97, 90, 104, 75, 113, 107, 68, 70, 77, 120, 82, 108, 100, 65, 68, 53, 107, 100, 54, 118, 65, 48, 106, 70, 81, 70, 84, 99, 68, 52, 83, 81, 97, 67, 68, 70, 107, 112, 98, 99, 76, 117, 85, 67, 82, 97, 114, 65, 88, 49, 84, 52, 10, 98, 101, 112, 74, 122, 49, 49, 115, 83, 54, 47, 118, 109, 115, 74, 87, 88, 77, 89, 49, 86, 107, 74, 113, 77, 70, 47, 67, 113, 47, 98, 105, 80, 84, 43, 122, 121, 82, 71, 80, 77, 85, 122, 88, 110, 48, 107, 67, 65, 119, 69, 65, 65, 97, 78, 67, 77, 69, 65, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 68, 86, 75, 10, 57, 85, 50, 118, 80, 57, 101, 67, 79, 75, 121, 114, 99, 87, 85, 88, 100, 89, 121, 100, 86, 90, 80, 109, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 48, 71, 67, 83, 113, 71, 10, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 66, 65, 81, 67, 111, 104, 43, 110, 115, 43, 69, 66, 110, 88, 99, 80, 66, 90, 115, 100, 65, 83, 53, 102, 56, 104, 120, 79, 81, 87, 115, 84, 118, 111, 77, 112, 102, 105, 55, 101, 110, 116, 47, 72, 87, 116, 87, 83, 51, 105, 114, 79, 52, 71, 56, 122, 97, 43, 54, 120, 109, 10, 105, 69, 72, 79, 54, 80, 122, 107, 50, 120, 54, 73, 112, 117, 48, 110, 85, 66, 115, 67, 77, 67, 82, 71, 101, 102, 52, 69, 104, 51, 67, 88, 81, 72, 80, 82, 119, 77, 70, 88, 71, 90, 112, 112, 112, 83, 101, 90, 113, 53, 49, 105, 104, 80, 90, 82, 119, 83, 122, 74, 73, 120, 88, 89, 75, 76, 101, 114, 74, 82, 79, 49, 82, 117, 71, 71, 10, 65, 118, 56, 109, 106, 77, 83, 73, 107, 104, 49, 87, 47, 104, 108, 110, 56, 108, 88, 107, 103, 75, 78, 114, 110, 75, 116, 51, 52, 86, 70, 120, 68, 83, 68, 98, 69, 74, 114, 98, 118, 88, 90, 53, 66, 51, 101, 90, 75, 75, 50, 97, 88, 116, 113, 120, 84, 48, 81, 115, 78, 89, 54, 108, 108, 115, 102, 57, 103, 47, 66, 89, 120, 110, 110, 87, 10, 109, 72, 121, 111, 106, 102, 54, 71, 80, 103, 99, 87, 107, 117, 70, 55, 53, 120, 51, 115, 77, 51, 90, 43, 81, 105, 53, 75, 104, 102, 109, 82, 105, 87, 105, 69, 65, 52, 71, 108, 109, 53, 113, 43, 52, 122, 102, 70, 86, 75, 116, 87, 79, 120, 103, 116, 81, 97, 81, 77, 43, 69, 76, 98, 109, 97, 68, 103, 99, 109, 43, 55, 88, 101, 69, 87, 10, 84, 49, 77, 75, 90, 80, 108, 79, 57, 76, 57, 79, 86, 76, 49, 52, 98, 73, 106, 113, 118, 53, 119, 84, 74, 77, 74, 119, 97, 97, 74, 47, 68, 56, 103, 56, 114, 81, 106, 74, 115, 74, 104, 65, 111, 121, 114, 110, 105, 73, 80, 116, 100, 52, 57, 48, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 79, 73, 83, 84, 69, 32, 87, 73, 83, 101, 75, 101, 121, 32, 71, 108, 111, 98, 97, 108, 32, 82, 111, 111, 116, 32, 71, 65, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 56, 84, 67, 67, 65, 116, 109, 103, 65, 119, 73, 66, 65, 103, 73, 81, 81, 84, 49, 121, 120, 47, 82, 114, 72, 52, 70, 68, 102, 102, 72, 83, 75, 70, 84, 102, 109, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 66, 105, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 81, 48, 103, 120, 69, 68, 65, 79, 66, 103, 78, 86, 66, 65, 111, 84, 66, 49, 100, 74, 85, 50, 86, 76, 90, 88, 107, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 115, 84, 69, 107, 78, 118, 99, 72, 108, 121, 97, 87, 100, 111, 100, 67, 65, 111, 89, 121, 107, 103, 77, 106, 65, 119, 78, 84, 69, 105, 77, 67, 65, 71, 10, 65, 49, 85, 69, 67, 120, 77, 90, 84, 48, 108, 84, 86, 69, 85, 103, 82, 109, 57, 49, 98, 109, 82, 104, 100, 71, 108, 118, 98, 105, 66, 70, 98, 109, 82, 118, 99, 110, 78, 108, 90, 68, 69, 111, 77, 67, 89, 71, 65, 49, 85, 69, 65, 120, 77, 102, 84, 48, 108, 84, 86, 69, 85, 103, 86, 48, 108, 84, 90, 85, 116, 108, 101, 83, 66, 72, 10, 98, 71, 57, 105, 89, 87, 119, 103, 85, 109, 57, 118, 100, 67, 66, 72, 81, 83, 66, 68, 81, 84, 65, 101, 70, 119, 48, 119, 78, 84, 69, 121, 77, 84, 69, 120, 78, 106, 65, 122, 78, 68, 82, 97, 70, 119, 48, 122, 78, 122, 69, 121, 77, 84, 69, 120, 78, 106, 65, 53, 78, 84, 70, 97, 77, 73, 71, 75, 77, 81, 115, 119, 67, 81, 89, 68, 10, 86, 81, 81, 71, 69, 119, 74, 68, 83, 68, 69, 81, 77, 65, 52, 71, 65, 49, 85, 69, 67, 104, 77, 72, 86, 48, 108, 84, 90, 85, 116, 108, 101, 84, 69, 98, 77, 66, 107, 71, 65, 49, 85, 69, 67, 120, 77, 83, 81, 50, 57, 119, 101, 88, 74, 112, 90, 50, 104, 48, 73, 67, 104, 106, 75, 83, 65, 121, 77, 68, 65, 49, 77, 83, 73, 119, 10, 73, 65, 89, 68, 86, 81, 81, 76, 69, 120, 108, 80, 83, 86, 78, 85, 82, 83, 66, 71, 98, 51, 86, 117, 90, 71, 70, 48, 97, 87, 57, 117, 73, 69, 86, 117, 90, 71, 57, 121, 99, 50, 86, 107, 77, 83, 103, 119, 74, 103, 89, 68, 86, 81, 81, 68, 69, 120, 57, 80, 83, 86, 78, 85, 82, 83, 66, 88, 83, 86, 78, 108, 83, 50, 86, 53, 10, 73, 69, 100, 115, 98, 50, 74, 104, 98, 67, 66, 83, 98, 50, 57, 48, 73, 69, 100, 66, 73, 69, 78, 66, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 121, 48, 43, 122, 65, 74, 115, 57, 10, 78, 116, 51, 53, 48, 85, 108, 113, 97, 120, 66, 74, 72, 43, 122, 89, 75, 55, 76, 71, 43, 68, 75, 66, 75, 85, 79, 86, 84, 74, 111, 90, 73, 121, 69, 86, 82, 100, 55, 106, 121, 66, 120, 82, 86, 86, 117, 117, 107, 43, 103, 51, 47, 121, 116, 114, 54, 100, 84, 113, 118, 105, 114, 100, 113, 70, 69, 114, 49, 50, 98, 68, 89, 86, 120, 103, 10, 65, 115, 106, 49, 122, 110, 74, 55, 79, 55, 106, 121, 84, 109, 85, 73, 109, 115, 50, 107, 97, 104, 110, 66, 65, 98, 116, 122, 112, 116, 102, 50, 119, 57, 51, 78, 118, 75, 83, 76, 116, 90, 108, 104, 117, 65, 71, 105, 111, 57, 82, 78, 49, 65, 85, 57, 107, 97, 51, 52, 116, 65, 104, 120, 90, 75, 57, 119, 56, 82, 120, 114, 102, 118, 98, 68, 10, 100, 53, 48, 107, 99, 51, 118, 107, 68, 73, 122, 104, 50, 84, 98, 104, 109, 89, 115, 70, 109, 81, 118, 116, 82, 84, 69, 74, 121, 115, 73, 65, 50, 47, 100, 121, 111, 74, 97, 113, 108, 89, 102, 81, 106, 115, 101, 50, 89, 88, 77, 78, 100, 109, 97, 77, 51, 66, 117, 48, 89, 54, 75, 102, 102, 53, 77, 84, 77, 80, 71, 104, 74, 57, 118, 90, 10, 47, 121, 120, 86, 105, 74, 71, 103, 52, 69, 56, 72, 115, 67, 104, 87, 106, 66, 103, 98, 108, 48, 83, 79, 105, 100, 51, 103, 70, 50, 55, 110, 75, 117, 43, 80, 79, 81, 111, 120, 104, 73, 76, 89, 81, 66, 82, 74, 76, 110, 112, 66, 53, 75, 102, 43, 52, 50, 84, 77, 119, 86, 108, 120, 83, 121, 119, 104, 112, 49, 116, 57, 52, 66, 51, 82, 10, 76, 111, 71, 98, 119, 57, 104, 111, 57, 55, 50, 87, 71, 54, 120, 119, 115, 82, 89, 85, 67, 57, 116, 103, 117, 83, 89, 66, 66, 81, 73, 68, 65, 81, 65, 66, 111, 49, 69, 119, 84, 122, 65, 76, 66, 103, 78, 86, 72, 81, 56, 69, 66, 65, 77, 67, 65, 89, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 10, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 115, 119, 78, 43, 114, 106, 97, 56, 115, 72, 110, 82, 51, 74, 81, 109, 116, 104, 71, 43, 73, 98, 74, 112, 104, 112, 81, 119, 69, 65, 89, 74, 75, 119, 89, 66, 66, 65, 71, 67, 78, 120, 85, 66, 66, 65, 77, 67, 65, 81, 65, 119, 68, 81, 89, 74, 10, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 69, 117, 104, 47, 119, 117, 72, 98, 114, 80, 53, 119, 85, 79, 120, 83, 80, 77, 111, 119, 66, 48, 117, 121, 81, 108, 66, 43, 112, 81, 65, 72, 75, 83, 107, 113, 48, 108, 80, 106, 122, 48, 101, 55, 48, 49, 118, 118, 98, 121, 107, 57, 118, 73, 109, 10, 77, 77, 107, 81, 121, 104, 50, 73, 43, 51, 81, 90, 72, 52, 86, 70, 118, 98, 66, 115, 85, 102, 107, 50, 102, 116, 118, 49, 84, 68, 73, 54, 81, 85, 57, 98, 82, 56, 47, 111, 67, 121, 50, 50, 120, 66, 109, 100, 100, 77, 86, 72, 120, 106, 116, 113, 68, 54, 119, 85, 50, 122, 122, 48, 99, 53, 121, 112, 66, 100, 56, 65, 51, 72, 82, 52, 10, 43, 118, 103, 49, 89, 70, 107, 67, 69, 120, 104, 56, 118, 80, 116, 78, 115, 67, 66, 116, 81, 55, 116, 103, 77, 72, 112, 110, 77, 49, 122, 70, 109, 100, 72, 52, 76, 84, 108, 83, 99, 47, 117, 77, 113, 112, 99, 108, 88, 72, 76, 90, 67, 66, 54, 114, 84, 106, 122, 106, 103, 84, 71, 102, 65, 54, 98, 55, 119, 80, 52, 112, 105, 70, 88, 97, 10, 104, 78, 86, 81, 65, 55, 98, 105, 104, 75, 79, 109, 78, 113, 111, 82, 79, 103, 72, 104, 71, 69, 118, 87, 82, 71, 105, 122, 80, 102, 108, 84, 100, 73, 83, 122, 82, 112, 70, 71, 108, 103, 67, 51, 103, 67, 121, 50, 52, 101, 77, 81, 52, 116, 117, 105, 53, 121, 105, 80, 65, 90, 90, 105, 70, 106, 52, 65, 52, 120, 121, 108, 78, 111, 69, 89, 10, 111, 107, 120, 83, 100, 115, 65, 82, 111, 50, 55, 109, 72, 98, 114, 106, 87, 114, 52, 50, 85, 56, 85, 43, 100, 89, 43, 71, 97, 83, 108, 89, 85, 55, 87, 99, 117, 50, 43, 102, 88, 77, 85, 89, 55, 78, 48, 118, 52, 90, 106, 74, 47, 76, 55, 102, 67, 103, 48, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 101, 114, 116, 105, 103, 110, 97, 10, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 113, 68, 67, 67, 65, 112, 67, 103, 65, 119, 73, 66, 65, 103, 73, 74, 65, 80, 55, 99, 52, 119, 69, 80, 121, 85, 106, 47, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 77, 68, 81, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 90, 83, 77, 82, 73, 119, 10, 69, 65, 89, 68, 86, 81, 81, 75, 68, 65, 108, 69, 97, 71, 108, 116, 101, 87, 57, 48, 97, 88, 77, 120, 69, 84, 65, 80, 66, 103, 78, 86, 66, 65, 77, 77, 67, 69, 78, 108, 99, 110, 82, 112, 90, 50, 53, 104, 77, 66, 52, 88, 68, 84, 65, 51, 77, 68, 89, 121, 79, 84, 69, 49, 77, 84, 77, 119, 78, 86, 111, 88, 68, 84, 73, 51, 10, 77, 68, 89, 121, 79, 84, 69, 49, 77, 84, 77, 119, 78, 86, 111, 119, 78, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 108, 73, 120, 69, 106, 65, 81, 66, 103, 78, 86, 66, 65, 111, 77, 67, 85, 82, 111, 97, 87, 49, 53, 98, 51, 82, 112, 99, 122, 69, 82, 77, 65, 56, 71, 65, 49, 85, 69, 65, 119, 119, 73, 10, 81, 50, 86, 121, 100, 71, 108, 110, 98, 109, 69, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 68, 73, 97, 80, 72, 74, 49, 116, 97, 122, 78, 72, 85, 109, 103, 104, 55, 115, 116, 76, 55, 113, 10, 88, 79, 69, 109, 55, 82, 70, 72, 89, 101, 71, 105, 102, 66, 90, 52, 81, 67, 72, 107, 89, 74, 53, 97, 121, 71, 80, 104, 120, 76, 71, 87, 107, 118, 56, 89, 98, 87, 107, 106, 52, 83, 116, 105, 57, 57, 51, 105, 78, 105, 43, 82, 66, 55, 108, 73, 122, 119, 55, 115, 101, 98, 89, 115, 53, 122, 82, 76, 99, 65, 103, 108, 111, 122, 121, 72, 10, 71, 120, 110, 121, 103, 81, 99, 80, 79, 74, 65, 90, 48, 120, 72, 43, 104, 114, 84, 121, 48, 86, 52, 101, 72, 112, 98, 78, 103, 71, 122, 79, 79, 122, 71, 84, 116, 118, 75, 103, 48, 75, 109, 86, 69, 110, 50, 108, 109, 115, 120, 114, 121, 73, 82, 87, 105, 106, 79, 112, 53, 121, 73, 86, 85, 120, 98, 119, 122, 66, 102, 115, 86, 49, 47, 112, 10, 111, 103, 113, 89, 67, 100, 55, 106, 88, 53, 120, 118, 51, 69, 106, 106, 104, 81, 115, 86, 87, 113, 97, 54, 110, 54, 120, 73, 52, 119, 109, 121, 57, 47, 81, 121, 51, 108, 52, 48, 118, 104, 120, 52, 88, 85, 74, 98, 122, 103, 52, 105, 106, 48, 50, 81, 49, 51, 48, 121, 71, 76, 77, 76, 76, 71, 113, 47, 106, 106, 56, 85, 69, 89, 107, 103, 10, 68, 110, 99, 85, 116, 84, 50, 85, 67, 73, 102, 51, 74, 82, 55, 86, 115, 109, 65, 65, 55, 71, 56, 113, 75, 67, 86, 117, 75, 106, 52, 89, 89, 120, 99, 108, 80, 122, 53, 69, 73, 66, 98, 50, 74, 115, 103, 108, 114, 103, 86, 75, 116, 79, 100, 106, 76, 80, 79, 77, 70, 108, 78, 43, 88, 80, 115, 82, 71, 103, 106, 66, 82, 109, 75, 102, 10, 73, 114, 106, 120, 119, 111, 49, 112, 51, 80, 111, 54, 87, 65, 98, 102, 65, 103, 77, 66, 65, 65, 71, 106, 103, 98, 119, 119, 103, 98, 107, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 71, 117, 51, 43, 81, 84, 109, 81, 10, 116, 67, 82, 90, 118, 103, 72, 121, 85, 116, 86, 70, 57, 108, 111, 53, 51, 66, 69, 119, 90, 65, 89, 68, 86, 82, 48, 106, 66, 70, 48, 119, 87, 52, 65, 85, 71, 117, 51, 43, 81, 84, 109, 81, 116, 67, 82, 90, 118, 103, 72, 121, 85, 116, 86, 70, 57, 108, 111, 53, 51, 66, 71, 104, 79, 75, 81, 50, 77, 68, 81, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 90, 83, 77, 82, 73, 119, 69, 65, 89, 68, 86, 81, 81, 75, 68, 65, 108, 69, 97, 71, 108, 116, 101, 87, 57, 48, 97, 88, 77, 120, 69, 84, 65, 80, 66, 103, 78, 86, 66, 65, 77, 77, 67, 69, 78, 108, 99, 110, 82, 112, 90, 50, 53, 104, 103, 103, 107, 65, 47, 116, 122, 106, 65, 81, 47, 74, 10, 83, 80, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 69, 71, 67, 87, 67, 71, 83, 65, 71, 71, 43, 69, 73, 66, 65, 81, 81, 69, 65, 119, 73, 65, 66, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 10, 104, 81, 77, 101, 107, 110, 72, 50, 81, 113, 47, 104, 111, 50, 71, 101, 54, 47, 80, 65, 68, 47, 75, 108, 49, 78, 113, 86, 53, 116, 97, 43, 97, 68, 89, 57, 102, 109, 52, 102, 84, 73, 114, 118, 48, 81, 56, 104, 98, 86, 54, 108, 85, 109, 80, 79, 69, 118, 106, 118, 75, 116, 112, 118, 54, 122, 102, 43, 69, 119, 76, 72, 121, 122, 115, 43, 10, 73, 109, 118, 97, 89, 83, 53, 47, 49, 72, 73, 57, 51, 84, 68, 104, 72, 107, 120, 65, 71, 89, 119, 80, 49, 53, 122, 82, 103, 122, 66, 55, 109, 70, 110, 99, 102, 99, 97, 53, 68, 67, 108, 77, 111, 84, 79, 105, 54, 50, 99, 54, 90, 89, 84, 84, 108, 117, 76, 116, 100, 107, 86, 119, 106, 55, 85, 114, 51, 118, 107, 106, 49, 107, 108, 117, 10, 80, 66, 83, 49, 120, 112, 56, 49, 72, 108, 68, 81, 119, 89, 57, 113, 99, 69, 81, 67, 89, 115, 117, 117, 72, 87, 104, 66, 112, 54, 112, 88, 54, 70, 79, 113, 66, 57, 73, 71, 57, 116, 85, 85, 66, 103, 117, 82, 65, 51, 85, 115, 98, 72, 75, 49, 89, 90, 87, 97, 68, 89, 117, 53, 68, 101, 102, 49, 51, 49, 84, 78, 51, 117, 98, 89, 10, 49, 103, 107, 73, 108, 50, 80, 108, 119, 83, 54, 119, 116, 48, 81, 109, 119, 67, 98, 65, 114, 49, 85, 119, 110, 106, 118, 86, 78, 105, 111, 90, 66, 80, 82, 99, 72, 118, 47, 80, 76, 76, 102, 47, 48, 80, 50, 72, 81, 66, 72, 86, 69, 83, 79, 55, 83, 77, 65, 104, 113, 97, 81, 111, 76, 102, 48, 86, 43, 76, 66, 79, 75, 47, 81, 119, 10, 87, 121, 72, 56, 69, 90, 69, 48, 118, 107, 72, 118, 101, 53, 50, 88, 100, 102, 43, 88, 108, 99, 67, 87, 87, 67, 47, 113, 117, 48, 98, 88, 117, 43, 84, 90, 76, 103, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 101, 117, 116, 115, 99, 104, 101, 32, 84, 101, 108, 101, 107, 111, 109, 32, 82, 111, 111, 116, 32, 67, 65, 32, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 110, 122, 67, 67, 65, 111, 101, 103, 65, 119, 73, 66, 65, 103, 73, 66, 74, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 120, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 69, 82, 84, 69, 99, 77, 66, 111, 71, 65, 49, 85, 69, 67, 104, 77, 84, 10, 82, 71, 86, 49, 100, 72, 78, 106, 97, 71, 85, 103, 86, 71, 86, 115, 90, 87, 116, 118, 98, 83, 66, 66, 82, 122, 69, 102, 77, 66, 48, 71, 65, 49, 85, 69, 67, 120, 77, 87, 86, 67, 49, 85, 90, 87, 120, 108, 85, 50, 86, 106, 73, 70, 82, 121, 100, 88, 78, 48, 73, 69, 78, 108, 98, 110, 82, 108, 99, 106, 69, 106, 77, 67, 69, 71, 10, 65, 49, 85, 69, 65, 120, 77, 97, 82, 71, 86, 49, 100, 72, 78, 106, 97, 71, 85, 103, 86, 71, 86, 115, 90, 87, 116, 118, 98, 83, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 68, 73, 119, 72, 104, 99, 78, 79, 84, 107, 119, 78, 122, 65, 53, 77, 84, 73, 120, 77, 84, 65, 119, 87, 104, 99, 78, 77, 84, 107, 119, 78, 122, 65, 53, 10, 77, 106, 77, 49, 79, 84, 65, 119, 87, 106, 66, 120, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 69, 82, 84, 69, 99, 77, 66, 111, 71, 65, 49, 85, 69, 67, 104, 77, 84, 82, 71, 86, 49, 100, 72, 78, 106, 97, 71, 85, 103, 86, 71, 86, 115, 90, 87, 116, 118, 98, 83, 66, 66, 82, 122, 69, 102, 77, 66, 48, 71, 10, 65, 49, 85, 69, 67, 120, 77, 87, 86, 67, 49, 85, 90, 87, 120, 108, 85, 50, 86, 106, 73, 70, 82, 121, 100, 88, 78, 48, 73, 69, 78, 108, 98, 110, 82, 108, 99, 106, 69, 106, 77, 67, 69, 71, 65, 49, 85, 69, 65, 120, 77, 97, 82, 71, 86, 49, 100, 72, 78, 106, 97, 71, 85, 103, 86, 71, 86, 115, 90, 87, 116, 118, 98, 83, 66, 83, 10, 98, 50, 57, 48, 73, 69, 78, 66, 73, 68, 73, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 114, 67, 54, 77, 49, 52, 73, 115, 112, 70, 76, 69, 85, 104, 97, 56, 56, 69, 79, 81, 53, 10, 98, 122, 86, 100, 83, 113, 55, 100, 54, 109, 71, 78, 108, 85, 110, 48, 98, 50, 83, 106, 71, 109, 66, 109, 112, 75, 108, 65, 73, 111, 84, 90, 49, 75, 88, 108, 101, 74, 77, 79, 97, 65, 71, 116, 117, 85, 49, 99, 79, 115, 55, 84, 117, 75, 104, 67, 81, 78, 47, 80, 111, 55, 113, 67, 87, 87, 113, 83, 71, 54, 119, 99, 109, 116, 111, 73, 10, 75, 121, 85, 110, 43, 87, 107, 106, 82, 47, 72, 103, 54, 121, 120, 54, 109, 47, 85, 84, 65, 116, 66, 43, 78, 72, 122, 67, 110, 106, 119, 65, 87, 97, 118, 49, 50, 103, 122, 49, 77, 106, 119, 114, 114, 70, 68, 97, 49, 115, 80, 101, 103, 53, 84, 75, 113, 65, 121, 90, 77, 103, 52, 73, 83, 70, 90, 98, 97, 118, 118, 97, 52, 86, 104, 89, 10, 65, 85, 108, 102, 99, 107, 69, 56, 70, 81, 89, 66, 106, 108, 50, 116, 113, 114, 105, 84, 116, 77, 50, 101, 54, 54, 102, 111, 97, 105, 49, 83, 78, 78, 115, 54, 55, 49, 120, 49, 85, 100, 114, 98, 56, 122, 72, 53, 55, 110, 71, 89, 77, 115, 82, 85, 70, 85, 81, 77, 43, 90, 116, 86, 55, 97, 51, 102, 71, 65, 105, 103, 111, 52, 97, 75, 10, 83, 101, 53, 84, 66, 89, 56, 90, 84, 78, 88, 101, 87, 72, 109, 98, 48, 109, 111, 99, 81, 113, 118, 70, 49, 97, 102, 80, 97, 65, 43, 87, 53, 79, 70, 104, 109, 72, 90, 104, 121, 74, 70, 56, 49, 106, 52, 65, 52, 112, 70, 81, 104, 43, 71, 100, 67, 117, 97, 116, 108, 57, 73, 100, 120, 106, 112, 57, 121, 55, 122, 97, 65, 122, 84, 86, 10, 106, 108, 115, 66, 57, 87, 111, 72, 116, 120, 97, 50, 98, 107, 112, 47, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 81, 120, 119, 51, 107, 98, 117, 118, 86, 84, 49, 120, 102, 103, 105, 88, 111, 116, 70, 50, 119, 75, 115, 121, 117, 100, 77, 122, 65, 80, 66, 103, 78, 86, 10, 72, 82, 77, 69, 67, 68, 65, 71, 65, 81, 72, 47, 65, 103, 69, 70, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 108, 71, 82, 90, 114, 84, 108, 107, 53, 121, 110, 114, 10, 69, 47, 53, 97, 119, 52, 115, 84, 86, 56, 103, 69, 74, 80, 66, 48, 100, 56, 66, 103, 52, 50, 102, 55, 54, 89, 109, 109, 103, 55, 43, 87, 103, 110, 120, 117, 49, 77, 77, 57, 55, 53, 54, 65, 98, 114, 115, 112, 116, 74, 104, 54, 115, 84, 116, 85, 54, 122, 107, 88, 82, 51, 52, 97, 106, 103, 118, 56, 72, 122, 70, 90, 77, 81, 83, 121, 10, 122, 104, 102, 122, 76, 77, 100, 105, 78, 108, 88, 105, 73, 116, 105, 74, 86, 98, 83, 89, 83, 75, 112, 107, 43, 116, 89, 99, 78, 116, 104, 69, 101, 70, 112, 97, 73, 122, 112, 88, 108, 47, 86, 54, 77, 69, 43, 117, 110, 50, 112, 77, 83, 121, 117, 79, 111, 65, 80, 106, 80, 117, 67, 112, 49, 78, 74, 55, 48, 114, 79, 111, 52, 110, 73, 56, 10, 114, 90, 55, 47, 103, 70, 110, 107, 109, 48, 87, 48, 57, 106, 117, 119, 122, 84, 107, 90, 109, 68, 76, 108, 54, 105, 70, 104, 107, 79, 81, 120, 73, 89, 52, 48, 115, 102, 99, 118, 78, 85, 113, 70, 69, 78, 114, 110, 105, 106, 99, 104, 118, 108, 108, 106, 52, 80, 75, 70, 105, 68, 70, 84, 49, 70, 81, 85, 104, 88, 66, 53, 57, 67, 52, 71, 10, 100, 121, 100, 49, 76, 120, 43, 52, 105, 118, 110, 43, 120, 98, 114, 89, 78, 117, 83, 68, 55, 79, 100, 108, 116, 55, 57, 106, 87, 118, 78, 71, 114, 52, 71, 85, 78, 57, 82, 66, 106, 78, 89, 106, 49, 104, 55, 80, 57, 87, 103, 98, 82, 71, 79, 105, 87, 114, 113, 110, 78, 86, 109, 104, 53, 88, 65, 70, 109, 119, 52, 106, 86, 53, 109, 85, 10, 67, 109, 50, 54, 79, 87, 77, 111, 104, 112, 76, 122, 71, 73, 84, 89, 43, 57, 72, 80, 66, 86, 90, 107, 86, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 121, 98, 101, 114, 116, 114, 117, 115, 116, 32, 71, 108, 111, 98, 97, 108, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 111, 84, 67, 67, 65, 111, 109, 103, 65, 119, 73, 66, 65, 103, 73, 76, 66, 65, 65, 65, 65, 65, 65, 66, 68, 52, 87, 113, 76, 85, 103, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 79, 122, 69, 89, 77, 66, 89, 71, 65, 49, 85, 69, 67, 104, 77, 80, 81, 51, 108, 105, 10, 90, 88, 74, 48, 99, 110, 86, 122, 100, 67, 119, 103, 83, 87, 53, 106, 77, 82, 56, 119, 72, 81, 89, 68, 86, 81, 81, 68, 69, 120, 90, 68, 101, 87, 74, 108, 99, 110, 82, 121, 100, 88, 78, 48, 73, 69, 100, 115, 98, 50, 74, 104, 98, 67, 66, 83, 98, 50, 57, 48, 77, 66, 52, 88, 68, 84, 65, 50, 77, 84, 73, 120, 78, 84, 65, 52, 10, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 73, 120, 77, 84, 73, 120, 78, 84, 65, 52, 77, 68, 65, 119, 77, 70, 111, 119, 79, 122, 69, 89, 77, 66, 89, 71, 65, 49, 85, 69, 67, 104, 77, 80, 81, 51, 108, 105, 90, 88, 74, 48, 99, 110, 86, 122, 100, 67, 119, 103, 83, 87, 53, 106, 77, 82, 56, 119, 72, 81, 89, 68, 86, 81, 81, 68, 10, 69, 120, 90, 68, 101, 87, 74, 108, 99, 110, 82, 121, 100, 88, 78, 48, 73, 69, 100, 115, 98, 50, 74, 104, 98, 67, 66, 83, 98, 50, 57, 48, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 10, 43, 77, 105, 56, 118, 82, 82, 81, 90, 104, 80, 47, 56, 78, 78, 53, 55, 67, 80, 121, 116, 120, 114, 72, 106, 111, 88, 120, 69, 110, 79, 109, 71, 97, 111, 81, 50, 53, 121, 105, 90, 88, 82, 97, 100, 122, 53, 82, 102, 86, 98, 50, 51, 67, 79, 50, 49, 79, 49, 102, 87, 76, 69, 51, 84, 100, 86, 74, 68, 109, 55, 49, 97, 111, 102, 87, 10, 48, 111, 122, 83, 74, 56, 98, 105, 47, 122, 97, 102, 109, 71, 87, 103, 69, 48, 55, 71, 75, 109, 83, 98, 49, 90, 65, 83, 122, 120, 81, 71, 57, 68, 118, 106, 49, 67, 105, 43, 54, 65, 55, 52, 113, 48, 53, 73, 108, 71, 50, 79, 108, 84, 69, 81, 88, 79, 50, 105, 76, 98, 51, 86, 79, 109, 50, 121, 72, 76, 116, 103, 119, 69, 90, 76, 10, 65, 102, 86, 74, 114, 110, 53, 71, 105, 116, 66, 48, 106, 97, 69, 77, 65, 115, 55, 117, 47, 79, 101, 80, 117, 71, 116, 109, 56, 51, 57, 69, 65, 76, 57, 109, 74, 82, 81, 114, 51, 82, 65, 119, 72, 81, 101, 87, 80, 48, 51, 50, 97, 55, 105, 80, 116, 51, 115, 77, 112, 84, 106, 114, 51, 107, 102, 98, 49, 86, 48, 53, 47, 73, 105, 110, 10, 56, 57, 99, 113, 100, 80, 72, 111, 87, 113, 73, 55, 110, 49, 67, 54, 112, 111, 120, 70, 78, 99, 74, 81, 90, 90, 88, 99, 89, 52, 76, 118, 51, 98, 57, 51, 84, 90, 120, 105, 121, 87, 78, 122, 70, 116, 65, 112, 68, 48, 109, 112, 83, 80, 67, 122, 113, 114, 100, 115, 120, 97, 99, 119, 79, 85, 66, 100, 114, 115, 84, 105, 88, 83, 90, 84, 10, 56, 77, 52, 99, 73, 119, 104, 104, 113, 74, 81, 90, 117, 103, 82, 105, 81, 79, 119, 102, 79, 72, 66, 51, 69, 103, 90, 120, 112, 122, 65, 89, 88, 83, 85, 110, 112, 81, 73, 68, 65, 81, 65, 66, 111, 52, 71, 108, 77, 73, 71, 105, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 80, 10, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 83, 50, 67, 72, 115, 78, 101, 115, 121, 115, 73, 69, 121, 71, 86, 106, 74, 101, 122, 54, 116, 117, 104, 83, 49, 119, 86, 122, 65, 47, 66, 103, 78, 86, 72, 82, 56, 69, 79, 68, 65, 50, 10, 77, 68, 83, 103, 77, 113, 65, 119, 104, 105, 53, 111, 100, 72, 82, 119, 79, 105, 56, 118, 100, 51, 100, 51, 77, 105, 53, 119, 100, 87, 74, 115, 97, 87, 77, 116, 100, 72, 74, 49, 99, 51, 81, 117, 89, 50, 57, 116, 76, 50, 78, 121, 98, 67, 57, 106, 100, 67, 57, 106, 100, 72, 74, 118, 98, 51, 81, 117, 89, 51, 74, 115, 77, 66, 56, 71, 10, 65, 49, 85, 100, 73, 119, 81, 89, 77, 66, 97, 65, 70, 76, 89, 73, 101, 119, 49, 54, 122, 75, 119, 103, 84, 73, 90, 87, 77, 108, 55, 80, 113, 50, 54, 70, 76, 88, 66, 88, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 66, 65, 81, 66, 87, 55, 119, 111, 106, 111, 70, 82, 79, 10, 108, 90, 102, 74, 43, 73, 110, 97, 82, 99, 72, 85, 111, 119, 65, 108, 57, 66, 56, 84, 113, 55, 101, 106, 104, 86, 104, 112, 119, 106, 67, 116, 50, 66, 87, 75, 76, 101, 80, 74, 122, 89, 70, 97, 43, 72, 77, 106, 87, 113, 100, 56, 66, 102, 80, 57, 73, 106, 115, 79, 48, 81, 98, 69, 50, 122, 90, 77, 99, 119, 83, 79, 53, 98, 65, 105, 10, 53, 77, 88, 122, 76, 113, 88, 90, 73, 43, 79, 52, 84, 107, 111, 103, 112, 50, 52, 67, 74, 74, 56, 105, 89, 71, 100, 55, 105, 120, 49, 121, 67, 99, 85, 120, 88, 79, 108, 53, 110, 52, 66, 72, 80, 97, 50, 104, 67, 119, 99, 85, 80, 85, 102, 47, 65, 50, 107, 97, 68, 65, 116, 69, 53, 50, 77, 108, 112, 51, 43, 121, 121, 98, 104, 50, 10, 104, 79, 48, 106, 57, 110, 48, 72, 113, 48, 86, 43, 48, 57, 43, 122, 118, 43, 109, 75, 116, 115, 50, 111, 111, 109, 99, 114, 85, 116, 87, 51, 90, 102, 65, 53, 84, 71, 79, 103, 107, 88, 109, 84, 85, 103, 57, 85, 51, 89, 79, 55, 110, 57, 71, 80, 112, 49, 78, 122, 119, 56, 118, 47, 77, 79, 120, 56, 66, 76, 106, 89, 82, 66, 43, 84, 10, 88, 51, 69, 74, 73, 114, 100, 117, 80, 117, 111, 99, 65, 48, 54, 100, 71, 105, 66, 104, 43, 52, 69, 51, 55, 70, 55, 56, 67, 107, 87, 114, 49, 43, 99, 88, 86, 100, 67, 103, 54, 109, 67, 98, 112, 118, 98, 106, 106, 70, 115, 112, 119, 103, 90, 103, 70, 74, 48, 116, 108, 48, 121, 112, 107, 120, 87, 100, 89, 99, 81, 66, 88, 48, 106, 87, 10, 87, 76, 49, 87, 77, 82, 74, 79, 69, 99, 103, 104, 52, 76, 77, 82, 107, 87, 88, 98, 116, 75, 97, 73, 79, 77, 53, 86, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 101, 80, 75, 73, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 115, 68, 67, 67, 65, 53, 105, 103, 65, 119, 73, 66, 65, 103, 73, 81, 70, 99, 105, 57, 90, 85, 100, 99, 114, 55, 105, 88, 65, 70, 55, 107, 66, 116, 75, 56, 110, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 101, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 85, 86, 122, 69, 106, 77, 67, 69, 71, 65, 49, 85, 69, 67, 103, 119, 97, 81, 50, 104, 49, 98, 109, 100, 111, 100, 50, 69, 103, 86, 71, 86, 115, 90, 87, 78, 118, 98, 83, 66, 68, 98, 121, 52, 115, 73, 69, 120, 48, 90, 67, 52, 120, 75, 106, 65, 111, 66, 103, 78, 86, 66, 65, 115, 77, 73, 87, 86, 81, 83, 48, 107, 103, 10, 85, 109, 57, 118, 100, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 84, 65, 101, 70, 119, 48, 119, 78, 68, 69, 121, 77, 106, 65, 119, 77, 106, 77, 120, 77, 106, 100, 97, 70, 119, 48, 122, 78, 68, 69, 121, 77, 106, 65, 119, 77, 106, 77, 120, 10, 77, 106, 100, 97, 77, 70, 52, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 82, 88, 77, 83, 77, 119, 73, 81, 89, 68, 86, 81, 81, 75, 68, 66, 112, 68, 97, 72, 86, 117, 90, 50, 104, 51, 89, 83, 66, 85, 90, 87, 120, 108, 89, 50, 57, 116, 73, 69, 78, 118, 76, 105, 119, 103, 84, 72, 82, 107, 76, 106, 69, 113, 10, 77, 67, 103, 71, 65, 49, 85, 69, 67, 119, 119, 104, 90, 86, 66, 76, 83, 83, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 73, 73, 67, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 10, 65, 81, 69, 70, 65, 65, 79, 67, 65, 103, 56, 65, 77, 73, 73, 67, 67, 103, 75, 67, 65, 103, 69, 65, 52, 83, 85, 80, 55, 111, 51, 98, 105, 68, 78, 49, 90, 56, 50, 116, 72, 51, 48, 54, 84, 109, 50, 100, 48, 121, 56, 85, 56, 50, 78, 48, 121, 119, 69, 104, 97, 106, 102, 113, 104, 70, 65, 72, 83, 121, 90, 98, 67, 85, 78, 115, 10, 73, 90, 53, 113, 121, 78, 85, 68, 57, 87, 66, 112, 106, 56, 122, 119, 73, 117, 81, 102, 53, 47, 100, 113, 73, 106, 71, 51, 76, 66, 88, 121, 52, 80, 52, 65, 97, 107, 80, 47, 104, 50, 88, 71, 116, 82, 114, 66, 112, 48, 120, 116, 73, 110, 65, 104, 105, 106, 72, 121, 108, 51, 83, 74, 67, 82, 73, 109, 72, 74, 55, 75, 50, 82, 75, 105, 10, 108, 84, 122, 97, 54, 87, 101, 47, 67, 75, 66, 107, 52, 57, 90, 67, 116, 48, 88, 118, 108, 47, 84, 50, 57, 100, 101, 49, 83, 104, 85, 67, 87, 72, 50, 89, 87, 69, 116, 103, 118, 77, 51, 88, 68, 90, 111, 84, 77, 49, 80, 82, 89, 102, 108, 54, 49, 100, 100, 52, 115, 53, 111, 122, 57, 119, 67, 71, 122, 104, 49, 78, 108, 68, 105, 118, 10, 113, 79, 120, 52, 85, 88, 67, 75, 88, 66, 67, 68, 85, 83, 72, 51, 69, 84, 48, 48, 104, 108, 55, 108, 83, 77, 50, 88, 103, 89, 73, 49, 84, 66, 110, 115, 90, 102, 90, 114, 120, 81, 87, 104, 55, 107, 99, 84, 49, 114, 77, 104, 74, 53, 81, 81, 67, 116, 107, 107, 79, 55, 113, 43, 82, 66, 78, 71, 77, 68, 43, 88, 80, 78, 106, 88, 10, 49, 50, 114, 117, 79, 122, 106, 106, 75, 57, 83, 88, 68, 114, 107, 98, 53, 119, 100, 74, 102, 122, 99, 113, 43, 88, 100, 52, 122, 49, 84, 116, 87, 48, 97, 100, 111, 52, 65, 79, 107, 85, 80, 66, 49, 108, 116, 102, 70, 76, 113, 102, 112, 111, 48, 107, 82, 48, 66, 90, 118, 51, 73, 52, 115, 106, 90, 115, 78, 47, 43, 90, 48, 86, 48, 79, 10, 87, 81, 113, 114, 97, 102, 102, 65, 115, 103, 82, 70, 101, 108, 81, 65, 114, 114, 53, 84, 57, 114, 88, 110, 52, 102, 103, 56, 111, 122, 72, 83, 113, 102, 52, 104, 85, 109, 84, 70, 112, 109, 102, 119, 100, 81, 99, 71, 108, 66, 83, 66, 86, 99, 89, 110, 53, 65, 71, 80, 70, 56, 70, 113, 99, 100, 101, 43, 83, 47, 117, 85, 87, 72, 49, 43, 10, 69, 84, 79, 120, 81, 118, 100, 105, 98, 66, 106, 87, 122, 119, 108, 111, 80, 110, 57, 115, 57, 104, 54, 80, 89, 113, 50, 108, 89, 57, 115, 74, 112, 120, 56, 105, 81, 107, 69, 101, 98, 53, 109, 75, 80, 116, 102, 53, 80, 48, 66, 54, 101, 98, 67, 108, 65, 90, 76, 83, 110, 84, 48, 73, 70, 97, 85, 81, 65, 83, 50, 122, 77, 110, 97, 111, 10, 108, 81, 50, 122, 101, 112, 114, 55, 66, 120, 66, 52, 69, 87, 47, 104, 106, 56, 101, 54, 68, 121, 85, 97, 100, 67, 114, 108, 72, 74, 104, 66, 109, 100, 56, 104, 104, 43, 105, 86, 66, 109, 111, 75, 115, 50, 112, 72, 100, 109, 88, 50, 79, 115, 43, 80, 89, 104, 99, 90, 101, 119, 111, 111, 122, 82, 114, 83, 103, 120, 52, 104, 120, 121, 121, 47, 10, 118, 118, 57, 104, 97, 76, 100, 110, 71, 55, 116, 52, 84, 89, 51, 79, 90, 43, 88, 107, 119, 89, 54, 51, 73, 50, 98, 105, 110, 90, 66, 49, 78, 74, 105, 112, 78, 105, 117, 75, 109, 112, 83, 53, 110, 101, 122, 77, 105, 114, 72, 52, 74, 89, 108, 99, 87, 114, 89, 118, 106, 66, 57, 116, 101, 83, 83, 110, 85, 109, 106, 68, 104, 68, 88, 105, 10, 90, 111, 49, 106, 68, 105, 86, 78, 49, 82, 109, 121, 53, 110, 107, 51, 112, 121, 75, 100, 86, 68, 69, 67, 65, 119, 69, 65, 65, 97, 78, 113, 77, 71, 103, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 66, 52, 77, 57, 55, 90, 110, 56, 117, 71, 83, 74, 103, 108, 70, 119, 70, 85, 53, 76, 110, 99, 47, 81, 107, 113, 105, 10, 77, 65, 119, 71, 65, 49, 85, 100, 69, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 79, 81, 89, 69, 90, 121, 111, 72, 65, 65, 81, 120, 77, 67, 56, 119, 76, 81, 73, 66, 65, 68, 65, 74, 66, 103, 85, 114, 68, 103, 77, 67, 71, 103, 85, 65, 77, 65, 99, 71, 66, 87, 99, 113, 65, 119, 65, 65, 66, 66, 82, 70, 115, 77, 76, 72, 10, 67, 108, 90, 56, 55, 108, 116, 52, 68, 74, 88, 53, 71, 70, 80, 66, 112, 104, 122, 89, 69, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 103, 69, 65, 67, 98, 79, 68, 85, 49, 107, 66, 80, 112, 86, 74, 117, 102, 71, 66, 117, 118, 108, 50, 73, 67, 79, 49, 74, 50, 66, 48, 10, 49, 71, 113, 90, 78, 70, 53, 115, 65, 70, 80, 90, 110, 47, 75, 109, 115, 83, 81, 72, 82, 71, 111, 113, 120, 113, 87, 79, 101, 66, 76, 111, 82, 57, 108, 89, 71, 120, 77, 113, 88, 110, 109, 98, 110, 119, 111, 113, 90, 54, 89, 108, 80, 119, 90, 112, 86, 110, 80, 68, 105, 109, 90, 73, 43, 121, 109, 66, 86, 51, 81, 71, 121, 112, 122, 113, 10, 75, 79, 103, 52, 90, 121, 89, 114, 56, 100, 87, 49, 80, 50, 87, 84, 43, 68, 90, 100, 106, 111, 50, 78, 81, 67, 67, 72, 71, 101, 114, 118, 74, 56, 65, 57, 116, 68, 107, 80, 74, 88, 116, 111, 85, 72, 82, 86, 110, 65, 120, 90, 102, 86, 111, 57, 81, 90, 81, 108, 85, 103, 106, 103, 82, 121, 119, 86, 77, 82, 110, 86, 118, 119, 100, 86, 10, 120, 114, 115, 83, 116, 90, 102, 48, 88, 52, 79, 70, 117, 110, 72, 66, 50, 87, 121, 66, 69, 88, 89, 75, 67, 114, 67, 47, 103, 112, 102, 51, 54, 106, 51, 54, 43, 117, 119, 116, 113, 83, 105, 85, 79, 49, 98, 100, 48, 108, 69, 117, 114, 115, 67, 57, 67, 66, 87, 77, 100, 49, 73, 48, 108, 116, 97, 98, 114, 78, 77, 100, 106, 109, 69, 80, 10, 78, 88, 117, 98, 114, 106, 108, 112, 67, 50, 74, 103, 81, 67, 65, 50, 106, 54, 47, 55, 78, 117, 52, 116, 67, 69, 111, 100, 117, 76, 43, 98, 88, 80, 106, 113, 112, 82, 117, 103, 99, 54, 98, 89, 43, 71, 55, 103, 77, 119, 82, 102, 97, 75, 111, 110, 104, 43, 51, 90, 119, 90, 67, 99, 55, 98, 51, 106, 97, 106, 87, 118, 89, 57, 43, 114, 10, 71, 78, 109, 54, 53, 117, 108, 75, 54, 108, 67, 75, 68, 50, 71, 84, 72, 117, 73, 116, 71, 101, 73, 119, 108, 68, 87, 83, 88, 81, 54, 50, 66, 54, 56, 90, 103, 73, 57, 72, 107, 70, 70, 76, 76, 107, 51, 100, 104, 101, 76, 83, 67, 108, 73, 75, 70, 53, 114, 56, 71, 114, 66, 81, 65, 117, 85, 66, 111, 50, 77, 51, 73, 85, 120, 69, 10, 120, 74, 116, 82, 109, 82, 69, 79, 99, 53, 119, 71, 106, 49, 81, 117, 112, 121, 104, 101, 82, 68, 109, 72, 86, 105, 48, 51, 118, 89, 86, 69, 108, 79, 69, 77, 83, 121, 121, 99, 119, 53, 75, 70, 78, 71, 72, 76, 68, 55, 105, 98, 83, 107, 78, 83, 47, 106, 81, 54, 102, 98, 106, 112, 75, 100, 120, 50, 113, 99, 103, 119, 43, 66, 82, 120, 10, 103, 77, 89, 101, 78, 107, 104, 48, 73, 107, 70, 99, 104, 52, 76, 111, 71, 72, 71, 76, 81, 89, 108, 69, 53, 51, 53, 89, 87, 54, 105, 52, 106, 82, 80, 112, 112, 50, 122, 68, 82, 43, 50, 122, 71, 112, 49, 105, 114, 111, 50, 67, 54, 112, 83, 101, 51, 86, 107, 81, 119, 54, 51, 100, 52, 107, 51, 106, 77, 100, 88, 72, 55, 79, 106, 121, 10, 115, 80, 54, 83, 72, 104, 89, 75, 71, 118, 122, 90, 56, 47, 103, 110, 116, 115, 109, 43, 72, 98, 82, 115, 90, 74, 66, 47, 57, 79, 84, 69, 87, 57, 99, 51, 114, 107, 73, 79, 51, 97, 81, 97, 98, 51, 121, 73, 86, 77, 85, 87, 98, 117, 70, 54, 97, 67, 55, 52, 79, 114, 56, 78, 112, 68, 121, 74, 79, 51, 105, 110, 84, 109, 79, 68, 10, 66, 67, 69, 73, 90, 52, 51, 121, 103, 107, 110, 81, 87, 47, 50, 120, 122, 81, 43, 68, 104, 78, 81, 43, 73, 73, 88, 51, 83, 106, 48, 114, 110, 80, 48, 113, 67, 103, 108, 78, 54, 111, 72, 52, 69, 90, 119, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 84, 92, 120, 99, 51, 92, 120, 57, 99, 92, 120, 52, 50, 92, 120, 67, 52, 92, 120, 66, 48, 84, 65, 75, 32, 85, 69, 75, 65, 69, 32, 75, 92, 120, 67, 51, 92, 120, 66, 54, 107, 32, 83, 101, 114, 116, 105, 102, 105, 107, 97, 32, 72, 105, 122, 109, 101, 116, 32, 83, 97, 92, 120, 67, 52, 92, 120, 57, 70, 108, 97, 121, 92, 120, 99, 52, 92, 120, 98, 49, 92, 120, 54, 51, 92, 120, 99, 52, 92, 120, 98, 49, 115, 92, 120, 99, 52, 92, 120, 98, 49, 32, 45, 32, 83, 92, 120, 67, 51, 92, 120, 66, 67, 114, 92, 120, 67, 51, 92, 120, 66, 67, 109, 32, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 70, 122, 67, 67, 65, 47, 43, 103, 65, 119, 73, 66, 65, 103, 73, 66, 69, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 67, 65, 83, 115, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 82, 83, 77, 82, 103, 119, 70, 103, 89, 68, 86, 81, 81, 72, 10, 68, 65, 57, 72, 90, 87, 74, 54, 90, 83, 65, 116, 73, 69, 116, 118, 89, 50, 70, 108, 98, 71, 107, 120, 82, 122, 66, 70, 66, 103, 78, 86, 66, 65, 111, 77, 80, 108, 84, 68, 118, 72, 74, 114, 97, 88, 108, 108, 73, 69, 74, 112, 98, 71, 108, 116, 99, 50, 86, 115, 73, 72, 90, 108, 73, 70, 82, 108, 97, 50, 53, 118, 98, 71, 57, 113, 10, 97, 87, 115, 103, 81, 88, 74, 104, 120, 90, 57, 48, 120, 76, 70, 121, 98, 87, 69, 103, 83, 51, 86, 121, 100, 87, 49, 49, 73, 67, 48, 103, 86, 77, 79, 99, 81, 115, 83, 119, 86, 69, 70, 76, 77, 85, 103, 119, 82, 103, 89, 68, 86, 81, 81, 76, 68, 68, 57, 86, 98, 72, 86, 122, 89, 87, 119, 103, 82, 87, 120, 108, 97, 51, 82, 121, 10, 98, 50, 53, 112, 97, 121, 66, 50, 90, 83, 66, 76, 99, 109, 108, 119, 100, 71, 57, 115, 98, 50, 112, 112, 73, 69, 70, 121, 89, 99, 87, 102, 100, 77, 83, 120, 99, 109, 49, 104, 73, 69, 86, 117, 99, 51, 82, 112, 100, 77, 79, 56, 99, 56, 79, 56, 73, 67, 48, 103, 86, 85, 86, 76, 81, 85, 85, 120, 73, 122, 65, 104, 66, 103, 78, 86, 10, 66, 65, 115, 77, 71, 107, 116, 104, 98, 88, 85, 103, 85, 50, 86, 121, 100, 71, 108, 109, 97, 87, 116, 104, 99, 51, 108, 118, 98, 105, 66, 78, 90, 88, 74, 114, 90, 88, 112, 112, 77, 85, 111, 119, 83, 65, 89, 68, 86, 81, 81, 68, 68, 69, 70, 85, 119, 53, 120, 67, 120, 76, 66, 85, 81, 85, 115, 103, 86, 85, 86, 76, 81, 85, 85, 103, 10, 83, 56, 79, 50, 97, 121, 66, 84, 90, 88, 74, 48, 97, 87, 90, 112, 97, 50, 69, 103, 83, 71, 108, 54, 98, 87, 86, 48, 73, 70, 78, 104, 120, 74, 57, 115, 89, 88, 110, 69, 115, 87, 80, 69, 115, 88, 80, 69, 115, 83, 65, 116, 73, 70, 80, 68, 118, 72, 76, 68, 118, 71, 48, 103, 77, 122, 65, 101, 70, 119, 48, 119, 78, 122, 65, 52, 10, 77, 106, 81, 120, 77, 84, 77, 51, 77, 68, 100, 97, 70, 119, 48, 120, 78, 122, 65, 52, 77, 106, 69, 120, 77, 84, 77, 51, 77, 68, 100, 97, 77, 73, 73, 66, 75, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 70, 73, 120, 71, 68, 65, 87, 66, 103, 78, 86, 66, 65, 99, 77, 68, 48, 100, 108, 89, 110, 112, 108, 10, 73, 67, 48, 103, 83, 50, 57, 106, 89, 87, 86, 115, 97, 84, 70, 72, 77, 69, 85, 71, 65, 49, 85, 69, 67, 103, 119, 43, 86, 77, 79, 56, 99, 109, 116, 112, 101, 87, 85, 103, 81, 109, 108, 115, 97, 87, 49, 122, 90, 87, 119, 103, 100, 109, 85, 103, 86, 71, 86, 114, 98, 109, 57, 115, 98, 50, 112, 112, 97, 121, 66, 66, 99, 109, 72, 70, 10, 110, 51, 84, 69, 115, 88, 74, 116, 89, 83, 66, 76, 100, 88, 74, 49, 98, 88, 85, 103, 76, 83, 66, 85, 119, 53, 120, 67, 120, 76, 66, 85, 81, 85, 115, 120, 83, 68, 66, 71, 66, 103, 78, 86, 66, 65, 115, 77, 80, 49, 86, 115, 100, 88, 78, 104, 98, 67, 66, 70, 98, 71, 86, 114, 100, 72, 74, 118, 98, 109, 108, 114, 73, 72, 90, 108, 10, 73, 69, 116, 121, 97, 88, 66, 48, 98, 50, 120, 118, 97, 109, 107, 103, 81, 88, 74, 104, 120, 90, 57, 48, 120, 76, 70, 121, 98, 87, 69, 103, 82, 87, 53, 122, 100, 71, 108, 48, 119, 55, 120, 122, 119, 55, 119, 103, 76, 83, 66, 86, 82, 85, 116, 66, 82, 84, 69, 106, 77, 67, 69, 71, 65, 49, 85, 69, 67, 119, 119, 97, 83, 50, 70, 116, 10, 100, 83, 66, 84, 90, 88, 74, 48, 97, 87, 90, 112, 97, 50, 70, 122, 101, 87, 57, 117, 73, 69, 49, 108, 99, 109, 116, 108, 101, 109, 107, 120, 83, 106, 66, 73, 66, 103, 78, 86, 66, 65, 77, 77, 81, 86, 84, 68, 110, 69, 76, 69, 115, 70, 82, 66, 83, 121, 66, 86, 82, 85, 116, 66, 82, 83, 66, 76, 119, 55, 90, 114, 73, 70, 78, 108, 10, 99, 110, 82, 112, 90, 109, 108, 114, 89, 83, 66, 73, 97, 88, 112, 116, 90, 88, 81, 103, 85, 50, 72, 69, 110, 50, 120, 104, 101, 99, 83, 120, 89, 56, 83, 120, 99, 56, 83, 120, 73, 67, 48, 103, 85, 56, 79, 56, 99, 115, 79, 56, 98, 83, 65, 122, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 10, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 105, 109, 49, 76, 47, 120, 67, 73, 79, 115, 80, 50, 102, 112, 84, 111, 54, 105, 66, 107, 99, 75, 52, 104, 103, 98, 52, 54, 101, 122, 122, 98, 56, 82, 49, 83, 102, 49, 110, 54, 56, 121, 74, 77, 108, 97, 67, 81, 118, 69, 104, 79, 10, 69, 97, 118, 55, 116, 55, 87, 78, 101, 111, 77, 111, 106, 67, 90, 71, 50, 69, 54, 86, 81, 73, 100, 104, 110, 56, 87, 101, 98, 89, 71, 72, 86, 50, 121, 75, 79, 55, 82, 109, 54, 115, 120, 65, 47, 79, 79, 113, 98, 76, 76, 76, 65, 100, 115, 121, 118, 57, 76, 114, 104, 99, 43, 104, 68, 86, 88, 68, 87, 122, 104, 88, 99, 76, 104, 49, 10, 120, 110, 110, 82, 70, 68, 68, 116, 71, 49, 104, 98, 97, 43, 56, 49, 56, 113, 69, 104, 84, 115, 88, 79, 102, 74, 108, 102, 98, 76, 109, 52, 73, 112, 78, 81, 112, 56, 49, 77, 99, 71, 113, 43, 97, 103, 86, 47, 69, 53, 119, 114, 72, 117, 114, 43, 82, 56, 52, 69, 112, 87, 43, 115, 107, 121, 53, 56, 75, 53, 43, 101, 101, 82, 79, 82, 10, 54, 79, 113, 101, 121, 106, 104, 49, 106, 109, 75, 119, 108, 90, 77, 113, 53, 100, 47, 112, 88, 112, 100, 117, 73, 70, 57, 102, 104, 72, 112, 69, 79, 82, 108, 65, 72, 76, 112, 86, 75, 47, 115, 119, 115, 111, 72, 118, 104, 79, 80, 99, 55, 74, 103, 52, 79, 81, 79, 70, 67, 75, 108, 85, 65, 119, 85, 112, 56, 77, 109, 80, 105, 43, 111, 76, 10, 104, 109, 85, 90, 69, 100, 80, 112, 67, 83, 80, 101, 97, 74, 77, 68, 121, 84, 89, 99, 73, 87, 55, 79, 106, 71, 98, 120, 109, 84, 68, 89, 49, 55, 80, 68, 72, 102, 105, 66, 76, 113, 105, 57, 103, 103, 116, 109, 47, 111, 76, 76, 52, 101, 65, 97, 103, 115, 78, 65, 103, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 100, 10, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 118, 89, 105, 72, 121, 89, 47, 50, 112, 65, 111, 76, 113, 117, 118, 70, 47, 112, 69, 106, 110, 97, 116, 75, 105, 106, 73, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 10, 77, 65, 77, 66, 65, 102, 56, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 66, 49, 56, 43, 107, 109, 80, 78, 79, 109, 51, 74, 112, 73, 87, 109, 103, 86, 48, 53, 48, 118, 81, 98, 84, 108, 115, 119, 121, 98, 50, 122, 114, 103, 120, 118, 77, 84, 102, 118, 67, 114, 52, 10, 78, 53, 69, 89, 51, 65, 84, 73, 90, 74, 107, 114, 71, 71, 50, 65, 65, 49, 110, 74, 114, 118, 104, 89, 48, 68, 55, 116, 119, 121, 79, 102, 97, 84, 121, 71, 79, 66, 121, 101, 55, 57, 111, 110, 101, 78, 71, 69, 78, 51, 71, 75, 80, 69, 115, 53, 122, 51, 53, 70, 66, 116, 89, 116, 50, 73, 112, 78, 101, 66, 76, 87, 114, 99, 76, 84, 10, 121, 57, 76, 81, 81, 102, 77, 109, 78, 107, 113, 98, 108, 87, 119, 77, 55, 117, 88, 82, 81, 121, 100, 109, 119, 89, 106, 51, 101, 114, 77, 103, 98, 79, 113, 119, 97, 83, 118, 72, 73, 79, 103, 77, 65, 56, 82, 66, 66, 90, 110, 105, 80, 43, 82, 114, 43, 75, 67, 71, 103, 99, 101, 69, 120, 104, 47, 86, 83, 52, 69, 83, 115, 104, 89, 104, 10, 76, 66, 79, 104, 103, 76, 74, 101, 68, 69, 111, 84, 110, 105, 68, 89, 89, 107, 67, 114, 107, 79, 112, 107, 83, 105, 43, 115, 68, 81, 69, 83, 101, 85, 87, 111, 76, 52, 99, 90, 97, 77, 106, 105, 104, 99, 99, 119, 115, 110, 88, 53, 79, 68, 43, 121, 119, 74, 79, 48, 97, 43, 73, 68, 82, 77, 53, 110, 111, 78, 43, 74, 49, 113, 50, 77, 10, 100, 113, 77, 84, 119, 53, 82, 104, 75, 50, 118, 90, 98, 77, 69, 72, 67, 105, 73, 72, 104, 87, 121, 70, 74, 69, 97, 112, 118, 106, 43, 76, 101, 73, 83, 67, 102, 105, 81, 77, 110, 102, 50, 66, 78, 43, 77, 108, 113, 79, 48, 50, 84, 112, 85, 115, 121, 90, 121, 81, 50, 117, 121, 112, 81, 106, 121, 116, 116, 103, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 99, 101, 114, 116, 83, 73, 71, 78, 32, 82, 79, 79, 84, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 79, 68, 67, 67, 65, 105, 67, 103, 65, 119, 73, 66, 65, 103, 73, 71, 73, 65, 89, 70, 70, 110, 65, 67, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 77, 68, 115, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 74, 80, 77, 82, 69, 119, 68, 119, 89, 68, 10, 86, 81, 81, 75, 69, 119, 104, 106, 90, 88, 74, 48, 85, 48, 108, 72, 84, 106, 69, 90, 77, 66, 99, 71, 65, 49, 85, 69, 67, 120, 77, 81, 89, 50, 86, 121, 100, 70, 78, 74, 82, 48, 52, 103, 85, 107, 57, 80, 86, 67, 66, 68, 81, 84, 65, 101, 70, 119, 48, 119, 78, 106, 65, 51, 77, 68, 81, 120, 78, 122, 73, 119, 77, 68, 82, 97, 10, 70, 119, 48, 122, 77, 84, 65, 51, 77, 68, 81, 120, 78, 122, 73, 119, 77, 68, 82, 97, 77, 68, 115, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 74, 80, 77, 82, 69, 119, 68, 119, 89, 68, 86, 81, 81, 75, 69, 119, 104, 106, 90, 88, 74, 48, 85, 48, 108, 72, 84, 106, 69, 90, 77, 66, 99, 71, 65, 49, 85, 69, 10, 67, 120, 77, 81, 89, 50, 86, 121, 100, 70, 78, 74, 82, 48, 52, 103, 85, 107, 57, 80, 86, 67, 66, 68, 81, 84, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 76, 99, 122, 117, 88, 55, 73, 10, 74, 85, 113, 79, 116, 100, 117, 48, 75, 66, 117, 113, 86, 53, 68, 111, 48, 83, 76, 84, 90, 76, 114, 84, 107, 43, 106, 85, 114, 73, 90, 104, 81, 71, 112, 103, 86, 50, 104, 85, 104, 69, 50, 56, 97, 108, 81, 67, 66, 102, 47, 102, 109, 53, 111, 113, 114, 108, 48, 72, 106, 48, 114, 68, 75, 72, 47, 118, 43, 121, 118, 54, 101, 102, 72, 72, 10, 114, 102, 65, 81, 85, 121, 83, 81, 105, 50, 98, 74, 113, 73, 105, 114, 114, 49, 113, 106, 65, 79, 109, 43, 117, 107, 98, 117, 87, 51, 78, 55, 76, 66, 101, 67, 103, 86, 53, 105, 76, 75, 69, 67, 90, 98, 79, 57, 120, 83, 115, 65, 102, 115, 84, 56, 65, 122, 78, 88, 68, 101, 51, 105, 43, 115, 53, 100, 82, 100, 89, 52, 122, 84, 87, 50, 10, 115, 115, 72, 81, 110, 73, 70, 75, 113, 117, 83, 121, 65, 86, 119, 100, 106, 49, 43, 90, 120, 76, 71, 116, 50, 52, 103, 104, 54, 53, 65, 73, 103, 111, 68, 122, 77, 75, 78, 68, 53, 112, 67, 67, 114, 108, 85, 111, 83, 101, 49, 98, 49, 54, 107, 81, 79, 65, 55, 43, 106, 48, 120, 98, 109, 48, 98, 113, 81, 102, 87, 119, 67, 72, 84, 68, 10, 48, 73, 103, 122, 116, 110, 122, 88, 100, 78, 47, 99, 104, 78, 70, 68, 68, 110, 85, 53, 111, 83, 86, 65, 75, 79, 112, 52, 121, 119, 52, 115, 76, 106, 109, 100, 106, 73, 116, 117, 70, 104, 119, 118, 74, 111, 73, 81, 52, 117, 78, 108, 108, 65, 111, 69, 119, 70, 55, 51, 88, 86, 118, 52, 69, 79, 76, 81, 117, 110, 112, 76, 43, 57, 52, 51, 10, 65, 65, 65, 97, 87, 121, 106, 106, 48, 112, 120, 122, 80, 106, 75, 72, 109, 75, 72, 74, 85, 83, 47, 88, 51, 113, 119, 122, 115, 48, 56, 67, 65, 119, 69, 65, 65, 97, 78, 67, 77, 69, 65, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 10, 65, 102, 56, 69, 66, 65, 77, 67, 65, 99, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 79, 67, 77, 109, 57, 115, 108, 83, 98, 80, 120, 102, 73, 98, 87, 115, 107, 75, 72, 67, 57, 66, 114, 111, 78, 110, 107, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 66, 10, 65, 81, 65, 43, 48, 104, 121, 74, 76, 106, 88, 56, 43, 72, 88, 100, 53, 110, 57, 108, 105, 80, 82, 121, 84, 77, 107, 115, 49, 122, 74, 79, 56, 57, 48, 90, 101, 85, 101, 57, 106, 106, 116, 98, 107, 119, 57, 81, 83, 83, 81, 84, 97, 120, 81, 71, 99, 117, 56, 74, 48, 54, 71, 104, 52, 48, 67, 69, 121, 101, 99, 89, 77, 110, 81, 56, 10, 83, 71, 52, 80, 110, 48, 118, 85, 57, 120, 55, 84, 107, 52, 90, 107, 86, 74, 100, 106, 99, 108, 68, 86, 86, 99, 47, 54, 73, 74, 77, 67, 111, 112, 118, 68, 73, 53, 78, 79, 70, 108, 86, 50, 111, 72, 66, 53, 98, 99, 48, 104, 72, 56, 56, 118, 76, 98, 119, 90, 52, 52, 103, 120, 43, 70, 107, 97, 103, 81, 110, 73, 108, 54, 90, 48, 10, 120, 50, 68, 69, 87, 56, 120, 88, 106, 114, 74, 49, 47, 82, 115, 67, 67, 100, 116, 90, 98, 51, 75, 84, 97, 102, 99, 120, 81, 100, 97, 73, 79, 76, 43, 72, 115, 114, 48, 87, 101, 102, 109, 113, 53, 76, 54, 73, 74, 100, 49, 104, 74, 121, 77, 99, 116, 84, 69, 72, 66, 68, 97, 48, 71, 112, 67, 57, 111, 72, 82, 120, 85, 73, 108, 116, 10, 118, 66, 84, 106, 68, 52, 97, 117, 56, 97, 115, 43, 120, 54, 65, 74, 122, 75, 78, 73, 48, 101, 68, 98, 90, 79, 101, 83, 116, 99, 43, 118, 99, 107, 78, 119, 105, 47, 110, 68, 104, 68, 119, 84, 113, 110, 54, 83, 109, 49, 100, 84, 107, 47, 112, 119, 119, 112, 69, 79, 77, 102, 109, 98, 90, 49, 51, 112, 108, 106, 104, 101, 88, 55, 78, 122, 10, 84, 111, 103, 86, 90, 57, 54, 101, 100, 104, 66, 105, 73, 76, 53, 86, 97, 90, 86, 68, 65, 68, 108, 78, 57, 117, 54, 119, 87, 107, 53, 74, 82, 70, 82, 89, 88, 48, 75, 68, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 78, 78, 73, 67, 32, 82, 79, 79, 84, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 86, 84, 67, 67, 65, 106, 50, 103, 65, 119, 73, 66, 65, 103, 73, 69, 83, 84, 77, 65, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 65, 121, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 68, 84, 106, 69, 79, 77, 65, 119, 71, 65, 49, 85, 69, 10, 67, 104, 77, 70, 81, 48, 53, 79, 83, 85, 77, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 77, 84, 67, 107, 78, 79, 84, 107, 108, 68, 73, 70, 74, 80, 84, 49, 81, 119, 72, 104, 99, 78, 77, 68, 99, 119, 78, 68, 69, 50, 77, 68, 99, 119, 79, 84, 69, 48, 87, 104, 99, 78, 77, 106, 99, 119, 78, 68, 69, 50, 77, 68, 99, 119, 10, 79, 84, 69, 48, 87, 106, 65, 121, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 68, 84, 106, 69, 79, 77, 65, 119, 71, 65, 49, 85, 69, 67, 104, 77, 70, 81, 48, 53, 79, 83, 85, 77, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 77, 84, 67, 107, 78, 79, 84, 107, 108, 68, 73, 70, 74, 80, 84, 49, 81, 119, 10, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 68, 84, 78, 102, 99, 47, 99, 51, 101, 116, 54, 70, 116, 122, 70, 56, 76, 82, 98, 43, 49, 86, 118, 71, 55, 113, 54, 75, 82, 53, 115, 109, 122, 68, 10, 111, 43, 47, 104, 110, 55, 69, 55, 83, 73, 88, 49, 109, 108, 119, 104, 73, 104, 65, 115, 120, 89, 76, 79, 50, 117, 79, 97, 98, 106, 102, 104, 104, 121, 122, 99, 117, 81, 120, 97, 117, 111, 104, 86, 51, 47, 50, 113, 50, 120, 56, 120, 54, 103, 72, 120, 51, 122, 107, 66, 119, 82, 80, 57, 83, 70, 73, 104, 120, 70, 88, 102, 50, 116, 105, 122, 10, 86, 72, 97, 54, 100, 76, 71, 51, 102, 100, 102, 65, 54, 80, 90, 90, 120, 85, 51, 73, 118, 97, 48, 102, 70, 78, 114, 102, 87, 69, 81, 108, 77, 104, 107, 113, 120, 51, 53, 43, 106, 113, 52, 52, 115, 68, 66, 55, 82, 51, 73, 74, 77, 102, 65, 119, 50, 56, 77, 98, 100, 105, 109, 55, 97, 88, 90, 79, 86, 47, 107, 98, 90, 75, 75, 84, 10, 86, 114, 100, 118, 109, 87, 55, 98, 67, 103, 83, 99, 69, 101, 79, 65, 72, 56, 116, 106, 108, 66, 65, 75, 113, 101, 70, 107, 103, 106, 72, 53, 106, 67, 102, 116, 112, 112, 107, 65, 57, 110, 67, 84, 71, 80, 105, 104, 78, 73, 97, 106, 51, 88, 114, 67, 71, 72, 110, 50, 101, 109, 85, 49, 122, 53, 68, 114, 118, 84, 79, 84, 110, 49, 79, 114, 10, 99, 122, 118, 109, 109, 122, 81, 103, 76, 120, 51, 118, 113, 82, 49, 106, 71, 113, 67, 65, 50, 119, 77, 118, 43, 83, 89, 97, 104, 116, 75, 78, 117, 54, 109, 43, 85, 106, 113, 72, 90, 48, 103, 78, 118, 55, 83, 103, 50, 67, 97, 43, 73, 49, 57, 122, 78, 51, 56, 109, 53, 112, 73, 69, 111, 51, 47, 80, 73, 75, 101, 51, 56, 122, 114, 75, 10, 121, 53, 110, 76, 65, 103, 77, 66, 65, 65, 71, 106, 99, 122, 66, 120, 77, 66, 69, 71, 67, 87, 67, 71, 83, 65, 71, 71, 43, 69, 73, 66, 65, 81, 81, 69, 65, 119, 73, 65, 66, 122, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 82, 108, 56, 106, 71, 116, 75, 118, 102, 51, 51, 86, 75, 87, 67, 115, 99, 67, 10, 119, 81, 55, 118, 112, 116, 85, 55, 69, 84, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 115, 71, 65, 49, 85, 100, 68, 119, 81, 69, 65, 119, 73, 66, 47, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 90, 102, 73, 120, 114, 83, 114, 51, 57, 57, 49, 83, 10, 108, 103, 114, 72, 65, 115, 69, 79, 55, 54, 98, 86, 79, 120, 69, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 69, 115, 49, 55, 115, 122, 107, 114, 114, 47, 68, 98, 113, 50, 102, 108, 84, 116, 76, 80, 49, 115, 101, 51, 49, 99, 112, 111, 108, 110, 75, 79, 79, 75, 53, 10, 71, 118, 43, 101, 53, 109, 52, 121, 51, 82, 54, 117, 54, 106, 87, 51, 57, 90, 79, 82, 84, 116, 112, 67, 52, 99, 77, 88, 89, 70, 68, 121, 48, 86, 119, 109, 117, 89, 75, 51, 54, 109, 51, 107, 110, 73, 84, 110, 65, 51, 107, 88, 114, 53, 103, 57, 108, 78, 118, 72, 117, 103, 68, 110, 117, 76, 56, 66, 86, 56, 70, 51, 82, 84, 73, 77, 10, 79, 47, 71, 48, 72, 65, 105, 119, 47, 86, 71, 103, 111, 100, 50, 97, 72, 82, 77, 50, 109, 109, 50, 51, 120, 122, 121, 53, 52, 99, 88, 90, 70, 47, 113, 68, 49, 84, 48, 86, 111, 68, 121, 55, 72, 103, 118, 105, 121, 74, 65, 47, 113, 73, 89, 77, 47, 80, 109, 76, 88, 111, 88, 76, 84, 49, 116, 76, 89, 104, 70, 72, 120, 85, 86, 56, 10, 66, 83, 57, 66, 115, 90, 52, 81, 97, 82, 117, 90, 108, 117, 66, 86, 101, 102, 116, 79, 104, 112, 109, 52, 108, 78, 113, 71, 79, 71, 113, 84, 111, 43, 102, 76, 98, 117, 88, 102, 54, 105, 70, 86, 105, 90, 120, 57, 102, 88, 43, 89, 57, 81, 67, 74, 55, 117, 79, 69, 119, 70, 121, 87, 116, 99, 86, 71, 54, 107, 98, 103, 104, 86, 87, 50, 10, 71, 56, 107, 83, 49, 115, 72, 78, 122, 89, 68, 122, 65, 103, 69, 56, 121, 71, 110, 76, 82, 85, 104, 106, 50, 74, 84, 81, 55, 73, 85, 79, 79, 48, 52, 82, 90, 102, 83, 67, 106, 75, 89, 57, 114, 105, 52, 105, 108, 65, 110, 73, 88, 79, 111, 56, 103, 86, 48, 87, 75, 103, 79, 88, 70, 108, 85, 74, 50, 52, 112, 66, 103, 112, 53, 109, 10, 109, 120, 69, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 101, 111, 84, 114, 117, 115, 116, 32, 80, 114, 105, 109, 97, 114, 121, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 45, 32, 71, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 47, 106, 67, 67, 65, 117, 97, 103, 65, 119, 73, 66, 65, 103, 73, 81, 70, 97, 120, 117, 108, 66, 109, 121, 101, 85, 116, 66, 57, 105, 101, 112, 119, 120, 103, 80, 72, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 66, 109, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 86, 86, 77, 120, 70, 106, 65, 85, 66, 103, 78, 86, 66, 65, 111, 84, 68, 85, 100, 108, 98, 49, 82, 121, 100, 88, 78, 48, 73, 69, 108, 117, 89, 121, 52, 120, 79, 84, 65, 51, 66, 103, 78, 86, 66, 65, 115, 84, 77, 67, 104, 106, 75, 83, 65, 121, 77, 68, 65, 52, 73, 69, 100, 108, 98, 49, 82, 121, 100, 88, 78, 48, 10, 73, 69, 108, 117, 89, 121, 52, 103, 76, 83, 66, 71, 98, 51, 73, 103, 89, 88, 86, 48, 97, 71, 57, 121, 97, 88, 112, 108, 90, 67, 66, 49, 99, 50, 85, 103, 98, 50, 53, 115, 101, 84, 69, 50, 77, 68, 81, 71, 65, 49, 85, 69, 65, 120, 77, 116, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 85, 72, 74, 112, 98, 87, 70, 121, 10, 101, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 83, 65, 116, 73, 69, 99, 122, 77, 66, 52, 88, 68, 84, 65, 52, 77, 68, 81, 119, 77, 106, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 77, 51, 77, 84, 73, 119, 77, 84, 73, 122, 10, 78, 84, 107, 49, 79, 86, 111, 119, 103, 90, 103, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 89, 119, 70, 65, 89, 68, 86, 81, 81, 75, 69, 119, 49, 72, 90, 87, 57, 85, 99, 110, 86, 122, 100, 67, 66, 74, 98, 109, 77, 117, 77, 84, 107, 119, 78, 119, 89, 68, 86, 81, 81, 76, 69, 122, 65, 111, 10, 89, 121, 107, 103, 77, 106, 65, 119, 79, 67, 66, 72, 90, 87, 57, 85, 99, 110, 86, 122, 100, 67, 66, 74, 98, 109, 77, 117, 73, 67, 48, 103, 82, 109, 57, 121, 73, 71, 70, 49, 100, 71, 104, 118, 99, 109, 108, 54, 90, 87, 81, 103, 100, 88, 78, 108, 73, 71, 57, 117, 98, 72, 107, 120, 78, 106, 65, 48, 66, 103, 78, 86, 66, 65, 77, 84, 10, 76, 85, 100, 108, 98, 49, 82, 121, 100, 88, 78, 48, 73, 70, 66, 121, 97, 87, 49, 104, 99, 110, 107, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 103, 76, 83, 66, 72, 77, 122, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 78, 122, 105, 88, 109, 74, 89, 72, 84, 78, 88, 79, 84, 73, 122, 43, 117, 118, 76, 104, 52, 121, 110, 49, 69, 114, 100, 66, 111, 106, 113, 90, 73, 52, 120, 109, 75, 85, 52, 107, 66, 54, 89, 122, 121, 53, 106, 10, 75, 47, 66, 71, 118, 69, 83, 121, 105, 97, 72, 65, 75, 65, 120, 74, 99, 67, 71, 86, 110, 50, 84, 65, 112, 112, 77, 83, 65, 109, 85, 109, 104, 115, 97, 108, 105, 102, 68, 54, 49, 52, 83, 103, 99, 75, 57, 80, 71, 112, 99, 47, 66, 107, 84, 86, 121, 101, 116, 121, 69, 72, 51, 107, 77, 83, 106, 55, 72, 71, 72, 109, 75, 65, 100, 69, 10, 99, 53, 73, 105, 97, 97, 99, 68, 105, 71, 121, 100, 89, 56, 104, 83, 50, 112, 103, 110, 53, 119, 104, 77, 99, 68, 54, 48, 121, 82, 76, 66, 120, 87, 101, 68, 88, 84, 80, 122, 65, 120, 72, 115, 97, 116, 66, 84, 52, 116, 71, 54, 78, 109, 67, 85, 103, 76, 116, 104, 89, 50, 120, 98, 70, 51, 55, 102, 81, 74, 81, 101, 113, 119, 51, 67, 10, 73, 83, 104, 119, 105, 80, 47, 87, 74, 109, 120, 115, 89, 65, 81, 108, 84, 108, 86, 43, 102, 101, 43, 47, 108, 69, 106, 101, 116, 120, 51, 100, 99, 73, 48, 70, 88, 52, 105, 108, 109, 47, 76, 67, 55, 117, 114, 82, 81, 69, 70, 116, 89, 106, 103, 100, 86, 103, 98, 70, 65, 48, 100, 82, 73, 66, 110, 56, 101, 120, 65, 76, 68, 109, 75, 117, 10, 100, 108, 87, 47, 88, 51, 101, 43, 80, 107, 107, 66, 85, 122, 50, 89, 74, 81, 78, 50, 74, 70, 111, 100, 116, 78, 117, 74, 54, 110, 110, 108, 116, 114, 77, 55, 80, 55, 112, 77, 75, 69, 70, 47, 66, 113, 120, 113, 106, 115, 72, 81, 57, 103, 85, 100, 102, 101, 90, 67, 104, 117, 79, 108, 49, 85, 99, 67, 65, 119, 69, 65, 65, 97, 78, 67, 10, 77, 69, 65, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 77, 82, 53, 121, 111, 54, 104, 84, 103, 77, 100, 72, 78, 120, 114, 10, 50, 122, 70, 98, 108, 68, 52, 47, 77, 72, 56, 116, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 66, 65, 81, 65, 116, 120, 82, 80, 80, 86, 111, 66, 55, 101, 110, 105, 57, 110, 54, 52, 115, 109, 101, 102, 118, 50, 116, 43, 85, 88, 103, 108, 112, 112, 43, 100, 117, 97, 73, 121, 57, 10, 99, 114, 53, 72, 113, 81, 54, 88, 69, 114, 104, 75, 56, 87, 84, 84, 79, 100, 56, 108, 78, 78, 84, 66, 122, 85, 54, 66, 56, 65, 56, 69, 120, 67, 83, 122, 78, 74, 98, 71, 112, 113, 111, 119, 51, 50, 104, 104, 99, 57, 102, 53, 106, 111, 87, 74, 55, 119, 53, 101, 108, 83, 104, 75, 75, 105, 101, 80, 69, 73, 52, 117, 102, 73, 98, 69, 10, 65, 112, 55, 97, 68, 72, 100, 108, 68, 107, 81, 78, 107, 118, 51, 57, 115, 120, 89, 50, 43, 104, 69, 78, 72, 89, 119, 79, 66, 52, 108, 113, 75, 86, 98, 51, 99, 118, 84, 100, 70, 90, 120, 51, 78, 87, 90, 88, 113, 120, 78, 84, 50, 73, 55, 66, 81, 77, 88, 88, 69, 120, 90, 97, 99, 115, 101, 51, 97, 81, 72, 69, 101, 114, 71, 68, 10, 65, 87, 104, 57, 106, 85, 71, 104, 108, 66, 106, 66, 74, 86, 122, 56, 56, 80, 54, 68, 65, 111, 100, 56, 68, 81, 51, 80, 76, 103, 104, 99, 83, 107, 65, 78, 80, 117, 121, 66, 89, 101, 89, 107, 50, 56, 114, 103, 68, 105, 48, 72, 115, 106, 53, 87, 51, 73, 51, 49, 81, 89, 85, 72, 83, 74, 115, 77, 67, 56, 116, 74, 80, 51, 51, 115, 10, 116, 47, 51, 76, 106, 87, 101, 74, 71, 113, 118, 116, 117, 120, 54, 106, 65, 65, 103, 73, 70, 121, 113, 67, 88, 68, 70, 100, 82, 111, 111, 116, 68, 52, 97, 98, 100, 78, 108, 70, 43, 57, 82, 65, 115, 88, 113, 113, 97, 67, 50, 71, 115, 112, 107, 105, 52, 99, 69, 114, 120, 53, 122, 52, 56, 49, 43, 111, 103, 104, 76, 114, 71, 82, 69, 116, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 116, 104, 97, 119, 116, 101, 32, 80, 114, 105, 109, 97, 114, 121, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 105, 68, 67, 67, 65, 103, 50, 103, 65, 119, 73, 66, 65, 103, 73, 81, 78, 102, 119, 109, 88, 78, 109, 69, 84, 56, 107, 57, 74, 106, 49, 88, 109, 54, 55, 88, 86, 106, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 122, 67, 66, 104, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 10, 86, 86, 77, 120, 70, 84, 65, 84, 66, 103, 78, 86, 66, 65, 111, 84, 68, 72, 82, 111, 89, 88, 100, 48, 90, 83, 119, 103, 83, 87, 53, 106, 76, 106, 69, 52, 77, 68, 89, 71, 65, 49, 85, 69, 67, 120, 77, 118, 75, 71, 77, 112, 73, 68, 73, 119, 77, 68, 99, 103, 100, 71, 104, 104, 100, 51, 82, 108, 76, 67, 66, 74, 98, 109, 77, 117, 10, 73, 67, 48, 103, 82, 109, 57, 121, 73, 71, 70, 49, 100, 71, 104, 118, 99, 109, 108, 54, 90, 87, 81, 103, 100, 88, 78, 108, 73, 71, 57, 117, 98, 72, 107, 120, 74, 68, 65, 105, 66, 103, 78, 86, 66, 65, 77, 84, 71, 51, 82, 111, 89, 88, 100, 48, 90, 83, 66, 81, 99, 109, 108, 116, 89, 88, 74, 53, 73, 70, 74, 118, 98, 51, 81, 103, 10, 81, 48, 69, 103, 76, 83, 66, 72, 77, 106, 65, 101, 70, 119, 48, 119, 78, 122, 69, 120, 77, 68, 85, 119, 77, 68, 65, 119, 77, 68, 66, 97, 70, 119, 48, 122, 79, 68, 65, 120, 77, 84, 103, 121, 77, 122, 85, 53, 78, 84, 108, 97, 77, 73, 71, 69, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 86, 10, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 100, 71, 104, 104, 100, 51, 82, 108, 76, 67, 66, 74, 98, 109, 77, 117, 77, 84, 103, 119, 78, 103, 89, 68, 86, 81, 81, 76, 69, 121, 56, 111, 89, 121, 107, 103, 77, 106, 65, 119, 78, 121, 66, 48, 97, 71, 70, 51, 100, 71, 85, 115, 73, 69, 108, 117, 89, 121, 52, 103, 76, 83, 66, 71, 10, 98, 51, 73, 103, 89, 88, 86, 48, 97, 71, 57, 121, 97, 88, 112, 108, 90, 67, 66, 49, 99, 50, 85, 103, 98, 50, 53, 115, 101, 84, 69, 107, 77, 67, 73, 71, 65, 49, 85, 69, 65, 120, 77, 98, 100, 71, 104, 104, 100, 51, 82, 108, 73, 70, 66, 121, 97, 87, 49, 104, 99, 110, 107, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 116, 10, 73, 69, 99, 121, 77, 72, 89, 119, 69, 65, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 70, 75, 52, 69, 69, 65, 67, 73, 68, 89, 103, 65, 69, 111, 116, 87, 99, 103, 110, 117, 86, 110, 102, 70, 83, 101, 73, 102, 43, 105, 104, 97, 47, 66, 101, 98, 102, 111, 119, 74, 80, 68, 81, 102, 71, 65, 70, 71, 54, 68, 65, 74, 83, 10, 76, 83, 75, 107, 81, 106, 110, 69, 47, 111, 47, 113, 121, 99, 71, 43, 49, 69, 51, 47, 110, 51, 113, 101, 52, 114, 70, 56, 109, 113, 50, 110, 104, 103, 108, 122, 104, 57, 72, 110, 109, 117, 78, 54, 112, 97, 112, 117, 43, 55, 113, 122, 99, 77, 66, 110, 105, 75, 73, 49, 49, 75, 79, 97, 115, 102, 50, 116, 119, 117, 56, 120, 43, 113, 105, 53, 10, 56, 47, 115, 73, 120, 112, 72, 82, 43, 121, 109, 86, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 10, 109, 116, 103, 65, 77, 65, 68, 110, 97, 51, 43, 70, 71, 79, 54, 76, 116, 115, 54, 75, 68, 80, 103, 82, 52, 98, 115, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 77, 68, 97, 81, 65, 119, 90, 103, 73, 120, 65, 78, 51, 52, 52, 70, 100, 72, 87, 54, 102, 109, 67, 115, 79, 57, 57, 89, 67, 75, 108, 122, 85, 78, 10, 71, 52, 107, 56, 86, 73, 90, 51, 75, 77, 113, 104, 57, 72, 110, 101, 116, 101, 89, 52, 115, 80, 66, 108, 99, 73, 120, 47, 65, 108, 84, 67, 118, 47, 47, 89, 111, 84, 55, 90, 122, 119, 73, 120, 65, 77, 83, 78, 108, 80, 122, 99, 85, 57, 76, 99, 110, 88, 103, 87, 72, 120, 85, 122, 73, 49, 78, 83, 52, 49, 111, 120, 88, 90, 51, 75, 10, 114, 114, 48, 84, 75, 85, 81, 78, 74, 49, 117, 111, 53, 50, 105, 99, 69, 118, 100, 89, 80, 121, 53, 121, 65, 108, 101, 106, 106, 54, 69, 85, 76, 103, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 116, 104, 97, 119, 116, 101, 32, 80, 114, 105, 109, 97, 114, 121, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 75, 106, 67, 67, 65, 120, 75, 103, 65, 119, 73, 66, 65, 103, 73, 81, 89, 65, 71, 88, 116, 48, 97, 110, 54, 114, 83, 48, 109, 116, 90, 76, 76, 47, 101, 81, 43, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 66, 114, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 86, 86, 77, 120, 70, 84, 65, 84, 66, 103, 78, 86, 66, 65, 111, 84, 68, 72, 82, 111, 89, 88, 100, 48, 90, 83, 119, 103, 83, 87, 53, 106, 76, 106, 69, 111, 77, 67, 89, 71, 65, 49, 85, 69, 67, 120, 77, 102, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 84, 90, 88, 74, 50, 10, 97, 87, 78, 108, 99, 121, 66, 69, 97, 88, 90, 112, 99, 50, 108, 118, 98, 106, 69, 52, 77, 68, 89, 71, 65, 49, 85, 69, 67, 120, 77, 118, 75, 71, 77, 112, 73, 68, 73, 119, 77, 68, 103, 103, 100, 71, 104, 104, 100, 51, 82, 108, 76, 67, 66, 74, 98, 109, 77, 117, 73, 67, 48, 103, 82, 109, 57, 121, 73, 71, 70, 49, 100, 71, 104, 118, 10, 99, 109, 108, 54, 90, 87, 81, 103, 100, 88, 78, 108, 73, 71, 57, 117, 98, 72, 107, 120, 74, 68, 65, 105, 66, 103, 78, 86, 66, 65, 77, 84, 71, 51, 82, 111, 89, 88, 100, 48, 90, 83, 66, 81, 99, 109, 108, 116, 89, 88, 74, 53, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 76, 83, 66, 72, 77, 122, 65, 101, 70, 119, 48, 119, 10, 79, 68, 65, 48, 77, 68, 73, 119, 77, 68, 65, 119, 77, 68, 66, 97, 70, 119, 48, 122, 78, 122, 69, 121, 77, 68, 69, 121, 77, 122, 85, 53, 78, 84, 108, 97, 77, 73, 71, 117, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 100, 71, 104, 104, 10, 100, 51, 82, 108, 76, 67, 66, 74, 98, 109, 77, 117, 77, 83, 103, 119, 74, 103, 89, 68, 86, 81, 81, 76, 69, 120, 57, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 86, 122, 73, 69, 82, 112, 100, 109, 108, 122, 97, 87, 57, 117, 77, 84, 103, 119, 78, 103, 89, 68, 10, 86, 81, 81, 76, 69, 121, 56, 111, 89, 121, 107, 103, 77, 106, 65, 119, 79, 67, 66, 48, 97, 71, 70, 51, 100, 71, 85, 115, 73, 69, 108, 117, 89, 121, 52, 103, 76, 83, 66, 71, 98, 51, 73, 103, 89, 88, 86, 48, 97, 71, 57, 121, 97, 88, 112, 108, 90, 67, 66, 49, 99, 50, 85, 103, 98, 50, 53, 115, 101, 84, 69, 107, 77, 67, 73, 71, 10, 65, 49, 85, 69, 65, 120, 77, 98, 100, 71, 104, 104, 100, 51, 82, 108, 73, 70, 66, 121, 97, 87, 49, 104, 99, 110, 107, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 116, 73, 69, 99, 122, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 10, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 115, 114, 56, 110, 76, 80, 118, 98, 50, 70, 118, 100, 101, 72, 115, 98, 110, 110, 100, 109, 103, 99, 115, 43, 118, 72, 121, 117, 56, 54, 89, 110, 109, 106, 83, 106, 97, 68, 70, 120, 79, 68, 78, 105, 53, 80, 78, 120, 90, 110, 109, 120, 113, 87, 87, 106, 112, 89, 118, 86, 106, 50, 65, 116, 10, 80, 48, 76, 77, 113, 109, 115, 121, 119, 67, 80, 76, 76, 69, 72, 100, 53, 78, 47, 56, 89, 90, 122, 105, 99, 55, 73, 105, 108, 82, 70, 68, 71, 70, 47, 69, 116, 104, 57, 88, 98, 65, 111, 70, 87, 67, 76, 73, 78, 107, 119, 54, 102, 75, 88, 82, 122, 52, 97, 118, 105, 75, 100, 69, 65, 104, 78, 48, 99, 88, 77, 75, 81, 108, 107, 67, 10, 43, 66, 115, 85, 97, 48, 76, 102, 98, 49, 43, 54, 97, 52, 75, 105, 110, 86, 118, 110, 83, 114, 48, 101, 65, 88, 76, 98, 83, 51, 84, 111, 79, 51, 57, 47, 102, 82, 56, 69, 116, 67, 97, 98, 52, 76, 82, 97, 114, 69, 99, 57, 86, 98, 106, 88, 115, 67, 90, 83, 75, 65, 69, 120, 81, 71, 98, 89, 50, 83, 83, 57, 57, 105, 114, 89, 10, 55, 67, 70, 74, 88, 74, 118, 50, 101, 117, 108, 47, 86, 84, 86, 43, 108, 109, 117, 78, 107, 53, 77, 110, 121, 53, 75, 55, 54, 113, 120, 65, 119, 74, 47, 67, 43, 73, 68, 80, 88, 102, 82, 97, 51, 77, 53, 48, 104, 113, 89, 43, 98, 65, 116, 84, 121, 114, 50, 83, 122, 104, 107, 71, 99, 117, 89, 77, 88, 68, 104, 112, 120, 119, 84, 87, 10, 118, 71, 122, 79, 87, 47, 98, 51, 97, 74, 122, 99, 74, 82, 86, 73, 105, 75, 72, 112, 113, 102, 105, 89, 110, 79, 68, 122, 49, 84, 69, 111, 89, 82, 70, 115, 90, 53, 97, 78, 79, 90, 110, 76, 119, 107, 85, 107, 79, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 10, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 114, 87, 121, 113, 108, 71, 67, 99, 55, 101, 84, 47, 43, 106, 52, 75, 100, 67, 116, 106, 65, 47, 101, 50, 87, 98, 56, 119, 68, 81, 89, 74, 10, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 69, 66, 65, 66, 112, 65, 50, 74, 86, 108, 114, 65, 109, 83, 105, 99, 89, 53, 57, 66, 68, 108, 113, 81, 53, 109, 85, 49, 49, 52, 51, 118, 111, 107, 107, 98, 118, 110, 82, 70, 72, 102, 120, 104, 89, 48, 67, 117, 57, 113, 82, 70, 72, 113, 75, 119, 101, 75, 10, 65, 51, 114, 68, 54, 122, 56, 75, 76, 70, 73, 87, 111, 67, 116, 68, 117, 83, 87, 81, 80, 51, 67, 112, 77, 121, 86, 116, 82, 82, 111, 111, 79, 121, 102, 80, 113, 115, 77, 112, 81, 104, 118, 102, 79, 48, 122, 65, 77, 122, 82, 98, 81, 89, 105, 47, 97, 121, 116, 108, 114, 121, 106, 118, 115, 118, 88, 68, 113, 109, 98, 79, 101, 49, 98, 117, 10, 116, 56, 106, 76, 90, 56, 72, 74, 110, 66, 111, 89, 117, 77, 84, 68, 83, 81, 80, 120, 89, 65, 53, 81, 122, 85, 98, 70, 56, 51, 100, 53, 57, 55, 89, 86, 52, 68, 106, 98, 120, 121, 56, 111, 111, 65, 119, 47, 100, 121, 90, 48, 50, 83, 85, 83, 50, 106, 72, 97, 71, 104, 55, 99, 75, 85, 71, 82, 73, 106, 120, 112, 112, 55, 115, 67, 10, 56, 114, 90, 99, 74, 119, 79, 74, 57, 65, 98, 113, 109, 43, 82, 121, 103, 117, 79, 104, 67, 99, 72, 112, 65, 66, 110, 84, 80, 116, 82, 119, 97, 55, 112, 120, 112, 113, 112, 89, 114, 118, 83, 55, 54, 87, 121, 50, 55, 52, 102, 77, 109, 55, 118, 47, 79, 101, 90, 87, 89, 100, 77, 75, 112, 56, 82, 99, 84, 71, 66, 55, 66, 88, 99, 109, 10, 101, 114, 47, 89, 66, 49, 73, 115, 89, 118, 100, 119, 89, 57, 107, 53, 118, 71, 56, 99, 119, 110, 110, 99, 100, 105, 109, 118, 122, 115, 85, 115, 90, 65, 82, 101, 105, 68, 90, 117, 77, 100, 82, 65, 71, 109, 73, 48, 78, 106, 56, 49, 65, 97, 54, 115, 89, 54, 65, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 101, 111, 84, 114, 117, 115, 116, 32, 80, 114, 105, 109, 97, 114, 121, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 45, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 114, 106, 67, 67, 65, 106, 87, 103, 65, 119, 73, 66, 65, 103, 73, 81, 80, 76, 76, 48, 83, 65, 111, 65, 52, 118, 55, 114, 74, 68, 116, 101, 89, 68, 55, 68, 97, 122, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 122, 67, 66, 109, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 10, 86, 86, 77, 120, 70, 106, 65, 85, 66, 103, 78, 86, 66, 65, 111, 84, 68, 85, 100, 108, 98, 49, 82, 121, 100, 88, 78, 48, 73, 69, 108, 117, 89, 121, 52, 120, 79, 84, 65, 51, 66, 103, 78, 86, 66, 65, 115, 84, 77, 67, 104, 106, 75, 83, 65, 121, 77, 68, 65, 51, 73, 69, 100, 108, 98, 49, 82, 121, 100, 88, 78, 48, 73, 69, 108, 117, 10, 89, 121, 52, 103, 76, 83, 66, 71, 98, 51, 73, 103, 89, 88, 86, 48, 97, 71, 57, 121, 97, 88, 112, 108, 90, 67, 66, 49, 99, 50, 85, 103, 98, 50, 53, 115, 101, 84, 69, 50, 77, 68, 81, 71, 65, 49, 85, 69, 65, 120, 77, 116, 82, 50, 86, 118, 86, 72, 74, 49, 99, 51, 81, 103, 85, 72, 74, 112, 98, 87, 70, 121, 101, 83, 66, 68, 10, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 83, 65, 116, 73, 69, 99, 121, 77, 66, 52, 88, 68, 84, 65, 51, 77, 84, 69, 119, 78, 84, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 77, 52, 77, 68, 69, 120, 79, 68, 73, 122, 78, 84, 107, 49, 10, 79, 86, 111, 119, 103, 90, 103, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 89, 119, 70, 65, 89, 68, 86, 81, 81, 75, 69, 119, 49, 72, 90, 87, 57, 85, 99, 110, 86, 122, 100, 67, 66, 74, 98, 109, 77, 117, 77, 84, 107, 119, 78, 119, 89, 68, 86, 81, 81, 76, 69, 122, 65, 111, 89, 121, 107, 103, 10, 77, 106, 65, 119, 78, 121, 66, 72, 90, 87, 57, 85, 99, 110, 86, 122, 100, 67, 66, 74, 98, 109, 77, 117, 73, 67, 48, 103, 82, 109, 57, 121, 73, 71, 70, 49, 100, 71, 104, 118, 99, 109, 108, 54, 90, 87, 81, 103, 100, 88, 78, 108, 73, 71, 57, 117, 98, 72, 107, 120, 78, 106, 65, 48, 66, 103, 78, 86, 66, 65, 77, 84, 76, 85, 100, 108, 10, 98, 49, 82, 121, 100, 88, 78, 48, 73, 70, 66, 121, 97, 87, 49, 104, 99, 110, 107, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 103, 76, 83, 66, 72, 77, 106, 66, 50, 77, 66, 65, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 10, 66, 83, 117, 66, 66, 65, 65, 105, 65, 50, 73, 65, 66, 66, 87, 120, 54, 80, 48, 68, 70, 85, 80, 108, 114, 79, 117, 72, 78, 120, 70, 105, 55, 57, 75, 68, 78, 108, 74, 57, 82, 86, 99, 76, 83, 111, 49, 55, 86, 68, 115, 54, 98, 108, 56, 86, 65, 115, 66, 81, 112, 115, 56, 108, 76, 51, 51, 75, 83, 76, 106, 72, 85, 71, 77, 99, 10, 75, 105, 69, 73, 102, 74, 111, 50, 50, 65, 118, 43, 48, 83, 98, 70, 87, 68, 69, 119, 75, 67, 88, 122, 88, 86, 50, 106, 117, 76, 97, 108, 116, 74, 76, 116, 98, 67, 121, 102, 54, 57, 49, 68, 105, 97, 73, 56, 83, 48, 105, 82, 72, 86, 68, 115, 74, 116, 47, 87, 89, 67, 54, 57, 73, 97, 78, 67, 77, 69, 65, 119, 68, 119, 89, 68, 10, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 66, 86, 102, 78, 86, 100, 82, 86, 102, 115, 108, 115, 113, 48, 68, 97, 102, 119, 66, 111, 47, 113, 43, 10, 69, 86, 88, 86, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 68, 65, 50, 99, 65, 77, 71, 81, 67, 77, 71, 83, 87, 87, 97, 98, 111, 67, 100, 54, 76, 117, 118, 112, 97, 105, 73, 106, 119, 72, 53, 72, 84, 82, 113, 106, 121, 83, 107, 119, 67, 89, 47, 116, 115, 88, 122, 106, 98, 76, 107, 71, 84, 113, 81, 55, 109, 10, 110, 100, 119, 120, 72, 76, 75, 103, 112, 120, 103, 99, 101, 101, 72, 72, 78, 103, 73, 119, 79, 108, 97, 118, 109, 110, 82, 115, 57, 118, 117, 68, 52, 68, 80, 84, 67, 70, 43, 104, 110, 77, 74, 98, 110, 48, 98, 87, 116, 115, 117, 82, 66, 109, 79, 105, 66, 117, 99, 122, 114, 68, 54, 111, 103, 82, 76, 81, 121, 55, 114, 81, 107, 103, 117, 50, 10, 110, 112, 97, 113, 66, 65, 43, 75, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 86, 101, 114, 105, 83, 105, 103, 110, 32, 85, 110, 105, 118, 101, 114, 115, 97, 108, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 117, 84, 67, 67, 65, 54, 71, 103, 65, 119, 73, 66, 65, 103, 73, 81, 81, 66, 114, 69, 90, 67, 71, 122, 69, 121, 69, 68, 68, 114, 118, 107, 69, 104, 114, 70, 72, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 66, 118, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 86, 86, 77, 120, 70, 122, 65, 86, 66, 103, 78, 86, 66, 65, 111, 84, 68, 108, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 76, 67, 66, 74, 98, 109, 77, 117, 77, 82, 56, 119, 72, 81, 89, 68, 86, 81, 81, 76, 69, 120, 90, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 66, 85, 99, 110, 86, 122, 100, 67, 66, 79, 10, 90, 88, 82, 51, 98, 51, 74, 114, 77, 84, 111, 119, 79, 65, 89, 68, 86, 81, 81, 76, 69, 122, 69, 111, 89, 121, 107, 103, 77, 106, 65, 119, 79, 67, 66, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 119, 103, 83, 87, 53, 106, 76, 105, 65, 116, 73, 69, 90, 118, 99, 105, 66, 104, 100, 88, 82, 111, 98, 51, 74, 112, 101, 109, 86, 107, 10, 73, 72, 86, 122, 90, 83, 66, 118, 98, 109, 120, 53, 77, 84, 103, 119, 78, 103, 89, 68, 86, 81, 81, 68, 69, 121, 57, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 66, 86, 98, 109, 108, 50, 90, 88, 74, 122, 89, 87, 119, 103, 85, 109, 57, 118, 100, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 10, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 84, 65, 101, 70, 119, 48, 119, 79, 68, 65, 48, 77, 68, 73, 119, 77, 68, 65, 119, 77, 68, 66, 97, 70, 119, 48, 122, 78, 122, 69, 121, 77, 68, 69, 121, 77, 122, 85, 53, 78, 84, 108, 97, 77, 73, 71, 57, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 10, 85, 122, 69, 88, 77, 66, 85, 71, 65, 49, 85, 69, 67, 104, 77, 79, 86, 109, 86, 121, 97, 86, 78, 112, 90, 50, 52, 115, 73, 69, 108, 117, 89, 121, 52, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 115, 84, 70, 108, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 73, 70, 82, 121, 100, 88, 78, 48, 73, 69, 53, 108, 100, 72, 100, 118, 10, 99, 109, 115, 120, 79, 106, 65, 52, 66, 103, 78, 86, 66, 65, 115, 84, 77, 83, 104, 106, 75, 83, 65, 121, 77, 68, 65, 52, 73, 70, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 76, 67, 66, 74, 98, 109, 77, 117, 73, 67, 48, 103, 82, 109, 57, 121, 73, 71, 70, 49, 100, 71, 104, 118, 99, 109, 108, 54, 90, 87, 81, 103, 100, 88, 78, 108, 10, 73, 71, 57, 117, 98, 72, 107, 120, 79, 68, 65, 50, 66, 103, 78, 86, 66, 65, 77, 84, 76, 49, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 73, 70, 86, 117, 97, 88, 90, 108, 99, 110, 78, 104, 98, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 10, 97, 71, 57, 121, 97, 88, 82, 53, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 120, 50, 69, 51, 88, 114, 69, 66, 78, 78, 116, 105, 49, 120, 87, 98, 47, 49, 104, 97, 106, 67, 77, 106, 10, 49, 109, 67, 79, 107, 100, 101, 81, 109, 73, 78, 54, 53, 108, 103, 90, 79, 73, 122, 70, 57, 117, 86, 107, 104, 98, 83, 105, 99, 102, 118, 116, 118, 98, 110, 97, 122, 85, 48, 65, 116, 77, 103, 116, 99, 54, 88, 72, 97, 88, 71, 86, 72, 122, 107, 56, 115, 107, 81, 72, 110, 79, 103, 79, 43, 107, 49, 75, 120, 67, 72, 102, 75, 87, 71, 80, 10, 77, 105, 74, 104, 103, 115, 87, 72, 72, 50, 54, 77, 102, 70, 56, 87, 73, 70, 70, 69, 48, 88, 66, 80, 86, 43, 114, 106, 72, 79, 80, 77, 101, 101, 53, 89, 50, 65, 55, 67, 115, 48, 87, 84, 119, 67, 122, 110, 109, 104, 99, 114, 101, 119, 65, 51, 101, 107, 69, 122, 101, 79, 69, 122, 52, 118, 77, 81, 71, 110, 43, 72, 76, 76, 55, 50, 10, 57, 102, 100, 67, 52, 117, 87, 47, 104, 50, 75, 74, 88, 119, 66, 76, 51, 56, 88, 100, 53, 72, 86, 69, 77, 107, 69, 54, 72, 110, 70, 117, 97, 99, 115, 76, 100, 85, 89, 73, 48, 99, 114, 83, 75, 53, 88, 81, 122, 47, 117, 53, 81, 71, 116, 107, 106, 70, 100, 78, 47, 66, 77, 82, 101, 89, 84, 116, 88, 108, 84, 50, 78, 74, 56, 73, 10, 65, 102, 77, 81, 74, 81, 89, 88, 83, 116, 114, 120, 72, 88, 112, 109, 97, 53, 104, 103, 90, 113, 84, 90, 55, 57, 73, 117, 103, 118, 72, 119, 55, 119, 110, 113, 82, 77, 107, 86, 97, 117, 73, 68, 98, 106, 80, 84, 114, 74, 57, 86, 65, 77, 102, 50, 67, 71, 113, 85, 117, 86, 47, 99, 52, 68, 80, 120, 104, 71, 68, 53, 87, 121, 99, 82, 10, 116, 80, 119, 87, 56, 114, 116, 87, 97, 111, 65, 108, 106, 81, 73, 68, 65, 81, 65, 66, 111, 52, 71, 121, 77, 73, 71, 118, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 71, 48, 71, 10, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 69, 77, 66, 71, 69, 119, 88, 54, 70, 100, 111, 70, 115, 119, 87, 84, 66, 88, 77, 70, 85, 87, 67, 87, 108, 116, 89, 87, 100, 108, 76, 50, 100, 112, 90, 106, 65, 104, 77, 66, 56, 119, 66, 119, 89, 70, 75, 119, 52, 68, 65, 104, 111, 69, 70, 73, 47, 108, 48, 120, 113, 71, 114, 73, 50, 79, 10, 97, 56, 80, 80, 103, 71, 114, 85, 83, 66, 103, 115, 101, 120, 107, 117, 77, 67, 85, 87, 73, 50, 104, 48, 100, 72, 65, 54, 76, 121, 57, 115, 98, 50, 100, 118, 76, 110, 90, 108, 99, 109, 108, 122, 97, 87, 100, 117, 76, 109, 78, 118, 98, 83, 57, 50, 99, 50, 120, 118, 90, 50, 56, 117, 90, 50, 108, 109, 77, 66, 48, 71, 65, 49, 85, 100, 10, 68, 103, 81, 87, 66, 66, 83, 50, 100, 47, 112, 112, 83, 69, 101, 102, 85, 120, 76, 86, 119, 117, 111, 72, 77, 110, 89, 72, 48, 90, 99, 72, 71, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, 67, 65, 81, 69, 65, 83, 118, 106, 52, 115, 65, 80, 109, 76, 71, 100, 55, 53, 74, 82, 51, 10, 89, 56, 120, 117, 84, 80, 108, 57, 68, 103, 51, 99, 121, 76, 107, 49, 117, 88, 66, 80, 89, 47, 111, 107, 43, 109, 121, 68, 106, 69, 101, 100, 79, 50, 80, 122, 109, 118, 108, 50, 77, 112, 87, 82, 115, 88, 101, 56, 114, 74, 113, 43, 115, 101, 81, 120, 73, 99, 97, 66, 108, 86, 90, 97, 68, 114, 72, 67, 49, 76, 71, 109, 87, 97, 122, 120, 10, 89, 56, 117, 52, 84, 66, 49, 90, 107, 69, 114, 118, 107, 66, 89, 111, 72, 49, 113, 117, 69, 80, 117, 66, 85, 68, 103, 77, 98, 77, 122, 120, 80, 99, 80, 49, 89, 43, 79, 122, 52, 121, 72, 74, 74, 68, 110, 112, 47, 82, 86, 109, 82, 118, 81, 98, 69, 100, 66, 78, 99, 54, 78, 57, 82, 118, 107, 57, 55, 97, 104, 102, 89, 116, 84, 120, 10, 80, 47, 106, 103, 100, 70, 99, 114, 71, 74, 50, 66, 116, 77, 81, 111, 50, 112, 83, 88, 112, 88, 68, 114, 114, 66, 50, 43, 66, 120, 72, 119, 49, 100, 118, 100, 53, 89, 122, 119, 49, 84, 75, 119, 103, 43, 90, 88, 52, 111, 43, 47, 118, 113, 71, 113, 118, 122, 48, 100, 116, 100, 81, 52, 54, 116, 101, 119, 88, 68, 112, 80, 97, 106, 43, 80, 10, 119, 71, 90, 115, 89, 54, 114, 112, 50, 97, 81, 87, 57, 73, 72, 82, 108, 82, 81, 79, 102, 99, 50, 86, 78, 78, 110, 83, 106, 51, 66, 122, 103, 88, 117, 99, 102, 114, 50, 89, 89, 100, 104, 70, 104, 53, 105, 81, 120, 101, 117, 71, 77, 77, 89, 49, 118, 47, 68, 47, 119, 49, 87, 73, 103, 48, 118, 118, 66, 90, 73, 71, 99, 102, 75, 52, 10, 109, 74, 79, 51, 55, 77, 50, 67, 89, 102, 69, 52, 53, 107, 43, 88, 109, 67, 112, 97, 106, 81, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 86, 101, 114, 105, 83, 105, 103, 110, 32, 67, 108, 97, 115, 115, 32, 51, 32, 80, 117, 98, 108, 105, 99, 32, 80, 114, 105, 109, 97, 114, 121, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 45, 32, 71, 52, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 104, 68, 67, 67, 65, 119, 113, 103, 65, 119, 73, 66, 65, 103, 73, 81, 76, 52, 68, 43, 73, 52, 119, 79, 73, 103, 57, 73, 90, 120, 73, 111, 107, 89, 101, 115, 115, 122, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 122, 67, 66, 121, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 10, 86, 86, 77, 120, 70, 122, 65, 86, 66, 103, 78, 86, 66, 65, 111, 84, 68, 108, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 76, 67, 66, 74, 98, 109, 77, 117, 77, 82, 56, 119, 72, 81, 89, 68, 86, 81, 81, 76, 69, 120, 90, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 66, 85, 99, 110, 86, 122, 100, 67, 66, 79, 90, 88, 82, 51, 10, 98, 51, 74, 114, 77, 84, 111, 119, 79, 65, 89, 68, 86, 81, 81, 76, 69, 122, 69, 111, 89, 121, 107, 103, 77, 106, 65, 119, 78, 121, 66, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 119, 103, 83, 87, 53, 106, 76, 105, 65, 116, 73, 69, 90, 118, 99, 105, 66, 104, 100, 88, 82, 111, 98, 51, 74, 112, 101, 109, 86, 107, 73, 72, 86, 122, 10, 90, 83, 66, 118, 98, 109, 120, 53, 77, 85, 85, 119, 81, 119, 89, 68, 86, 81, 81, 68, 69, 122, 120, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 66, 68, 98, 71, 70, 122, 99, 121, 65, 122, 73, 70, 66, 49, 89, 109, 120, 112, 89, 121, 66, 81, 99, 109, 108, 116, 89, 88, 74, 53, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 10, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 73, 67, 48, 103, 82, 122, 81, 119, 72, 104, 99, 78, 77, 68, 99, 120, 77, 84, 65, 49, 77, 68, 65, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 122, 103, 119, 77, 84, 69, 52, 77, 106, 77, 49, 79, 84, 85, 53, 87, 106, 67, 66, 121, 106, 69, 76, 10, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 122, 65, 86, 66, 103, 78, 86, 66, 65, 111, 84, 68, 108, 90, 108, 99, 109, 108, 84, 97, 87, 100, 117, 76, 67, 66, 74, 98, 109, 77, 117, 77, 82, 56, 119, 72, 81, 89, 68, 86, 81, 81, 76, 69, 120, 90, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 66, 85, 10, 99, 110, 86, 122, 100, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 77, 84, 111, 119, 79, 65, 89, 68, 86, 81, 81, 76, 69, 122, 69, 111, 89, 121, 107, 103, 77, 106, 65, 119, 78, 121, 66, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 119, 103, 83, 87, 53, 106, 76, 105, 65, 116, 73, 69, 90, 118, 99, 105, 66, 104, 100, 88, 82, 111, 10, 98, 51, 74, 112, 101, 109, 86, 107, 73, 72, 86, 122, 90, 83, 66, 118, 98, 109, 120, 53, 77, 85, 85, 119, 81, 119, 89, 68, 86, 81, 81, 68, 69, 122, 120, 87, 90, 88, 74, 112, 85, 50, 108, 110, 98, 105, 66, 68, 98, 71, 70, 122, 99, 121, 65, 122, 73, 70, 66, 49, 89, 109, 120, 112, 89, 121, 66, 81, 99, 109, 108, 116, 89, 88, 74, 53, 10, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 73, 67, 48, 103, 82, 122, 81, 119, 100, 106, 65, 81, 66, 103, 99, 113, 104, 107, 106, 79, 80, 81, 73, 66, 66, 103, 85, 114, 103, 81, 81, 65, 73, 103, 78, 105, 65, 65, 83, 110, 86, 110, 112, 56, 10, 85, 116, 112, 107, 109, 119, 52, 116, 88, 78, 104, 101, 114, 74, 73, 57, 47, 103, 72, 109, 71, 85, 111, 57, 70, 65, 78, 76, 43, 109, 65, 110, 73, 78, 109, 68, 105, 87, 110, 54, 86, 77, 97, 97, 71, 70, 53, 86, 75, 109, 84, 101, 66, 118, 97, 78, 83, 106, 117, 116, 69, 68, 120, 108, 80, 90, 67, 73, 66, 73, 110, 103, 77, 71, 71, 122, 10, 114, 108, 48, 66, 112, 51, 118, 101, 102, 76, 75, 43, 121, 109, 86, 104, 65, 73, 97, 117, 50, 111, 57, 55, 48, 73, 109, 116, 84, 82, 49, 90, 109, 107, 71, 120, 118, 69, 101, 65, 51, 74, 53, 105, 119, 47, 109, 106, 103, 98, 73, 119, 103, 97, 56, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 10, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 98, 81, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 81, 119, 69, 89, 84, 66, 102, 111, 86, 50, 103, 87, 122, 66, 90, 77, 70, 99, 119, 86, 82, 89, 74, 97, 87, 49, 104, 90, 50, 85, 118, 90, 50, 108, 109, 77, 67, 69, 119, 10, 72, 122, 65, 72, 66, 103, 85, 114, 68, 103, 77, 67, 71, 103, 81, 85, 106, 43, 88, 84, 71, 111, 97, 115, 106, 89, 53, 114, 119, 56, 43, 65, 97, 116, 82, 73, 71, 67, 120, 55, 71, 83, 52, 119, 74, 82, 89, 106, 97, 72, 82, 48, 99, 68, 111, 118, 76, 50, 120, 118, 90, 50, 56, 117, 100, 109, 86, 121, 97, 88, 78, 112, 90, 50, 52, 117, 10, 89, 50, 57, 116, 76, 51, 90, 122, 98, 71, 57, 110, 98, 121, 53, 110, 97, 87, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 76, 77, 87, 107, 102, 51, 117, 112, 109, 55, 107, 116, 83, 53, 74, 106, 52, 100, 52, 103, 89, 68, 115, 53, 98, 71, 49, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 68, 10, 65, 50, 103, 65, 77, 71, 85, 67, 77, 71, 89, 104, 68, 66, 103, 109, 89, 70, 111, 52, 101, 49, 90, 67, 52, 75, 102, 56, 78, 111, 82, 82, 107, 83, 65, 115, 100, 107, 49, 68, 80, 99, 81, 100, 104, 67, 80, 81, 114, 78, 90, 56, 78, 81, 98, 79, 122, 87, 109, 57, 107, 65, 51, 98, 98, 69, 104, 67, 72, 81, 54, 113, 81, 103, 73, 120, 10, 65, 74, 119, 57, 83, 68, 107, 106, 79, 86, 103, 97, 70, 82, 74, 90, 97, 112, 55, 118, 49, 86, 109, 121, 72, 86, 73, 115, 109, 88, 72, 78, 120, 121, 110, 102, 71, 121, 112, 104, 101, 51, 72, 82, 51, 118, 80, 65, 53, 81, 48, 54, 83, 113, 111, 116, 112, 57, 105, 71, 75, 116, 48, 117, 69, 65, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 78, 101, 116, 76, 111, 99, 107, 32, 65, 114, 97, 110, 121, 32, 40, 67, 108, 97, 115, 115, 32, 71, 111, 108, 100, 41, 32, 70, 197, 145, 116, 97, 110, 195, 186, 115, 195, 173, 116, 118, 195, 161, 110, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 70, 84, 67, 67, 65, 118, 50, 103, 65, 119, 73, 66, 65, 103, 73, 71, 83, 85, 69, 115, 53, 65, 65, 81, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 77, 73, 71, 110, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 73, 86, 84, 69, 82, 77, 65, 56, 71, 10, 65, 49, 85, 69, 66, 119, 119, 73, 81, 110, 86, 107, 89, 88, 66, 108, 99, 51, 81, 120, 70, 84, 65, 84, 66, 103, 78, 86, 66, 65, 111, 77, 68, 69, 53, 108, 100, 69, 120, 118, 89, 50, 115, 103, 83, 50, 90, 48, 76, 106, 69, 51, 77, 68, 85, 71, 65, 49, 85, 69, 67, 119, 119, 117, 86, 71, 70, 117, 119, 55, 112, 122, 119, 54, 49, 48, 10, 100, 115, 79, 104, 98, 110, 108, 114, 97, 87, 70, 107, 119, 55, 78, 114, 73, 67, 104, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 86, 122, 75, 84, 69, 49, 77, 68, 77, 71, 65, 49, 85, 69, 65, 119, 119, 115, 84, 109, 86, 48, 84, 71, 57, 106, 97, 121, 66, 66, 10, 99, 109, 70, 117, 101, 83, 65, 111, 81, 50, 120, 104, 99, 51, 77, 103, 82, 50, 57, 115, 90, 67, 107, 103, 82, 115, 87, 82, 100, 71, 70, 117, 119, 55, 112, 122, 119, 54, 49, 48, 100, 115, 79, 104, 98, 110, 107, 119, 72, 104, 99, 78, 77, 68, 103, 120, 77, 106, 69, 120, 77, 84, 85, 119, 79, 68, 73, 120, 87, 104, 99, 78, 77, 106, 103, 120, 10, 77, 106, 65, 50, 77, 84, 85, 119, 79, 68, 73, 120, 87, 106, 67, 66, 112, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 83, 70, 85, 120, 69, 84, 65, 80, 66, 103, 78, 86, 66, 65, 99, 77, 67, 69, 74, 49, 90, 71, 70, 119, 90, 88, 78, 48, 77, 82, 85, 119, 69, 119, 89, 68, 86, 81, 81, 75, 68, 65, 120, 79, 10, 90, 88, 82, 77, 98, 50, 78, 114, 73, 69, 116, 109, 100, 67, 52, 120, 78, 122, 65, 49, 66, 103, 78, 86, 66, 65, 115, 77, 76, 108, 82, 104, 98, 115, 79, 54, 99, 56, 79, 116, 100, 72, 98, 68, 111, 87, 53, 53, 97, 50, 108, 104, 90, 77, 79, 122, 97, 121, 65, 111, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 10, 98, 105, 66, 84, 90, 88, 74, 50, 97, 87, 78, 108, 99, 121, 107, 120, 78, 84, 65, 122, 66, 103, 78, 86, 66, 65, 77, 77, 76, 69, 53, 108, 100, 69, 120, 118, 89, 50, 115, 103, 81, 88, 74, 104, 98, 110, 107, 103, 75, 69, 78, 115, 89, 88, 78, 122, 73, 69, 100, 118, 98, 71, 81, 112, 73, 69, 98, 70, 107, 88, 82, 104, 98, 115, 79, 54, 10, 99, 56, 79, 116, 100, 72, 98, 68, 111, 87, 53, 53, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 120, 67, 82, 101, 99, 55, 53, 76, 98, 82, 84, 68, 111, 102, 84, 106, 108, 53, 66, 117, 10, 48, 106, 66, 70, 72, 106, 122, 117, 90, 57, 108, 107, 52, 66, 113, 75, 102, 56, 111, 119, 121, 111, 80, 106, 73, 77, 72, 106, 57, 68, 114, 84, 108, 70, 56, 97, 102, 70, 116, 116, 118, 122, 66, 80, 104, 67, 102, 50, 110, 120, 57, 74, 118, 77, 97, 90, 67, 112, 68, 121, 68, 47, 86, 47, 81, 52, 81, 51, 89, 49, 71, 76, 101, 113, 86, 119, 10, 47, 72, 112, 89, 122, 89, 54, 98, 55, 99, 78, 71, 98, 73, 82, 119, 88, 100, 114, 122, 65, 90, 65, 106, 47, 69, 52, 119, 113, 88, 55, 104, 74, 50, 80, 110, 55, 87, 81, 56, 111, 76, 106, 74, 77, 50, 80, 43, 70, 112, 68, 47, 115, 76, 106, 57, 49, 54, 106, 65, 119, 74, 82, 68, 67, 55, 98, 86, 87, 97, 97, 101, 86, 116, 65, 107, 10, 72, 51, 66, 53, 114, 57, 115, 53, 86, 65, 49, 108, 100, 100, 107, 86, 81, 90, 81, 66, 114, 49, 55, 115, 57, 111, 51, 120, 47, 54, 49, 107, 47, 105, 67, 97, 49, 49, 122, 114, 47, 113, 89, 102, 67, 71, 83, 106, 105, 51, 90, 86, 114, 82, 52, 55, 75, 71, 65, 117, 104, 121, 88, 111, 113, 113, 56, 102, 120, 109, 82, 71, 73, 76, 100, 119, 10, 102, 122, 122, 101, 83, 78, 117, 87, 85, 55, 99, 53, 100, 43, 81, 97, 52, 115, 99, 87, 104, 72, 97, 88, 87, 121, 43, 55, 71, 82, 87, 70, 43, 71, 109, 70, 57, 90, 109, 110, 113, 102, 73, 48, 112, 54, 109, 50, 112, 103, 80, 56, 98, 52, 89, 57, 86, 72, 120, 50, 66, 74, 116, 114, 43, 85, 66, 100, 65, 68, 84, 72, 76, 112, 108, 49, 10, 110, 101, 87, 73, 65, 54, 112, 78, 43, 65, 80, 83, 81, 110, 98, 65, 71, 119, 73, 68, 65, 75, 105, 76, 111, 48, 85, 119, 81, 122, 65, 83, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 67, 68, 65, 71, 65, 81, 72, 47, 65, 103, 69, 69, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 10, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 122, 80, 112, 110, 107, 47, 67, 50, 117, 78, 67, 108, 119, 66, 55, 122, 85, 47, 50, 77, 85, 57, 43, 68, 49, 53, 89, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 69, 66, 65, 75, 116, 47, 55, 104, 119, 87, 10, 113, 90, 119, 56, 85, 81, 67, 103, 119, 66, 69, 73, 66, 97, 101, 90, 53, 109, 56, 66, 105, 70, 82, 104, 98, 118, 71, 53, 71, 75, 49, 75, 114, 102, 54, 66, 81, 67, 79, 85, 76, 47, 116, 49, 102, 67, 56, 111, 83, 50, 73, 107, 103, 89, 73, 76, 57, 87, 72, 120, 72, 71, 54, 52, 89, 84, 106, 114, 103, 102, 112, 105, 111, 84, 116, 97, 10, 89, 116, 79, 85, 90, 99, 84, 104, 53, 109, 50, 67, 43, 67, 56, 108, 99, 76, 73, 104, 74, 115, 70, 121, 85, 82, 43, 77, 76, 77, 79, 69, 107, 77, 78, 97, 106, 55, 114, 80, 57, 75, 100, 108, 112, 101, 117, 89, 48, 102, 115, 70, 115, 107, 90, 49, 70, 83, 78, 113, 98, 52, 86, 106, 77, 73, 68, 119, 49, 90, 52, 102, 75, 82, 122, 67, 10, 98, 76, 66, 81, 87, 86, 50, 81, 87, 122, 117, 111, 68, 84, 68, 80, 118, 51, 49, 47, 122, 118, 71, 100, 103, 55, 51, 74, 82, 109, 52, 103, 112, 118, 108, 104, 85, 98, 111, 104, 76, 51, 117, 43, 112, 82, 86, 106, 111, 100, 83, 86, 104, 47, 71, 101, 117, 102, 79, 74, 56, 122, 50, 70, 117, 76, 106, 98, 118, 114, 87, 53, 75, 102, 110, 97, 10, 78, 119, 85, 65, 83, 90, 81, 68, 104, 69, 84, 110, 118, 48, 77, 120, 122, 51, 87, 76, 74, 100, 72, 48, 112, 109, 84, 49, 107, 118, 97, 114, 66, 101, 115, 57, 54, 97, 85, 76, 78, 109, 76, 97, 122, 65, 90, 102, 78, 111, 117, 50, 88, 106, 71, 52, 75, 118, 116, 101, 57, 110, 72, 102, 82, 67, 97, 101, 120, 79, 89, 78, 107, 98, 81, 117, 10, 100, 90, 87, 65, 85, 87, 112, 76, 77, 75, 97, 119, 89, 113, 71, 84, 56, 90, 118, 89, 122, 115, 82, 106, 100, 84, 57, 90, 82, 55, 69, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 116, 97, 97, 116, 32, 100, 101, 114, 32, 78, 101, 100, 101, 114, 108, 97, 110, 100, 101, 110, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 121, 106, 67, 67, 65, 55, 75, 103, 65, 119, 73, 66, 65, 103, 73, 69, 65, 74, 105, 87, 106, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 97, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 79, 84, 68, 69, 101, 77, 66, 119, 71, 65, 49, 85, 69, 10, 67, 103, 119, 86, 85, 51, 82, 104, 89, 88, 81, 103, 90, 71, 86, 121, 73, 69, 53, 108, 90, 71, 86, 121, 98, 71, 70, 117, 90, 71, 86, 117, 77, 83, 115, 119, 75, 81, 89, 68, 86, 81, 81, 68, 68, 67, 74, 84, 100, 71, 70, 104, 100, 67, 66, 107, 90, 88, 73, 103, 84, 109, 86, 107, 90, 88, 74, 115, 89, 87, 53, 107, 90, 87, 52, 103, 10, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 116, 73, 69, 99, 121, 77, 66, 52, 88, 68, 84, 65, 52, 77, 68, 77, 121, 78, 106, 69, 120, 77, 84, 103, 120, 78, 49, 111, 88, 68, 84, 73, 119, 77, 68, 77, 121, 78, 84, 69, 120, 77, 68, 77, 120, 77, 70, 111, 119, 87, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 10, 84, 107, 119, 120, 72, 106, 65, 99, 66, 103, 78, 86, 66, 65, 111, 77, 70, 86, 78, 48, 89, 87, 70, 48, 73, 71, 82, 108, 99, 105, 66, 79, 90, 87, 82, 108, 99, 109, 120, 104, 98, 109, 82, 108, 98, 106, 69, 114, 77, 67, 107, 71, 65, 49, 85, 69, 65, 119, 119, 105, 85, 51, 82, 104, 89, 88, 81, 103, 90, 71, 86, 121, 73, 69, 53, 108, 10, 90, 71, 86, 121, 98, 71, 70, 117, 90, 71, 86, 117, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 76, 83, 66, 72, 77, 106, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 77, 86, 90, 10, 53, 50, 57, 49, 113, 106, 53, 76, 110, 76, 87, 52, 114, 74, 52, 76, 53, 80, 110, 90, 121, 113, 116, 100, 106, 55, 85, 53, 69, 73, 76, 88, 114, 49, 72, 103, 79, 43, 69, 65, 83, 71, 114, 80, 50, 117, 69, 71, 81, 120, 71, 90, 113, 104, 81, 108, 69, 113, 48, 105, 54, 65, 66, 116, 81, 56, 83, 112, 117, 79, 85, 102, 105, 85, 116, 110, 10, 118, 87, 70, 73, 55, 47, 51, 83, 52, 71, 67, 73, 53, 98, 107, 89, 89, 67, 106, 68, 100, 121, 117, 116, 115, 68, 101, 113, 78, 57, 53, 107, 87, 83, 112, 71, 86, 43, 82, 76, 117, 102, 103, 51, 102, 78, 85, 50, 53, 52, 68, 66, 116, 118, 80, 85, 90, 53, 117, 87, 54, 77, 55, 88, 120, 103, 112, 84, 48, 71, 116, 74, 108, 118, 79, 106, 10, 67, 119, 86, 51, 83, 80, 99, 108, 53, 88, 67, 115, 77, 66, 81, 103, 74, 101, 78, 47, 100, 86, 114, 108, 83, 80, 104, 79, 101, 119, 77, 72, 66, 80, 113, 67, 89, 89, 100, 117, 56, 68, 118, 69, 112, 77, 102, 81, 57, 88, 81, 43, 112, 86, 48, 97, 67, 80, 75, 98, 74, 100, 76, 50, 114, 65, 81, 109, 80, 108, 85, 54, 89, 105, 105, 108, 10, 101, 55, 73, 119, 114, 47, 103, 51, 119, 116, 71, 54, 49, 106, 106, 57, 57, 79, 57, 74, 77, 68, 101, 90, 74, 105, 70, 73, 104, 81, 71, 112, 53, 82, 98, 110, 51, 74, 66, 86, 51, 119, 47, 111, 79, 77, 50, 90, 78, 121, 70, 80, 88, 102, 85, 105, 98, 50, 114, 70, 69, 104, 90, 103, 70, 49, 88, 121, 90, 87, 97, 109, 112, 122, 67, 82, 10, 79, 77, 69, 52, 72, 89, 89, 69, 104, 76, 111, 97, 74, 88, 104, 101, 110, 97, 47, 77, 85, 71, 68, 87, 69, 52, 100, 83, 55, 87, 77, 102, 98, 87, 86, 57, 119, 104, 85, 89, 100, 77, 114, 104, 102, 109, 81, 112, 106, 72, 76, 89, 70, 104, 78, 57, 67, 48, 108, 75, 56, 83, 103, 98, 73, 72, 82, 114, 120, 84, 51, 100, 115, 75, 112, 73, 10, 67, 84, 48, 117, 103, 112, 84, 78, 71, 109, 88, 90, 75, 52, 105, 97, 109, 98, 119, 89, 102, 112, 47, 117, 102, 87, 90, 56, 80, 114, 50, 85, 117, 73, 72, 79, 122, 90, 103, 119, 101, 77, 70, 118, 90, 57, 67, 43, 88, 43, 66, 111, 55, 100, 55, 105, 115, 99, 107, 115, 87, 88, 105, 83, 113, 116, 56, 114, 89, 71, 80, 121, 53, 86, 54, 53, 10, 52, 56, 114, 54, 102, 49, 67, 71, 80, 113, 73, 48, 71, 65, 119, 74, 97, 67, 103, 82, 72, 79, 84, 104, 117, 86, 119, 43, 82, 55, 111, 121, 80, 120, 106, 77, 87, 52, 84, 49, 56, 50, 116, 48, 120, 72, 74, 48, 52, 101, 79, 76, 111, 69, 113, 57, 106, 87, 89, 118, 54, 113, 48, 49, 50, 105, 68, 84, 105, 73, 74, 104, 56, 66, 73, 105, 10, 116, 114, 122, 81, 49, 97, 84, 115, 114, 49, 83, 73, 74, 83, 81, 56, 112, 50, 50, 120, 99, 105, 107, 47, 80, 108, 101, 109, 102, 49, 87, 118, 98, 105, 98, 71, 47, 117, 102, 77, 81, 70, 120, 82, 82, 73, 69, 75, 101, 78, 53, 75, 122, 108, 87, 47, 72, 100, 88, 90, 116, 49, 98, 118, 56, 72, 98, 47, 67, 51, 109, 49, 114, 55, 51, 55, 10, 113, 87, 109, 82, 82, 112, 100, 111, 103, 66, 81, 50, 72, 98, 78, 47, 117, 121, 109, 89, 78, 113, 85, 103, 43, 111, 74, 103, 89, 106, 79, 107, 55, 78, 97, 54, 66, 54, 100, 117, 120, 99, 56, 85, 112, 117, 102, 87, 107, 106, 84, 89, 103, 102, 88, 56, 72, 86, 50, 113, 88, 66, 55, 50, 111, 48, 48, 55, 117, 80, 99, 53, 65, 103, 77, 66, 10, 65, 65, 71, 106, 103, 90, 99, 119, 103, 90, 81, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 66, 83, 66, 103, 78, 86, 72, 83, 65, 69, 83, 122, 66, 74, 77, 69, 99, 71, 66, 70, 85, 100, 73, 65, 65, 119, 80, 122, 65, 57, 66, 103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 67, 10, 65, 82, 89, 120, 97, 72, 82, 48, 99, 68, 111, 118, 76, 51, 100, 51, 100, 121, 53, 119, 97, 50, 108, 118, 100, 109, 86, 121, 97, 71, 86, 112, 90, 67, 53, 117, 98, 67, 57, 119, 98, 50, 120, 112, 89, 50, 108, 108, 99, 121, 57, 121, 98, 50, 57, 48, 76, 88, 66, 118, 98, 71, 108, 106, 101, 83, 49, 72, 77, 106, 65, 79, 66, 103, 78, 86, 10, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 74, 70, 111, 77, 111, 99, 86, 72, 89, 110, 105, 116, 102, 71, 115, 78, 105, 103, 48, 106, 81, 116, 56, 89, 111, 106, 114, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 10, 65, 52, 73, 67, 65, 81, 67, 111, 81, 85, 112, 110, 75, 112, 75, 66, 103, 108, 66, 117, 52, 100, 102, 89, 115, 122, 107, 55, 56, 119, 73, 86, 67, 86, 66, 82, 55, 121, 50, 57, 74, 72, 117, 73, 104, 106, 118, 53, 116, 76, 121, 83, 67, 90, 97, 53, 57, 115, 67, 114, 73, 50, 65, 71, 101, 89, 119, 82, 84, 108, 72, 83, 101, 89, 65, 122, 10, 43, 53, 49, 73, 118, 117, 120, 66, 81, 52, 69, 102, 102, 107, 100, 65, 72, 79, 86, 54, 67, 77, 113, 113, 105, 51, 87, 116, 70, 77, 84, 67, 54, 71, 89, 56, 103, 103, 101, 110, 53, 105, 101, 67, 87, 120, 106, 109, 68, 50, 55, 90, 85, 68, 54, 75, 81, 104, 103, 112, 120, 114, 82, 87, 47, 70, 89, 81, 111, 65, 85, 88, 118, 81, 119, 106, 10, 102, 47, 83, 84, 55, 90, 119, 97, 85, 98, 55, 100, 82, 85, 71, 47, 107, 83, 83, 48, 72, 52, 122, 112, 88, 56, 57, 55, 73, 90, 109, 102, 108, 90, 56, 53, 79, 107, 89, 99, 98, 80, 110, 78, 101, 53, 121, 81, 122, 83, 105, 112, 120, 54, 108, 86, 117, 54, 120, 105, 78, 71, 73, 49, 69, 48, 115, 85, 79, 108, 87, 68, 117, 89, 97, 78, 10, 107, 113, 98, 71, 57, 65, 99, 108, 86, 77, 119, 87, 86, 120, 74, 75, 103, 110, 106, 73, 70, 78, 107, 88, 103, 105, 89, 116, 88, 83, 65, 102, 101, 97, 55, 43, 49, 72, 65, 87, 70, 112, 87, 68, 50, 68, 85, 53, 47, 49, 74, 100, 100, 82, 119, 87, 120, 82, 78, 86, 122, 48, 102, 77, 100, 87, 86, 83, 83, 116, 55, 119, 115, 75, 102, 107, 10, 67, 112, 89, 76, 43, 54, 51, 67, 52, 105, 87, 69, 115, 116, 51, 107, 118, 88, 53, 90, 98, 74, 118, 119, 56, 78, 106, 110, 121, 118, 76, 112, 108, 122, 104, 43, 105, 98, 55, 77, 43, 122, 107, 88, 89, 84, 57, 121, 50, 122, 113, 82, 50, 71, 85, 66, 71, 82, 50, 116, 85, 75, 82, 88, 67, 110, 120, 76, 118, 74, 120, 120, 99, 121, 112, 70, 10, 85, 82, 109, 70, 122, 73, 55, 57, 82, 54, 100, 48, 108, 82, 50, 111, 48, 97, 57, 79, 70, 55, 70, 112, 74, 115, 75, 113, 101, 70, 100, 98, 120, 85, 50, 110, 53, 90, 52, 70, 70, 53, 84, 75, 115, 108, 43, 103, 83, 82, 105, 78, 78, 79, 107, 109, 98, 69, 103, 101, 113, 109, 105, 83, 66, 101, 71, 67, 99, 49, 113, 98, 51, 65, 100, 98, 10, 67, 71, 49, 57, 110, 100, 101, 78, 73, 100, 110, 56, 70, 67, 67, 113, 119, 107, 88, 102, 80, 43, 99, 65, 115, 108, 72, 107, 119, 118, 103, 70, 117, 88, 107, 97, 106, 68, 84, 122, 110, 108, 118, 107, 78, 49, 116, 114, 83, 116, 56, 115, 86, 52, 112, 65, 87, 106, 97, 54, 51, 88, 86, 69, 67, 68, 100, 67, 99, 65, 122, 43, 51, 70, 52, 104, 10, 111, 75, 79, 75, 119, 74, 67, 99, 97, 78, 112, 81, 53, 107, 85, 81, 82, 51, 105, 50, 84, 116, 74, 108, 121, 99, 77, 51, 51, 43, 70, 67, 89, 55, 66, 88, 78, 48, 85, 116, 101, 52, 113, 99, 118, 119, 88, 113, 90, 86, 85, 122, 57, 122, 107, 81, 120, 83, 103, 113, 73, 88, 111, 98, 105, 115, 81, 107, 43, 84, 56, 86, 121, 74, 111, 86, 10, 73, 80, 86, 86, 89, 112, 98, 116, 98, 90, 78, 81, 118, 79, 83, 113, 101, 75, 51, 90, 121, 119, 112, 108, 104, 54, 90, 109, 119, 99, 83, 66, 111, 51, 99, 54, 87, 66, 52, 76, 55, 111, 79, 76, 110, 82, 55, 83, 85, 113, 84, 77, 72, 87, 43, 119, 109, 71, 50, 85, 77, 98, 88, 52, 99, 81, 114, 99, 117, 102, 120, 57, 77, 109, 68, 109, 10, 54, 54, 43, 75, 65, 81, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 72, 111, 110, 103, 107, 111, 110, 103, 32, 80, 111, 115, 116, 32, 82, 111, 111, 116, 32, 67, 65, 32, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 77, 68, 67, 67, 65, 104, 105, 103, 65, 119, 73, 66, 65, 103, 73, 67, 65, 43, 103, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 82, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 83, 69, 115, 120, 70, 106, 65, 85, 66, 103, 78, 86, 66, 65, 111, 84, 10, 68, 85, 104, 118, 98, 109, 100, 114, 98, 50, 53, 110, 73, 70, 66, 118, 99, 51, 81, 120, 73, 68, 65, 101, 66, 103, 78, 86, 66, 65, 77, 84, 70, 48, 104, 118, 98, 109, 100, 114, 98, 50, 53, 110, 73, 70, 66, 118, 99, 51, 81, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 120, 77, 66, 52, 88, 68, 84, 65, 122, 77, 68, 85, 120, 10, 78, 84, 65, 49, 77, 84, 77, 120, 78, 70, 111, 88, 68, 84, 73, 122, 77, 68, 85, 120, 78, 84, 65, 48, 78, 84, 73, 121, 79, 86, 111, 119, 82, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 83, 69, 115, 120, 70, 106, 65, 85, 66, 103, 78, 86, 66, 65, 111, 84, 68, 85, 104, 118, 98, 109, 100, 114, 98, 50, 53, 110, 10, 73, 70, 66, 118, 99, 51, 81, 120, 73, 68, 65, 101, 66, 103, 78, 86, 66, 65, 77, 84, 70, 48, 104, 118, 98, 109, 100, 114, 98, 50, 53, 110, 73, 70, 66, 118, 99, 51, 81, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 120, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 10, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 114, 80, 56, 52, 116, 117, 108, 109, 65, 107, 110, 106, 111, 114, 84, 104, 107, 80, 108, 65, 106, 51, 110, 53, 52, 114, 49, 53, 47, 103, 75, 57, 55, 105, 83, 83, 72, 83, 76, 50, 50, 111, 86, 121, 97, 102, 55, 88, 80, 119, 110, 85, 51, 90, 71, 49, 10, 65, 112, 122, 81, 106, 86, 114, 104, 86, 99, 78, 81, 104, 114, 107, 112, 74, 115, 76, 106, 50, 97, 68, 120, 97, 81, 77, 111, 73, 73, 66, 70, 73, 105, 49, 87, 112, 122, 116, 85, 108, 86, 89, 105, 87, 82, 56, 111, 51, 120, 56, 103, 80, 87, 50, 105, 78, 114, 52, 106, 111, 76, 70, 117, 116, 98, 69, 110, 80, 122, 108, 84, 67, 101, 113, 114, 10, 97, 117, 104, 48, 115, 115, 74, 108, 88, 73, 54, 47, 102, 77, 78, 52, 104, 77, 50, 101, 70, 118, 122, 49, 76, 107, 56, 103, 75, 103, 105, 102, 100, 47, 80, 70, 72, 115, 83, 97, 85, 109, 89, 101, 83, 70, 55, 106, 69, 65, 97, 80, 73, 112, 106, 104, 90, 89, 52, 98, 88, 83, 78, 109, 79, 55, 105, 108, 77, 108, 72, 73, 104, 113, 113, 104, 10, 113, 90, 53, 47, 100, 112, 84, 67, 112, 109, 121, 51, 81, 102, 68, 86, 121, 65, 89, 52, 53, 116, 81, 77, 52, 118, 77, 55, 84, 71, 49, 81, 106, 77, 83, 68, 74, 56, 69, 84, 104, 70, 107, 57, 110, 110, 86, 48, 116, 116, 103, 67, 88, 106, 113, 81, 101, 115, 66, 67, 78, 110, 76, 115, 97, 107, 51, 99, 55, 56, 81, 65, 51, 120, 77, 89, 10, 86, 49, 56, 109, 101, 77, 106, 87, 67, 110, 108, 51, 118, 47, 101, 118, 116, 51, 97, 53, 112, 81, 117, 69, 70, 49, 48, 81, 54, 109, 47, 104, 113, 53, 85, 82, 88, 50, 48, 56, 111, 49, 120, 78, 103, 49, 118, 121, 115, 120, 109, 75, 103, 73, 115, 76, 104, 119, 73, 68, 65, 81, 65, 66, 111, 121, 89, 119, 74, 68, 65, 83, 66, 103, 78, 86, 10, 72, 82, 77, 66, 65, 102, 56, 69, 67, 68, 65, 71, 65, 81, 72, 47, 65, 103, 69, 68, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 120, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 68, 107, 98, 86, 80, 75, 55, 105, 10, 104, 57, 108, 101, 103, 89, 115, 67, 109, 69, 69, 73, 106, 69, 121, 56, 50, 116, 118, 117, 74, 120, 117, 67, 53, 50, 112, 70, 55, 66, 97, 76, 84, 52, 87, 103, 56, 55, 74, 119, 118, 86, 113, 87, 117, 115, 112, 117, 98, 101, 53, 71, 105, 50, 55, 110, 75, 105, 54, 87, 115, 120, 107, 122, 54, 55, 83, 102, 113, 76, 73, 51, 55, 112, 105, 111, 10, 108, 55, 89, 117, 116, 109, 99, 110, 49, 75, 90, 74, 47, 82, 121, 84, 90, 88, 97, 101, 81, 105, 47, 99, 73, 109, 121, 97, 84, 47, 74, 97, 70, 84, 109, 120, 99, 100, 99, 114, 85, 101, 104, 116, 72, 74, 106, 65, 50, 83, 114, 48, 111, 89, 74, 55, 49, 99, 108, 66, 111, 105, 77, 66, 100, 68, 104, 86, 105, 119, 43, 53, 76, 109, 101, 105, 10, 73, 65, 81, 51, 50, 112, 119, 76, 48, 120, 99, 104, 52, 73, 43, 88, 101, 84, 82, 118, 104, 69, 103, 67, 73, 68, 77, 98, 53, 106, 82, 69, 110, 53, 70, 119, 57, 73, 66, 101, 104, 69, 80, 67, 75, 100, 74, 115, 69, 104, 84, 107, 89, 89, 50, 115, 69, 74, 67, 101, 104, 70, 67, 55, 56, 74, 90, 118, 82, 90, 43, 75, 56, 56, 112, 115, 10, 84, 47, 111, 82, 79, 104, 85, 86, 82, 115, 80, 78, 72, 52, 78, 98, 76, 85, 69, 83, 55, 86, 66, 110, 81, 82, 77, 57, 73, 97, 117, 85, 105, 113, 112, 79, 102, 77, 71, 120, 43, 54, 102, 87, 116, 83, 99, 118, 108, 54, 116, 117, 52, 66, 51, 105, 48, 82, 119, 115, 72, 48, 84, 105, 47, 76, 54, 82, 111, 90, 122, 55, 49, 105, 108, 84, 10, 99, 52, 97, 102, 85, 57, 104, 68, 68, 108, 51, 87, 89, 52, 74, 120, 72, 89, 66, 48, 121, 118, 98, 105, 65, 109, 118, 90, 87, 103, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 101, 99, 117, 114, 101, 83, 105, 103, 110, 32, 82, 111, 111, 116, 67, 65, 49, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 98, 84, 67, 67, 65, 108, 87, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 89, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 75, 85, 68, 69, 114, 77, 67, 107, 71, 65, 49, 85, 69, 67, 104, 77, 105, 10, 83, 109, 70, 119, 89, 87, 52, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 84, 90, 88, 74, 50, 97, 87, 78, 108, 99, 121, 119, 103, 83, 87, 53, 106, 76, 106, 69, 99, 77, 66, 111, 71, 65, 49, 85, 69, 65, 120, 77, 84, 85, 50, 86, 106, 100, 88, 74, 108, 85, 50, 108, 110, 98, 105, 66, 83, 10, 98, 50, 57, 48, 81, 48, 69, 120, 77, 84, 65, 101, 70, 119, 48, 119, 79, 84, 65, 48, 77, 68, 103, 119, 78, 68, 85, 50, 78, 68, 100, 97, 70, 119, 48, 121, 79, 84, 65, 48, 77, 68, 103, 119, 78, 68, 85, 50, 78, 68, 100, 97, 77, 70, 103, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 112, 81, 77, 83, 115, 119, 10, 75, 81, 89, 68, 86, 81, 81, 75, 69, 121, 74, 75, 89, 88, 66, 104, 98, 105, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 86, 122, 76, 67, 66, 74, 98, 109, 77, 117, 77, 82, 119, 119, 71, 103, 89, 68, 86, 81, 81, 68, 69, 120, 78, 84, 90, 87, 78, 49, 10, 99, 109, 86, 84, 97, 87, 100, 117, 73, 70, 74, 118, 98, 51, 82, 68, 81, 84, 69, 120, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 47, 88, 101, 113, 112, 82, 121, 81, 66, 84, 118, 76, 10, 84, 74, 115, 122, 105, 49, 111, 85, 82, 97, 84, 110, 107, 66, 98, 82, 51, 49, 102, 83, 73, 82, 67, 107, 70, 47, 51, 102, 114, 78, 89, 102, 112, 43, 84, 98, 102, 80, 102, 115, 51, 55, 103, 68, 50, 112, 82, 89, 47, 86, 49, 121, 102, 73, 119, 47, 88, 119, 70, 110, 100, 66, 87, 87, 52, 119, 73, 56, 104, 57, 117, 117, 121, 119, 71, 79, 10, 119, 118, 78, 109, 120, 111, 86, 70, 57, 65, 76, 71, 79, 114, 86, 105, 115, 113, 47, 54, 110, 76, 43, 107, 53, 116, 83, 65, 77, 74, 106, 122, 68, 98, 97, 84, 106, 54, 110, 85, 50, 68, 98, 121, 115, 80, 121, 75, 121, 105, 121, 104, 70, 84, 79, 86, 77, 100, 114, 65, 71, 47, 76, 117, 89, 112, 109, 71, 89, 122, 43, 47, 51, 90, 77, 113, 10, 103, 54, 104, 50, 117, 82, 77, 102, 116, 56, 53, 79, 81, 111, 87, 80, 73, 117, 99, 117, 71, 118, 75, 86, 67, 98, 73, 70, 116, 85, 82, 79, 100, 54, 69, 103, 118, 97, 110, 121, 84, 103, 112, 57, 85, 75, 51, 49, 66, 81, 49, 70, 84, 48, 90, 120, 47, 83, 103, 43, 85, 47, 115, 69, 50, 67, 51, 88, 90, 82, 49, 75, 71, 47, 114, 80, 10, 79, 55, 65, 120, 109, 106, 86, 117, 121, 73, 115, 71, 48, 119, 67, 82, 56, 112, 81, 73, 90, 85, 121, 120, 78, 65, 89, 65, 101, 111, 110, 105, 56, 77, 99, 68, 87, 99, 47, 86, 49, 117, 105, 110, 77, 114, 80, 109, 109, 69, 67, 71, 120, 99, 48, 110, 69, 111, 118, 77, 101, 56, 54, 51, 69, 84, 120, 105, 89, 65, 99, 106, 80, 105, 116, 65, 10, 98, 112, 83, 65, 67, 87, 50, 50, 115, 50, 57, 51, 98, 122, 85, 73, 85, 80, 115, 67, 104, 56, 85, 43, 105, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 87, 47, 104, 78, 84, 55, 75, 108, 104, 116, 81, 54, 48, 118, 70, 106, 109, 113, 67, 43, 67, 102, 90, 88, 10, 116, 57, 52, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 75, 67, 104, 10, 79, 66, 90, 109, 76, 113, 100, 87, 72, 121, 71, 99, 66, 118, 111, 100, 55, 98, 107, 105, 120, 84, 103, 109, 50, 69, 53, 80, 55, 75, 78, 47, 101, 100, 53, 71, 73, 97, 71, 72, 100, 52, 56, 72, 67, 74, 113, 121, 112, 77, 87, 118, 68, 122, 75, 89, 67, 51, 120, 109, 75, 98, 97, 98, 102, 83, 86, 83, 83, 85, 79, 114, 84, 67, 52, 114, 10, 98, 110, 112, 119, 114, 120, 89, 79, 52, 119, 74, 115, 43, 48, 76, 109, 71, 74, 49, 70, 50, 70, 88, 73, 54, 68, 118, 100, 53, 43, 72, 48, 76, 103, 115, 99, 78, 70, 120, 115, 87, 69, 114, 55, 106, 73, 104, 81, 88, 53, 85, 99, 118, 43, 50, 114, 73, 114, 86, 108, 115, 52, 87, 54, 110, 103, 43, 52, 114, 101, 86, 54, 71, 52, 112, 81, 10, 79, 104, 50, 57, 68, 98, 120, 55, 86, 70, 65, 76, 117, 85, 75, 118, 86, 97, 65, 89, 103, 97, 49, 108, 109, 101, 43, 43, 53, 74, 121, 47, 120, 73, 87, 114, 81, 98, 74, 85, 98, 57, 119, 108, 122, 101, 49, 52, 52, 111, 52, 77, 106, 81, 108, 74, 51, 87, 78, 55, 87, 109, 109, 87, 65, 105, 71, 111, 118, 86, 74, 90, 54, 88, 48, 49, 10, 121, 56, 104, 83, 121, 110, 43, 66, 47, 116, 108, 114, 48, 47, 99, 82, 55, 83, 88, 102, 43, 79, 102, 53, 112, 80, 112, 121, 108, 52, 82, 84, 68, 97, 88, 81, 77, 104, 104, 82, 100, 108, 107, 85, 98, 65, 47, 114, 55, 70, 43, 65, 106, 72, 86, 68, 103, 56, 79, 70, 109, 80, 57, 77, 110, 105, 48, 78, 53, 72, 101, 68, 107, 48, 54, 49, 10, 108, 103, 101, 76, 75, 66, 79, 98, 106, 66, 109, 78, 81, 83, 100, 74, 81, 79, 55, 101, 53, 105, 78, 69, 79, 100, 121, 104, 73, 116, 97, 54, 65, 47, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 67, 69, 68, 73, 67, 79, 77, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 116, 84, 67, 67, 65, 53, 50, 103, 65, 119, 73, 66, 65, 103, 73, 73, 89, 89, 51, 72, 104, 106, 115, 66, 103, 103, 85, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 82, 68, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 65, 119, 119, 78, 81, 85, 78, 70, 82, 69, 108, 68, 10, 84, 48, 48, 103, 85, 109, 57, 118, 100, 68, 69, 77, 77, 65, 111, 71, 65, 49, 85, 69, 67, 119, 119, 68, 85, 69, 116, 74, 77, 81, 56, 119, 68, 81, 89, 68, 86, 81, 81, 75, 68, 65, 90, 70, 82, 69, 108, 68, 84, 48, 48, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 86, 84, 77, 66, 52, 88, 68, 84, 65, 52, 10, 77, 68, 81, 120, 79, 68, 69, 50, 77, 106, 81, 121, 77, 108, 111, 88, 68, 84, 73, 52, 77, 68, 81, 120, 77, 122, 69, 50, 77, 106, 81, 121, 77, 108, 111, 119, 82, 68, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 65, 119, 119, 78, 81, 85, 78, 70, 82, 69, 108, 68, 84, 48, 48, 103, 85, 109, 57, 118, 100, 68, 69, 77, 77, 65, 111, 71, 10, 65, 49, 85, 69, 67, 119, 119, 68, 85, 69, 116, 74, 77, 81, 56, 119, 68, 81, 89, 68, 86, 81, 81, 75, 68, 65, 90, 70, 82, 69, 108, 68, 84, 48, 48, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 86, 84, 77, 73, 73, 67, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 10, 65, 65, 79, 67, 65, 103, 56, 65, 77, 73, 73, 67, 67, 103, 75, 67, 65, 103, 69, 65, 47, 53, 75, 86, 52, 87, 103, 71, 100, 114, 81, 115, 121, 70, 104, 73, 121, 118, 50, 65, 86, 67, 108, 86, 89, 121, 84, 47, 107, 71, 87, 98, 69, 72, 86, 55, 119, 50, 114, 98, 89, 103, 73, 66, 56, 104, 105, 71, 116, 88, 120, 97, 79, 76, 72, 107, 10, 87, 76, 110, 55, 48, 57, 103, 116, 110, 55, 48, 121, 78, 55, 56, 115, 70, 87, 50, 43, 116, 102, 81, 104, 48, 104, 79, 82, 50, 81, 101, 116, 65, 81, 88, 87, 56, 55, 49, 51, 122, 108, 57, 67, 103, 81, 114, 53, 97, 117, 79, 68, 65, 75, 103, 114, 76, 108, 85, 84, 89, 52, 72, 75, 82, 120, 120, 55, 88, 66, 90, 88, 101, 104, 117, 68, 10, 89, 65, 81, 54, 80, 109, 88, 68, 122, 81, 72, 101, 51, 113, 84, 87, 68, 76, 113, 79, 51, 116, 107, 69, 55, 104, 100, 87, 73, 112, 117, 80, 89, 47, 49, 78, 70, 103, 117, 51, 101, 51, 101, 77, 43, 83, 87, 49, 48, 87, 50, 90, 69, 105, 53, 80, 71, 114, 106, 109, 54, 103, 83, 83, 114, 106, 48, 82, 117, 86, 70, 67, 80, 89, 101, 119, 10, 77, 89, 87, 118, 101, 86, 113, 99, 47, 117, 100, 79, 88, 112, 74, 80, 81, 47, 121, 114, 79, 113, 50, 108, 69, 105, 90, 109, 117, 101, 73, 77, 49, 53, 106, 79, 49, 70, 105, 108, 108, 85, 65, 75, 116, 48, 83, 100, 69, 51, 81, 114, 119, 113, 88, 114, 73, 104, 87, 89, 69, 78, 105, 76, 120, 81, 83, 102, 72, 89, 57, 103, 53, 81, 89, 98, 10, 109, 56, 43, 53, 101, 97, 65, 57, 111, 105, 77, 47, 81, 106, 57, 114, 43, 104, 119, 68, 101, 122, 67, 78, 122, 109, 122, 65, 118, 43, 89, 98, 88, 55, 57, 110, 117, 73, 81, 90, 49, 82, 88, 118, 101, 56, 117, 81, 78, 106, 70, 105, 121, 98, 119, 67, 113, 48, 90, 102, 109, 47, 52, 97, 97, 74, 81, 48, 80, 90, 67, 79, 114, 102, 98, 107, 10, 72, 81, 108, 47, 83, 111, 103, 52, 80, 55, 53, 110, 47, 84, 83, 87, 57, 82, 50, 56, 77, 72, 84, 76, 79, 79, 55, 86, 98, 75, 118, 85, 47, 80, 81, 65, 116, 119, 66, 98, 104, 84, 73, 87, 100, 106, 80, 112, 50, 75, 79, 90, 110, 81, 85, 65, 113, 104, 98, 109, 56, 52, 70, 57, 98, 51, 50, 113, 104, 109, 50, 116, 70, 88, 84, 84, 10, 120, 75, 74, 120, 113, 118, 81, 85, 102, 101, 99, 121, 117, 66, 43, 56, 49, 102, 70, 79, 118, 87, 56, 88, 65, 106, 110, 88, 68, 112, 86, 67, 79, 115, 99, 65, 80, 117, 107, 109, 89, 120, 72, 113, 67, 57, 70, 75, 47, 120, 105, 100, 115, 116, 100, 55, 76, 122, 114, 90, 108, 118, 118, 111, 72, 112, 75, 117, 69, 49, 88, 73, 50, 83, 102, 50, 10, 51, 69, 103, 98, 115, 67, 84, 66, 104, 101, 78, 51, 110, 90, 113, 107, 56, 119, 119, 82, 72, 81, 51, 73, 116, 66, 84, 117, 116, 89, 74, 88, 67, 98, 56, 103, 87, 72, 56, 118, 73, 105, 80, 89, 99, 77, 116, 53, 98, 77, 108, 76, 56, 113, 107, 113, 121, 80, 121, 72, 75, 57, 99, 97, 85, 80, 103, 110, 54, 67, 57, 68, 52, 122, 113, 57, 10, 50, 70, 100, 120, 47, 99, 54, 109, 85, 108, 118, 53, 51, 85, 51, 116, 53, 102, 90, 118, 105, 101, 50, 55, 107, 53, 120, 50, 73, 88, 88, 119, 107, 107, 119, 112, 57, 121, 43, 99, 65, 83, 55, 43, 85, 69, 97, 101, 90, 65, 119, 85, 115, 119, 100, 98, 120, 99, 74, 122, 98, 80, 69, 72, 88, 69, 85, 107, 70, 68, 87, 117, 103, 47, 70, 113, 10, 84, 89, 108, 54, 43, 114, 80, 89, 76, 87, 98, 119, 78, 111, 102, 49, 75, 49, 77, 67, 65, 119, 69, 65, 65, 97, 79, 66, 113, 106, 67, 66, 112, 122, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 56, 71, 65, 49, 85, 100, 73, 119, 81, 89, 77, 66, 97, 65, 70, 75, 97, 122, 10, 52, 83, 115, 114, 83, 98, 98, 88, 99, 54, 71, 113, 108, 80, 85, 66, 53, 51, 78, 108, 84, 75, 120, 81, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 104, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 112, 114, 80, 104, 75, 121, 116, 74, 116, 116, 100, 122, 111, 97, 113, 85, 10, 57, 81, 72, 110, 99, 50, 86, 77, 114, 70, 65, 119, 82, 65, 89, 68, 86, 82, 48, 103, 66, 68, 48, 119, 79, 122, 65, 53, 66, 103, 82, 86, 72, 83, 65, 65, 77, 68, 69, 119, 76, 119, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 103, 69, 87, 73, 50, 104, 48, 100, 72, 65, 54, 76, 121, 57, 104, 89, 50, 86, 107, 97, 87, 78, 118, 10, 98, 83, 53, 108, 90, 71, 108, 106, 98, 50, 49, 110, 99, 109, 57, 49, 99, 67, 53, 106, 98, 50, 48, 118, 90, 71, 57, 106, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 67, 65, 81, 68, 79, 76, 65, 116, 83, 85, 87, 73, 109, 102, 81, 119, 110, 103, 52, 47, 70, 57, 116, 113, 103, 10, 97, 72, 116, 80, 107, 108, 55, 113, 112, 72, 77, 121, 69, 86, 78, 69, 115, 107, 84, 76, 110, 101, 119, 80, 101, 85, 75, 122, 69, 75, 98, 72, 68, 90, 51, 76, 116, 118, 111, 47, 79, 110, 122, 113, 118, 52, 104, 84, 71, 122, 122, 51, 103, 118, 111, 70, 78, 84, 80, 104, 78, 97, 104, 88, 119, 79, 102, 57, 106, 85, 56, 47, 107, 122, 74, 80, 10, 101, 71, 89, 68, 100, 119, 100, 89, 54, 90, 88, 73, 102, 106, 55, 81, 101, 81, 67, 77, 56, 104, 116, 82, 77, 53, 117, 56, 108, 79, 107, 54, 101, 50, 53, 83, 76, 84, 75, 101, 73, 54, 82, 70, 43, 55, 89, 117, 69, 55, 67, 76, 71, 76, 72, 100, 122, 116, 85, 100, 112, 48, 74, 47, 86, 98, 55, 55, 87, 55, 116, 72, 49, 80, 119, 107, 10, 122, 81, 83, 117, 108, 103, 85, 86, 49, 113, 122, 79, 77, 80, 80, 75, 67, 56, 87, 54, 52, 105, 76, 103, 112, 113, 48, 105, 53, 65, 76, 117, 100, 66, 70, 47, 84, 80, 57, 52, 72, 84, 88, 97, 53, 103, 73, 48, 54, 120, 103, 83, 89, 88, 99, 71, 67, 82, 90, 106, 54, 104, 105, 116, 111, 111, 99, 102, 56, 115, 101, 65, 67, 81, 108, 49, 10, 84, 104, 67, 111, 106, 122, 50, 71, 117, 72, 85, 82, 119, 67, 82, 105, 105, 112, 90, 55, 83, 107, 88, 112, 55, 70, 110, 70, 118, 109, 117, 68, 53, 117, 72, 111, 114, 76, 85, 119, 72, 118, 52, 70, 66, 52, 68, 53, 52, 83, 77, 78, 85, 73, 56, 70, 109, 80, 56, 115, 88, 43, 103, 55, 116, 113, 51, 80, 103, 98, 85, 104, 104, 56, 111, 73, 10, 75, 105, 77, 110, 77, 67, 65, 114, 122, 43, 50, 85, 87, 54, 121, 121, 101, 116, 76, 72, 75, 75, 71, 75, 67, 53, 116, 78, 83, 105, 120, 116, 104, 84, 56, 74, 99, 106, 120, 110, 52, 116, 110, 99, 66, 55, 114, 114, 90, 88, 116, 97, 65, 87, 80, 87, 107, 70, 116, 80, 70, 50, 89, 57, 102, 119, 115, 90, 111, 53, 78, 106, 69, 70, 73, 113, 10, 110, 120, 81, 87, 87, 79, 76, 99, 112, 102, 83, 104, 70, 111, 115, 79, 107, 89, 117, 66, 121, 112, 116, 90, 43, 116, 104, 114, 107, 81, 100, 108, 86, 86, 57, 83, 72, 54, 56, 54, 43, 53, 68, 100, 97, 97, 86, 98, 110, 71, 48, 79, 76, 76, 98, 54, 122, 113, 121, 108, 102, 68, 74, 75, 90, 48, 68, 99, 77, 68, 81, 106, 51, 100, 99, 69, 10, 73, 50, 98, 119, 47, 70, 87, 65, 112, 47, 116, 109, 71, 89, 73, 49, 90, 50, 74, 119, 79, 86, 53, 118, 120, 43, 113, 81, 81, 69, 81, 73, 72, 114, 105, 121, 49, 116, 118, 117, 87, 97, 99, 78, 71, 72, 107, 48, 118, 70, 81, 89, 88, 108, 80, 75, 78, 70, 72, 116, 82, 81, 114, 109, 106, 115, 101, 67, 78, 106, 54, 110, 79, 71, 79, 112, 10, 77, 67, 119, 88, 69, 71, 67, 83, 110, 49, 87, 72, 69, 108, 107, 81, 119, 103, 57, 110, 97, 82, 72, 77, 84, 104, 53, 43, 83, 112, 113, 116, 114, 48, 67, 111, 100, 97, 120, 87, 107, 72, 83, 52, 111, 74, 121, 108, 101, 87, 47, 99, 54, 82, 114, 73, 97, 81, 88, 112, 117, 118, 111, 68, 115, 51, 122, 107, 52, 69, 55, 67, 122, 112, 51, 111, 10, 116, 107, 89, 78, 98, 110, 53, 88, 79, 109, 101, 85, 119, 115, 115, 102, 110, 72, 100, 75, 90, 48, 53, 112, 104, 107, 79, 84, 79, 80, 117, 50, 50, 48, 43, 68, 107, 100, 82, 103, 102, 107, 115, 43, 75, 122, 103, 72, 86, 90, 104, 101, 112, 65, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 77, 105, 99, 114, 111, 115, 101, 99, 32, 101, 45, 83, 122, 105, 103, 110, 111, 32, 82, 111, 111, 116, 32, 67, 65, 32, 50, 48, 48, 57, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 67, 106, 67, 67, 65, 118, 75, 103, 65, 119, 73, 66, 65, 103, 73, 74, 65, 77, 74, 43, 81, 119, 82, 79, 82, 122, 56, 90, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 77, 73, 71, 67, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 73, 86, 84, 69, 82, 10, 77, 65, 56, 71, 65, 49, 85, 69, 66, 119, 119, 73, 81, 110, 86, 107, 89, 88, 66, 108, 99, 51, 81, 120, 70, 106, 65, 85, 66, 103, 78, 86, 66, 65, 111, 77, 68, 85, 49, 112, 89, 51, 74, 118, 99, 50, 86, 106, 73, 69, 120, 48, 90, 67, 52, 120, 74, 122, 65, 108, 66, 103, 78, 86, 66, 65, 77, 77, 72, 107, 49, 112, 89, 51, 74, 118, 10, 99, 50, 86, 106, 73, 71, 85, 116, 85, 51, 112, 112, 90, 50, 53, 118, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 77, 106, 65, 119, 79, 84, 69, 102, 77, 66, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 74, 65, 82, 89, 81, 97, 87, 53, 109, 98, 48, 66, 108, 76, 88, 78, 54, 97, 87, 100, 117, 98, 121, 53, 111, 10, 100, 84, 65, 101, 70, 119, 48, 119, 79, 84, 65, 50, 77, 84, 89, 120, 77, 84, 77, 119, 77, 84, 104, 97, 70, 119, 48, 121, 79, 84, 69, 121, 77, 122, 65, 120, 77, 84, 77, 119, 77, 84, 104, 97, 77, 73, 71, 67, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 73, 86, 84, 69, 82, 77, 65, 56, 71, 65, 49, 85, 69, 10, 66, 119, 119, 73, 81, 110, 86, 107, 89, 88, 66, 108, 99, 51, 81, 120, 70, 106, 65, 85, 66, 103, 78, 86, 66, 65, 111, 77, 68, 85, 49, 112, 89, 51, 74, 118, 99, 50, 86, 106, 73, 69, 120, 48, 90, 67, 52, 120, 74, 122, 65, 108, 66, 103, 78, 86, 66, 65, 77, 77, 72, 107, 49, 112, 89, 51, 74, 118, 99, 50, 86, 106, 73, 71, 85, 116, 10, 85, 51, 112, 112, 90, 50, 53, 118, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 77, 106, 65, 119, 79, 84, 69, 102, 77, 66, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 74, 65, 82, 89, 81, 97, 87, 53, 109, 98, 48, 66, 108, 76, 88, 78, 54, 97, 87, 100, 117, 98, 121, 53, 111, 100, 84, 67, 67, 65, 83, 73, 119, 10, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 79, 110, 52, 106, 47, 78, 106, 114, 100, 113, 71, 50, 75, 102, 103, 81, 118, 118, 80, 107, 100, 54, 109, 74, 118, 105, 90, 112, 87, 78, 119, 114, 90, 117, 117, 121, 106, 78, 65, 10, 102, 87, 50, 87, 98, 113, 69, 79, 82, 79, 55, 104, 69, 53, 50, 85, 81, 108, 75, 97, 118, 88, 87, 70, 100, 67, 121, 111, 68, 104, 50, 84, 116, 104, 105, 51, 106, 67, 121, 111, 122, 47, 116, 99, 99, 98, 110, 97, 55, 80, 55, 111, 102, 111, 47, 107, 76, 120, 50, 121, 113, 72, 87, 72, 50, 76, 101, 104, 53, 84, 118, 80, 109, 85, 112, 71, 10, 48, 73, 77, 90, 102, 99, 67, 104, 69, 104, 121, 86, 98, 85, 114, 48, 50, 77, 101, 108, 84, 84, 77, 117, 104, 84, 108, 65, 100, 88, 52, 85, 102, 73, 65, 83, 109, 70, 68, 72, 81, 87, 101, 52, 111, 73, 66, 104, 86, 75, 90, 115, 84, 104, 47, 103, 110, 81, 52, 72, 54, 99, 109, 54, 77, 43, 102, 43, 119, 70, 85, 111, 76, 65, 75, 65, 10, 112, 120, 110, 49, 110, 116, 120, 86, 85, 119, 79, 88, 101, 119, 100, 73, 47, 53, 110, 55, 78, 52, 111, 107, 120, 70, 110, 77, 85, 66, 66, 106, 106, 113, 113, 112, 71, 114, 67, 69, 71, 111, 98, 53, 88, 55, 117, 120, 85, 71, 54, 107, 48, 81, 114, 77, 49, 88, 70, 43, 72, 54, 99, 98, 102, 80, 86, 84, 98, 105, 74, 102, 121, 121, 118, 109, 10, 49, 72, 120, 100, 114, 116, 98, 67, 120, 107, 122, 108, 66, 81, 72, 90, 55, 86, 102, 56, 119, 83, 78, 53, 47, 80, 114, 73, 74, 73, 79, 86, 56, 55, 86, 113, 85, 81, 72, 81, 100, 57, 98, 112, 69, 113, 72, 53, 71, 111, 80, 55, 103, 104, 117, 53, 115, 74, 102, 48, 100, 103, 89, 122, 81, 48, 109, 103, 47, 119, 117, 49, 43, 114, 85, 67, 10, 65, 119, 69, 65, 65, 97, 79, 66, 103, 68, 66, 43, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 84, 76, 68, 56, 98, 102, 10, 81, 107, 80, 77, 80, 99, 117, 49, 83, 67, 79, 104, 71, 110, 113, 109, 75, 114, 115, 48, 97, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 84, 76, 68, 56, 98, 102, 81, 107, 80, 77, 80, 99, 117, 49, 83, 67, 79, 104, 71, 110, 113, 109, 75, 114, 115, 48, 97, 68, 65, 98, 66, 103, 78, 86, 72, 82, 69, 69, 10, 70, 68, 65, 83, 103, 82, 66, 112, 98, 109, 90, 118, 81, 71, 85, 116, 99, 51, 112, 112, 90, 50, 53, 118, 76, 109, 104, 49, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 66, 65, 81, 68, 74, 48, 81, 53, 101, 76, 116, 88, 77, 115, 51, 119, 43, 121, 47, 119, 57, 47, 119, 48, 111, 10, 108, 90, 77, 69, 121, 76, 47, 97, 122, 88, 109, 52, 81, 53, 68, 119, 112, 76, 55, 118, 56, 117, 56, 104, 109, 76, 122, 85, 49, 70, 48, 71, 57, 117, 53, 67, 55, 68, 66, 115, 111, 75, 113, 112, 121, 118, 71, 118, 105, 118, 111, 47, 67, 51, 78, 113, 80, 117, 111, 117, 81, 72, 52, 102, 114, 108, 82, 104, 101, 101, 115, 117, 67, 68, 102, 88, 10, 73, 47, 79, 77, 110, 55, 52, 100, 115, 101, 71, 107, 100, 100, 117, 103, 52, 108, 81, 85, 115, 98, 111, 99, 75, 97, 81, 89, 57, 104, 75, 54, 111, 104, 81, 85, 52, 122, 69, 49, 121, 69, 68, 47, 116, 43, 65, 70, 100, 108, 102, 66, 72, 70, 110, 121, 43, 76, 47, 107, 55, 83, 86, 105, 88, 73, 84, 119, 102, 110, 52, 102, 115, 55, 55, 53, 10, 116, 121, 69, 82, 122, 65, 77, 66, 86, 110, 67, 110, 69, 74, 73, 101, 71, 122, 83, 66, 72, 113, 50, 99, 71, 115, 77, 69, 80, 79, 48, 67, 89, 100, 89, 101, 66, 118, 78, 102, 79, 111, 102, 121, 75, 47, 70, 70, 104, 43, 85, 57, 114, 78, 72, 72, 86, 52, 83, 57, 97, 54, 55, 99, 50, 80, 109, 50, 71, 50, 74, 119, 67, 122, 48, 50, 10, 121, 85, 76, 121, 77, 116, 100, 54, 89, 101, 98, 83, 50, 122, 51, 80, 121, 75, 110, 74, 109, 57, 122, 98, 87, 69, 84, 88, 98, 122, 105, 118, 102, 51, 106, 84, 111, 54, 48, 97, 100, 98, 111, 99, 119, 84, 90, 56, 106, 120, 53, 116, 72, 77, 78, 49, 82, 113, 52, 49, 66, 97, 98, 50, 88, 68, 48, 104, 55, 108, 98, 119, 121, 89, 73, 105, 10, 76, 88, 112, 85, 113, 51, 68, 68, 102, 83, 74, 108, 103, 110, 67, 87, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 108, 111, 98, 97, 108, 83, 105, 103, 110, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 82, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 88, 122, 67, 67, 65, 107, 101, 103, 65, 119, 73, 66, 65, 103, 73, 76, 66, 65, 65, 65, 65, 65, 65, 66, 73, 86, 104, 84, 67, 75, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 84, 68, 69, 103, 77, 66, 52, 71, 65, 49, 85, 69, 67, 120, 77, 88, 82, 50, 120, 118, 10, 89, 109, 70, 115, 85, 50, 108, 110, 98, 105, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 67, 48, 103, 85, 106, 77, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 111, 84, 67, 107, 100, 115, 98, 50, 74, 104, 98, 70, 78, 112, 90, 50, 52, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 77, 84, 67, 107, 100, 115, 98, 50, 74, 104, 10, 98, 70, 78, 112, 90, 50, 52, 119, 72, 104, 99, 78, 77, 68, 107, 119, 77, 122, 69, 52, 77, 84, 65, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 106, 107, 119, 77, 122, 69, 52, 77, 84, 65, 119, 77, 68, 65, 119, 87, 106, 66, 77, 77, 83, 65, 119, 72, 103, 89, 68, 86, 81, 81, 76, 69, 120, 100, 72, 98, 71, 57, 105, 89, 87, 120, 84, 10, 97, 87, 100, 117, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 76, 83, 66, 83, 77, 122, 69, 84, 77, 66, 69, 71, 65, 49, 85, 69, 67, 104, 77, 75, 82, 50, 120, 118, 89, 109, 70, 115, 85, 50, 108, 110, 98, 106, 69, 84, 77, 66, 69, 71, 65, 49, 85, 69, 65, 120, 77, 75, 82, 50, 120, 118, 89, 109, 70, 115, 85, 50, 108, 110, 10, 98, 106, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 77, 119, 108, 100, 112, 66, 53, 66, 110, 103, 105, 70, 118, 88, 65, 103, 55, 97, 69, 121, 105, 105, 101, 47, 81, 86, 50, 69, 99, 87, 116, 10, 105, 72, 76, 56, 82, 103, 74, 68, 120, 55, 75, 75, 110, 81, 82, 102, 74, 77, 115, 117, 83, 43, 70, 103, 103, 107, 98, 104, 85, 113, 115, 77, 103, 85, 100, 119, 98, 78, 49, 107, 48, 101, 118, 49, 76, 75, 77, 80, 103, 106, 48, 77, 75, 54, 54, 88, 49, 55, 89, 85, 104, 104, 66, 53, 117, 122, 115, 84, 103, 72, 101, 77, 67, 79, 70, 74, 10, 48, 109, 112, 105, 76, 120, 57, 101, 43, 112, 90, 111, 51, 52, 107, 110, 108, 84, 105, 102, 66, 116, 99, 43, 121, 99, 115, 109, 87, 81, 49, 122, 51, 114, 68, 73, 54, 83, 89, 79, 103, 120, 88, 71, 55, 49, 117, 76, 48, 103, 82, 103, 121, 107, 109, 109, 75, 80, 90, 112, 79, 47, 98, 76, 121, 67, 105, 82, 53, 90, 50, 75, 89, 86, 99, 51, 10, 114, 72, 81, 85, 51, 72, 84, 103, 79, 117, 53, 121, 76, 121, 54, 99, 43, 57, 67, 55, 118, 47, 85, 57, 65, 79, 69, 71, 77, 43, 105, 67, 75, 54, 53, 84, 112, 106, 111, 87, 99, 52, 122, 100, 81, 81, 52, 103, 79, 115, 67, 48, 112, 54, 72, 112, 115, 107, 43, 81, 76, 106, 74, 103, 54, 86, 102, 76, 117, 81, 83, 83, 97, 71, 106, 108, 10, 79, 67, 90, 103, 100, 98, 75, 102, 100, 47, 43, 82, 70, 79, 43, 117, 73, 69, 110, 56, 114, 85, 65, 86, 83, 78, 69, 67, 77, 87, 69, 90, 88, 114, 105, 88, 55, 54, 49, 51, 116, 50, 83, 97, 101, 114, 57, 102, 119, 82, 80, 118, 109, 50, 76, 55, 68, 87, 122, 103, 86, 71, 107, 87, 113, 81, 80, 97, 98, 117, 109, 68, 107, 51, 70, 50, 10, 120, 109, 109, 70, 103, 104, 99, 67, 65, 119, 69, 65, 65, 97, 78, 67, 77, 69, 65, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 10, 70, 73, 47, 119, 83, 51, 43, 111, 76, 107, 85, 107, 114, 107, 49, 81, 43, 109, 79, 97, 105, 57, 55, 105, 51, 82, 117, 56, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 66, 65, 81, 66, 76, 81, 78, 118, 65, 85, 75, 114, 43, 121, 65, 122, 118, 57, 53, 90, 85, 82, 85, 109, 55, 10, 108, 103, 65, 74, 81, 97, 121, 122, 69, 52, 97, 71, 75, 65, 99, 122, 121, 109, 118, 109, 100, 76, 109, 54, 65, 67, 50, 117, 112, 65, 114, 84, 57, 102, 72, 120, 68, 52, 113, 47, 99, 50, 100, 75, 103, 56, 100, 69, 101, 51, 106, 103, 114, 50, 53, 115, 98, 119, 77, 112, 106, 106, 77, 53, 82, 99, 79, 79, 53, 76, 108, 88, 98, 75, 114, 56, 10, 69, 112, 98, 115, 85, 56, 89, 116, 53, 67, 82, 115, 117, 90, 82, 106, 43, 57, 120, 84, 97, 71, 100, 87, 80, 111, 79, 52, 122, 122, 85, 104, 119, 56, 108, 111, 47, 115, 55, 97, 119, 108, 79, 113, 122, 74, 67, 75, 54, 102, 66, 100, 82, 111, 121, 86, 51, 88, 112, 89, 75, 66, 111, 118, 72, 100, 55, 78, 65, 68, 100, 66, 106, 43, 49, 69, 10, 98, 100, 100, 84, 75, 74, 100, 43, 56, 50, 99, 69, 72, 104, 88, 88, 105, 112, 97, 48, 48, 57, 53, 77, 74, 54, 82, 77, 71, 51, 78, 122, 100, 118, 81, 88, 109, 99, 73, 102, 101, 103, 55, 106, 76, 81, 105, 116, 67, 104, 119, 115, 47, 122, 121, 114, 86, 81, 52, 80, 107, 88, 52, 50, 54, 56, 78, 88, 83, 98, 55, 104, 76, 105, 49, 56, 10, 89, 73, 118, 68, 81, 86, 69, 84, 73, 53, 51, 79, 57, 122, 74, 114, 108, 65, 71, 111, 109, 101, 99, 115, 77, 120, 56, 54, 79, 121, 88, 83, 104, 107, 68, 79, 79, 121, 121, 71, 101, 77, 108, 104, 76, 120, 83, 54, 55, 116, 116, 86, 98, 57, 43, 69, 55, 103, 85, 74, 84, 98, 48, 111, 50, 72, 76, 79, 48, 50, 74, 81, 90, 82, 55, 114, 10, 107, 112, 101, 68, 77, 100, 109, 122, 116, 99, 112, 72, 87, 68, 57, 102, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 117, 116, 111, 114, 105, 100, 97, 100, 32, 100, 101, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 99, 105, 111, 110, 32, 70, 105, 114, 109, 97, 112, 114, 111, 102, 101, 115, 105, 111, 110, 97, 108, 32, 67, 73, 70, 32, 65, 54, 50, 54, 51, 52, 48, 54, 56, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 71, 70, 68, 67, 67, 65, 47, 121, 103, 65, 119, 73, 66, 65, 103, 73, 73, 85, 43, 119, 55, 55, 118, 117, 121, 83, 70, 56, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 85, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 86, 77, 120, 81, 106, 66, 65, 10, 66, 103, 78, 86, 66, 65, 77, 77, 79, 85, 70, 49, 100, 71, 57, 121, 97, 87, 82, 104, 90, 67, 66, 107, 90, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 106, 97, 87, 57, 117, 73, 69, 90, 112, 99, 109, 49, 104, 99, 72, 74, 118, 90, 109, 86, 122, 97, 87, 57, 117, 89, 87, 119, 103, 81, 48, 108, 71, 73, 69, 69, 50, 10, 77, 106, 89, 122, 78, 68, 65, 50, 79, 68, 65, 101, 70, 119, 48, 119, 79, 84, 65, 49, 77, 106, 65, 119, 79, 68, 77, 52, 77, 84, 86, 97, 70, 119, 48, 122, 77, 68, 69, 121, 77, 122, 69, 119, 79, 68, 77, 52, 77, 84, 86, 97, 77, 70, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 86, 84, 77, 85, 73, 119, 10, 81, 65, 89, 68, 86, 81, 81, 68, 68, 68, 108, 66, 100, 88, 82, 118, 99, 109, 108, 107, 89, 87, 81, 103, 90, 71, 85, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 89, 50, 108, 118, 98, 105, 66, 71, 97, 88, 74, 116, 89, 88, 66, 121, 98, 50, 90, 108, 99, 50, 108, 118, 98, 109, 70, 115, 73, 69, 78, 74, 82, 105, 66, 66, 10, 78, 106, 73, 50, 77, 122, 81, 119, 78, 106, 103, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 68, 75, 108, 109, 117, 79, 54, 118, 106, 55, 56, 97, 73, 49, 52, 72, 57, 77, 50, 117, 68, 68, 10, 85, 116, 100, 57, 116, 104, 68, 73, 65, 108, 54, 122, 81, 121, 114, 69, 84, 50, 113, 121, 121, 104, 120, 100, 75, 74, 112, 52, 69, 82, 112, 112, 87, 86, 101, 118, 116, 83, 66, 67, 53, 73, 115, 80, 53, 116, 57, 98, 112, 103, 79, 83, 76, 47, 85, 82, 53, 71, 76, 88, 77, 110, 69, 52, 50, 81, 81, 77, 99, 97, 115, 57, 85, 88, 52, 80, 10, 66, 57, 57, 106, 66, 86, 122, 112, 118, 53, 82, 118, 119, 83, 109, 67, 119, 76, 84, 97, 85, 98, 68, 66, 80, 76, 117, 116, 78, 48, 112, 99, 121, 118, 70, 76, 78, 103, 52, 107, 113, 55, 47, 68, 104, 72, 102, 57, 113, 70, 68, 48, 115, 101, 102, 71, 76, 57, 73, 116, 87, 89, 49, 54, 67, 107, 54, 87, 97, 86, 73, 67, 113, 106, 97, 89, 10, 55, 80, 122, 54, 70, 73, 77, 77, 78, 120, 47, 74, 107, 106, 100, 47, 49, 52, 69, 116, 53, 99, 83, 53, 52, 68, 52, 48, 47, 109, 102, 48, 80, 109, 98, 82, 48, 47, 82, 65, 122, 49, 53, 105, 78, 65, 57, 119, 66, 106, 52, 103, 71, 70, 114, 79, 57, 51, 73, 98, 74, 87, 121, 84, 100, 66, 83, 84, 111, 51, 79, 120, 68, 113, 113, 72, 10, 69, 67, 78, 90, 88, 121, 65, 70, 71, 85, 102, 116, 97, 73, 54, 83, 69, 115, 112, 100, 47, 78, 89, 114, 115, 112, 73, 56, 73, 77, 47, 104, 88, 54, 56, 103, 118, 113, 66, 50, 102, 51, 98, 108, 55, 66, 113, 71, 89, 84, 77, 43, 53, 51, 117, 48, 80, 54, 65, 80, 106, 113, 75, 53, 97, 109, 43, 53, 104, 121, 90, 118, 81, 87, 121, 73, 10, 112, 108, 68, 57, 97, 109, 77, 76, 57, 90, 77, 87, 71, 120, 109, 80, 115, 117, 50, 98, 109, 56, 109, 81, 57, 81, 69, 77, 51, 120, 107, 57, 68, 122, 52, 52, 73, 56, 107, 118, 106, 119, 122, 82, 65, 118, 52, 98, 86, 100, 90, 79, 48, 73, 48, 56, 114, 48, 43, 107, 56, 47, 54, 118, 75, 116, 77, 70, 110, 88, 107, 73, 111, 99, 116, 88, 10, 77, 98, 83, 99, 121, 74, 67, 121, 90, 47, 81, 89, 70, 112, 77, 54, 47, 69, 102, 89, 48, 88, 105, 87, 77, 82, 43, 54, 75, 119, 120, 102, 88, 90, 109, 116, 89, 52, 108, 97, 74, 67, 66, 50, 50, 78, 47, 57, 113, 48, 54, 109, 73, 113, 113, 100, 88, 117, 89, 110, 105, 110, 49, 111, 75, 97, 80, 110, 105, 114, 106, 97, 69, 98, 115, 88, 10, 76, 90, 109, 100, 69, 121, 82, 71, 57, 56, 88, 105, 50, 74, 43, 79, 102, 56, 101, 80, 100, 71, 49, 97, 115, 117, 104, 121, 57, 97, 122, 117, 74, 66, 67, 116, 76, 120, 84, 97, 47, 121, 50, 97, 82, 110, 70, 72, 118, 107, 76, 102, 117, 119, 72, 98, 57, 72, 47, 84, 75, 73, 56, 120, 87, 86, 118, 84, 121, 81, 75, 109, 116, 70, 76, 75, 10, 98, 112, 102, 55, 81, 56, 85, 73, 74, 109, 43, 75, 57, 76, 118, 57, 110, 121, 105, 113, 68, 100, 86, 70, 56, 120, 77, 54, 72, 100, 106, 65, 101, 73, 57, 66, 90, 122, 119, 101, 108, 71, 83, 117, 101, 119, 118, 70, 54, 78, 107, 66, 105, 68, 107, 97, 108, 52, 90, 107, 81, 100, 85, 55, 104, 119, 120, 117, 43, 103, 47, 71, 118, 85, 103, 85, 10, 118, 122, 108, 78, 49, 74, 53, 66, 116, 111, 43, 87, 72, 87, 79, 87, 107, 57, 109, 86, 66, 110, 103, 120, 97, 74, 52, 51, 66, 106, 117, 65, 105, 85, 86, 104, 79, 83, 80, 72, 71, 48, 83, 106, 70, 101, 85, 99, 43, 74, 73, 119, 117, 119, 73, 68, 65, 81, 65, 66, 111, 52, 72, 118, 77, 73, 72, 115, 77, 66, 73, 71, 65, 49, 85, 100, 10, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 69, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 108, 122, 101, 117, 114, 78, 82, 52, 65, 80, 110, 55, 86, 100, 77, 65, 99, 116, 72, 78, 72, 10, 68, 104, 112, 107, 76, 122, 67, 66, 112, 103, 89, 68, 86, 82, 48, 103, 66, 73, 71, 101, 77, 73, 71, 98, 77, 73, 71, 89, 66, 103, 82, 86, 72, 83, 65, 65, 77, 73, 71, 80, 77, 67, 56, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 73, 66, 70, 105, 78, 111, 100, 72, 82, 119, 79, 105, 56, 118, 100, 51, 100, 51, 76, 109, 90, 112, 10, 99, 109, 49, 104, 99, 72, 74, 118, 90, 109, 86, 122, 97, 87, 57, 117, 89, 87, 119, 117, 89, 50, 57, 116, 76, 50, 78, 119, 99, 122, 66, 99, 66, 103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 67, 65, 106, 66, 81, 72, 107, 52, 65, 85, 65, 66, 104, 65, 72, 77, 65, 90, 81, 66, 118, 65, 67, 65, 65, 90, 65, 66, 108, 65, 67, 65, 65, 10, 98, 65, 66, 104, 65, 67, 65, 65, 81, 103, 66, 118, 65, 71, 52, 65, 89, 81, 66, 117, 65, 71, 56, 65, 100, 103, 66, 104, 65, 67, 65, 65, 78, 65, 65, 51, 65, 67, 65, 65, 81, 103, 66, 104, 65, 72, 73, 65, 89, 119, 66, 108, 65, 71, 119, 65, 98, 119, 66, 117, 65, 71, 69, 65, 73, 65, 65, 119, 65, 68, 103, 65, 77, 65, 65, 120, 10, 65, 68, 99, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 73, 66, 65, 66, 100, 57, 111, 80, 109, 48, 51, 99, 88, 70, 54, 54, 49, 76, 74, 76, 87, 104, 65, 113, 118, 100, 112, 89, 104, 75, 115, 103, 57, 86, 83, 121, 116, 88, 106, 68, 118, 108, 77, 100, 51, 43, 120, 68, 76, 120, 10, 53, 49, 116, 107, 108, 106, 89, 121, 71, 79, 121, 108, 77, 110, 102, 88, 52, 48, 83, 50, 119, 66, 69, 113, 103, 76, 107, 57, 97, 109, 53, 56, 109, 57, 79, 116, 47, 77, 80, 87, 111, 43, 90, 107, 75, 88, 122, 82, 52, 84, 103, 101, 103, 105, 118, 47, 74, 50, 87, 118, 43, 120, 89, 86, 120, 67, 53, 120, 104, 79, 87, 49, 47, 47, 113, 107, 10, 82, 55, 49, 107, 77, 114, 118, 50, 74, 89, 83, 105, 74, 48, 76, 49, 73, 76, 68, 67, 69, 120, 65, 82, 122, 82, 65, 86, 117, 107, 75, 81, 75, 116, 74, 69, 52, 90, 89, 109, 54, 122, 70, 73, 69, 118, 48, 113, 50, 115, 107, 71, 122, 51, 81, 101, 113, 85, 118, 86, 104, 121, 106, 53, 101, 84, 83, 83, 80, 105, 53, 69, 54, 80, 97, 80, 10, 84, 52, 56, 49, 80, 121, 87, 122, 79, 100, 120, 106, 75, 112, 66, 114, 73, 70, 47, 69, 85, 104, 74, 79, 108, 121, 119, 113, 114, 74, 50, 88, 51, 107, 106, 121, 111, 50, 98, 98, 119, 116, 75, 68, 108, 97, 90, 109, 112, 53, 52, 108, 68, 43, 107, 76, 77, 53, 70, 108, 67, 108, 114, 68, 50, 86, 81, 83, 51, 97, 47, 68, 84, 103, 52, 102, 10, 74, 108, 52, 78, 51, 76, 79, 78, 55, 78, 87, 66, 99, 78, 55, 83, 84, 121, 81, 70, 56, 50, 120, 79, 57, 85, 120, 74, 90, 111, 51, 82, 47, 57, 73, 76, 74, 85, 70, 73, 47, 108, 71, 69, 120, 107, 75, 118, 103, 65, 84, 80, 48, 72, 53, 107, 83, 101, 84, 121, 51, 54, 76, 115, 115, 85, 122, 65, 75, 104, 51, 110, 116, 76, 70, 108, 10, 111, 115, 83, 56, 56, 90, 106, 48, 113, 110, 65, 72, 89, 55, 83, 52, 50, 106, 116, 77, 43, 107, 65, 105, 77, 70, 115, 82, 112, 118, 65, 70, 68, 115, 89, 67, 65, 48, 105, 114, 104, 112, 117, 70, 51, 100, 118, 100, 54, 113, 74, 50, 103, 72, 78, 57, 57, 90, 119, 69, 120, 69, 87, 78, 53, 55, 107, 99, 105, 53, 55, 113, 49, 51, 88, 82, 10, 99, 114, 72, 101, 100, 85, 84, 110, 81, 110, 51, 105, 86, 50, 116, 57, 51, 74, 109, 56, 80, 89, 77, 111, 54, 111, 67, 84, 106, 99, 86, 77, 90, 99, 70, 119, 103, 98, 103, 52, 47, 69, 77, 120, 115, 118, 89, 68, 78, 69, 101, 121, 114, 80, 115, 105, 66, 115, 115, 101, 51, 82, 100, 72, 72, 70, 57, 109, 117, 100, 77, 97, 111, 116, 111, 82, 10, 115, 97, 83, 56, 73, 56, 110, 107, 118, 111, 102, 47, 117, 90, 83, 50, 43, 70, 48, 103, 83, 116, 82, 102, 53, 55, 49, 111, 101, 50, 88, 121, 70, 82, 55, 83, 79, 113, 107, 116, 54, 100, 104, 114, 74, 75, 121, 88, 87, 69, 82, 72, 114, 86, 107, 89, 56, 83, 70, 108, 99, 78, 55, 79, 78, 71, 67, 111, 81, 80, 72, 122, 80, 75, 84, 68, 10, 75, 67, 79, 77, 47, 105, 99, 122, 81, 48, 67, 103, 70, 122, 122, 114, 54, 106, 117, 119, 99, 113, 97, 106, 117, 85, 112, 76, 88, 104, 90, 73, 57, 76, 75, 56, 121, 73, 121, 83, 120, 90, 50, 102, 114, 72, 73, 50, 118, 68, 83, 65, 78, 71, 117, 112, 105, 53, 76, 65, 117, 66, 102, 116, 55, 72, 90, 84, 57, 83, 81, 66, 106, 76, 77, 105, 10, 54, 69, 116, 56, 86, 99, 97, 100, 43, 113, 77, 85, 117, 50, 87, 70, 98, 109, 53, 80, 69, 110, 52, 75, 80, 74, 50, 86, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 73, 122, 101, 110, 112, 101, 46, 99, 111, 109, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 56, 84, 67, 67, 65, 57, 109, 103, 65, 119, 73, 66, 65, 103, 73, 81, 65, 76, 67, 51, 87, 104, 90, 73, 88, 55, 47, 104, 121, 47, 87, 76, 49, 120, 110, 109, 102, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 65, 52, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 70, 85, 122, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 67, 103, 119, 76, 83, 86, 112, 70, 84, 108, 66, 70, 73, 70, 77, 117, 81, 83, 52, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 77, 77, 67, 107, 108, 54, 90, 87, 53, 119, 90, 83, 53, 106, 98, 50, 48, 119, 72, 104, 99, 78, 77, 68, 99, 120, 77, 106, 69, 122, 10, 77, 84, 77, 119, 79, 68, 73, 52, 87, 104, 99, 78, 77, 122, 99, 120, 77, 106, 69, 122, 77, 68, 103, 121, 78, 122, 73, 49, 87, 106, 65, 52, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 70, 85, 122, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 67, 103, 119, 76, 83, 86, 112, 70, 84, 108, 66, 70, 73, 70, 77, 117, 10, 81, 83, 52, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 77, 77, 67, 107, 108, 54, 90, 87, 53, 119, 90, 83, 53, 106, 98, 50, 48, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 68, 74, 10, 48, 51, 114, 75, 68, 120, 54, 115, 112, 52, 98, 111, 70, 109, 86, 113, 115, 99, 73, 98, 82, 84, 74, 120, 108, 100, 110, 43, 69, 70, 118, 77, 114, 43, 101, 108, 101, 81, 71, 80, 105, 99, 80, 75, 56, 108, 86, 120, 57, 51, 101, 43, 100, 53, 84, 122, 99, 113, 81, 115, 82, 78, 105, 101, 107, 112, 115, 85, 79, 113, 72, 110, 74, 74, 65, 75, 10, 67, 108, 97, 79, 120, 100, 103, 109, 108, 79, 72, 90, 83, 79, 69, 116, 80, 116, 111, 75, 99, 116, 50, 106, 109, 82, 88, 97, 103, 97, 75, 72, 57, 72, 116, 117, 74, 110, 101, 74, 87, 75, 51, 87, 54, 119, 121, 121, 81, 88, 112, 122, 98, 109, 51, 98, 101, 110, 104, 66, 54, 81, 105, 73, 69, 110, 54, 72, 76, 109, 89, 82, 89, 50, 120, 85, 10, 43, 122, 121, 100, 99, 115, 67, 56, 76, 118, 47, 67, 116, 57, 48, 78, 100, 117, 77, 54, 49, 47, 101, 48, 97, 76, 54, 105, 57, 101, 79, 66, 98, 115, 70, 71, 98, 49, 50, 78, 52, 69, 51, 71, 86, 70, 87, 74, 71, 106, 77, 120, 67, 114, 70, 88, 117, 97, 79, 75, 109, 77, 80, 115, 79, 122, 84, 70, 108, 85, 70, 112, 102, 110, 88, 67, 10, 80, 67, 68, 70, 89, 98, 112, 82, 82, 54, 65, 103, 107, 74, 79, 104, 107, 69, 118, 122, 84, 110, 121, 70, 82, 86, 83, 97, 48, 81, 85, 109, 81, 98, 67, 49, 84, 82, 48, 122, 118, 115, 81, 68, 121, 67, 86, 56, 119, 88, 68, 98, 79, 47, 81, 74, 76, 86, 81, 110, 83, 75, 119, 118, 52, 99, 83, 115, 80, 115, 106, 76, 107, 107, 120, 84, 10, 79, 84, 99, 106, 55, 78, 77, 66, 43, 101, 65, 74, 82, 69, 49, 78, 90, 77, 68, 104, 68, 86, 113, 72, 73, 114, 121, 116, 71, 54, 80, 43, 74, 114, 85, 86, 56, 54, 102, 56, 104, 66, 110, 112, 55, 75, 71, 73, 116, 69, 82, 112, 104, 73, 80, 122, 105, 100, 70, 48, 66, 113, 110, 77, 67, 57, 98, 67, 51, 105, 101, 70, 85, 67, 98, 75, 10, 70, 55, 106, 74, 101, 111, 100, 87, 76, 66, 111, 66, 72, 109, 121, 43, 69, 54, 48, 81, 114, 76, 85, 107, 57, 84, 105, 82, 111, 100, 90, 76, 50, 118, 71, 55, 48, 116, 53, 72, 116, 102, 71, 56, 103, 102, 90, 90, 97, 56, 56, 90, 85, 43, 109, 78, 70, 99, 116, 75, 121, 54, 108, 118, 82, 79, 85, 98, 81, 99, 47, 104, 104, 113, 102, 75, 10, 48, 71, 113, 102, 118, 69, 121, 78, 66, 106, 78, 97, 111, 111, 88, 108, 107, 68, 87, 103, 89, 108, 119, 87, 84, 118, 68, 106, 111, 118, 111, 68, 71, 114, 81, 115, 99, 98, 78, 89, 76, 78, 53, 55, 67, 57, 115, 97, 68, 43, 118, 101, 73, 82, 56, 71, 100, 119, 89, 68, 115, 77, 110, 118, 109, 102, 122, 65, 117, 85, 56, 76, 104, 105, 106, 43, 10, 48, 114, 110, 113, 52, 57, 113, 108, 119, 48, 100, 112, 69, 117, 68, 98, 56, 80, 89, 90, 105, 43, 49, 55, 99, 78, 99, 67, 49, 117, 50, 72, 71, 67, 103, 115, 66, 67, 82, 77, 100, 43, 82, 73, 105, 104, 114, 71, 79, 53, 114, 85, 68, 56, 114, 54, 100, 100, 73, 66, 81, 70, 113, 78, 101, 98, 43, 76, 122, 48, 118, 80, 113, 104, 98, 66, 10, 108, 101, 83, 116, 84, 73, 111, 43, 70, 53, 72, 85, 115, 87, 76, 108, 103, 117, 87, 65, 66, 75, 81, 68, 102, 111, 50, 47, 50, 110, 43, 105, 68, 53, 100, 80, 68, 78, 77, 78, 43, 57, 102, 82, 53, 88, 74, 43, 72, 77, 104, 51, 47, 49, 117, 97, 68, 55, 101, 117, 66, 85, 98, 108, 56, 97, 103, 87, 55, 69, 101, 107, 70, 119, 73, 68, 10, 65, 81, 65, 66, 111, 52, 72, 50, 77, 73, 72, 122, 77, 73, 71, 119, 66, 103, 78, 86, 72, 82, 69, 69, 103, 97, 103, 119, 103, 97, 87, 66, 68, 50, 108, 117, 90, 109, 57, 65, 97, 88, 112, 108, 98, 110, 66, 108, 76, 109, 78, 118, 98, 97, 83, 66, 107, 84, 67, 66, 106, 106, 70, 72, 77, 69, 85, 71, 65, 49, 85, 69, 67, 103, 119, 43, 10, 83, 86, 112, 70, 84, 108, 66, 70, 73, 70, 77, 117, 81, 83, 52, 103, 76, 83, 66, 68, 83, 85, 89, 103, 81, 84, 65, 120, 77, 122, 77, 51, 77, 106, 89, 119, 76, 86, 74, 78, 90, 88, 74, 106, 76, 108, 90, 112, 100, 71, 57, 121, 97, 87, 69, 116, 82, 50, 70, 122, 100, 71, 86, 112, 101, 105, 66, 85, 77, 84, 65, 49, 78, 83, 66, 71, 10, 78, 106, 73, 103, 85, 122, 103, 120, 81, 122, 66, 66, 66, 103, 78, 86, 66, 65, 107, 77, 79, 107, 70, 50, 90, 71, 69, 103, 90, 71, 86, 115, 73, 69, 49, 108, 90, 71, 108, 48, 90, 88, 74, 121, 89, 87, 53, 108, 98, 121, 66, 70, 100, 71, 57, 121, 89, 109, 108, 107, 90, 87, 69, 103, 77, 84, 81, 103, 76, 83, 65, 119, 77, 84, 65, 120, 10, 77, 67, 66, 87, 97, 88, 82, 118, 99, 109, 108, 104, 76, 85, 100, 104, 99, 51, 82, 108, 97, 88, 111, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 10, 66, 66, 89, 69, 70, 66, 48, 99, 90, 81, 54, 111, 56, 105, 86, 55, 116, 74, 72, 80, 53, 76, 71, 120, 53, 114, 49, 86, 100, 71, 119, 70, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 67, 65, 81, 66, 52, 112, 103, 119, 87, 83, 112, 57, 77, 105, 68, 114, 65, 121, 119, 54, 108, 10, 70, 110, 50, 102, 117, 85, 104, 102, 71, 73, 56, 78, 89, 106, 98, 50, 122, 82, 108, 114, 114, 75, 118, 86, 57, 112, 70, 57, 114, 110, 72, 122, 80, 55, 77, 79, 101, 73, 87, 98, 108, 97, 81, 110, 73, 85, 100, 67, 83, 110, 120, 73, 79, 118, 86, 70, 102, 76, 77, 77, 106, 108, 70, 52, 114, 74, 85, 84, 51, 115, 98, 57, 102, 98, 103, 97, 10, 107, 69, 121, 114, 107, 103, 80, 72, 55, 85, 73, 66, 122, 103, 47, 89, 115, 102, 113, 105, 107, 117, 70, 103, 98, 97, 53, 54, 97, 119, 109, 113, 120, 105, 110, 117, 97, 69, 108, 110, 77, 73, 65, 107, 101, 106, 69, 87, 79, 86, 116, 43, 56, 82, 119, 117, 51, 87, 119, 74, 114, 102, 73, 120, 119, 89, 74, 79, 117, 98, 118, 53, 118, 114, 56, 113, 10, 104, 84, 47, 65, 81, 75, 77, 54, 87, 102, 120, 90, 83, 122, 119, 111, 74, 78, 117, 48, 70, 88, 87, 117, 68, 89, 105, 54, 76, 110, 80, 65, 118, 86, 105, 72, 53, 85, 76, 121, 54, 49, 55, 117, 72, 106, 65, 105, 109, 99, 115, 51, 48, 99, 81, 104, 98, 73, 72, 115, 118, 109, 48, 109, 53, 104, 122, 107, 81, 105, 67, 101, 82, 55, 67, 115, 10, 103, 49, 108, 119, 76, 68, 88, 87, 114, 122, 89, 48, 116, 77, 48, 55, 43, 68, 75, 111, 55, 43, 78, 52, 105, 102, 117, 78, 82, 83, 122, 97, 110, 76, 104, 43, 81, 66, 120, 104, 53, 122, 54, 105, 107, 105, 120, 76, 56, 115, 51, 54, 109, 76, 89, 112, 47, 47, 80, 121, 101, 54, 107, 102, 76, 113, 67, 84, 86, 121, 118, 101, 104, 81, 80, 53, 10, 97, 84, 102, 76, 110, 110, 104, 113, 66, 98, 84, 70, 77, 88, 105, 74, 55, 72, 113, 110, 104, 101, 71, 53, 101, 122, 122, 101, 118, 104, 53, 53, 104, 77, 54, 102, 99, 65, 53, 90, 119, 106, 85, 117, 107, 67, 111, 120, 50, 101, 82, 70, 101, 107, 71, 107, 76, 104, 79, 98, 78, 65, 53, 109, 101, 48, 109, 114, 90, 74, 102, 81, 82, 115, 78, 53, 10, 110, 88, 74, 81, 89, 54, 97, 89, 87, 119, 97, 57, 83, 71, 51, 89, 79, 89, 78, 119, 54, 68, 88, 119, 66, 100, 71, 113, 118, 79, 80, 98, 121, 65, 76, 113, 102, 80, 50, 67, 50, 115, 74, 98, 85, 106, 87, 117, 109, 68, 113, 116, 117, 106, 87, 84, 73, 54, 99, 102, 83, 78, 48, 49, 82, 112, 105, 121, 69, 71, 106, 107, 112, 84, 72, 67, 10, 67, 108, 103, 117, 71, 89, 69, 81, 121, 86, 66, 49, 47, 79, 112, 97, 70, 115, 52, 82, 49, 43, 55, 118, 85, 73, 103, 116, 89, 102, 56, 47, 81, 110, 77, 70, 108, 69, 80, 86, 106, 106, 120, 79, 65, 84, 111, 90, 112, 82, 57, 71, 84, 110, 102, 81, 88, 101, 87, 66, 73, 105, 71, 72, 47, 112, 82, 57, 104, 78, 105, 84, 114, 100, 90, 111, 10, 81, 48, 105, 121, 50, 43, 116, 122, 74, 79, 101, 82, 102, 49, 83, 107, 116, 111, 65, 43, 110, 97, 77, 56, 84, 72, 76, 67, 86, 56, 83, 103, 49, 77, 119, 52, 74, 56, 55, 86, 66, 112, 54, 105, 83, 78, 110, 112, 110, 56, 54, 67, 99, 68, 97, 84, 109, 106, 118, 102, 108, 105, 72, 106, 87, 98, 99, 77, 50, 112, 69, 51, 56, 80, 49, 90, 10, 87, 114, 79, 90, 121, 71, 108, 115, 81, 121, 89, 66, 78, 87, 78, 103, 86, 89, 107, 68, 79, 110, 88, 89, 117, 107, 114, 90, 86, 80, 47, 117, 51, 111, 68, 89, 76, 100, 69, 52, 49, 86, 52, 116, 67, 53, 104, 57, 80, 109, 122, 98, 47, 67, 97, 73, 120, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 104, 97, 109, 98, 101, 114, 115, 32, 111, 102, 32, 67, 111, 109, 109, 101, 114, 99, 101, 32, 82, 111, 111, 116, 32, 45, 32, 50, 48, 48, 56, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 72, 84, 122, 67, 67, 66, 84, 101, 103, 65, 119, 73, 66, 65, 103, 73, 74, 65, 75, 80, 97, 81, 110, 54, 107, 115, 97, 55, 97, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 77, 73, 71, 117, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 70, 86, 84, 70, 68, 10, 77, 69, 69, 71, 65, 49, 85, 69, 66, 120, 77, 54, 84, 87, 70, 107, 99, 109, 108, 107, 73, 67, 104, 122, 90, 87, 85, 103, 89, 51, 86, 121, 99, 109, 86, 117, 100, 67, 66, 104, 90, 71, 82, 121, 90, 88, 78, 122, 73, 71, 70, 48, 73, 72, 100, 51, 100, 121, 53, 106, 89, 87, 49, 108, 99, 109, 90, 112, 99, 109, 49, 104, 76, 109, 78, 118, 10, 98, 83, 57, 104, 90, 71, 82, 121, 90, 88, 78, 122, 75, 84, 69, 83, 77, 66, 65, 71, 65, 49, 85, 69, 66, 82, 77, 74, 81, 84, 103, 121, 78, 122, 81, 122, 77, 106, 103, 51, 77, 82, 115, 119, 71, 81, 89, 68, 86, 81, 81, 75, 69, 120, 74, 66, 81, 121, 66, 68, 89, 87, 49, 108, 99, 109, 90, 112, 99, 109, 49, 104, 73, 70, 77, 117, 10, 81, 83, 52, 120, 75, 84, 65, 110, 66, 103, 78, 86, 66, 65, 77, 84, 73, 69, 78, 111, 89, 87, 49, 105, 90, 88, 74, 122, 73, 71, 57, 109, 73, 69, 78, 118, 98, 87, 49, 108, 99, 109, 78, 108, 73, 70, 74, 118, 98, 51, 81, 103, 76, 83, 65, 121, 77, 68, 65, 52, 77, 66, 52, 88, 68, 84, 65, 52, 77, 68, 103, 119, 77, 84, 69, 121, 10, 77, 106, 107, 49, 77, 70, 111, 88, 68, 84, 77, 52, 77, 68, 99, 122, 77, 84, 69, 121, 77, 106, 107, 49, 77, 70, 111, 119, 103, 97, 52, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 86, 86, 77, 85, 77, 119, 81, 81, 89, 68, 86, 81, 81, 72, 69, 122, 112, 78, 89, 87, 82, 121, 97, 87, 81, 103, 75, 72, 78, 108, 10, 90, 83, 66, 106, 100, 88, 74, 121, 90, 87, 53, 48, 73, 71, 70, 107, 90, 72, 74, 108, 99, 51, 77, 103, 89, 88, 81, 103, 100, 51, 100, 51, 76, 109, 78, 104, 98, 87, 86, 121, 90, 109, 108, 121, 98, 87, 69, 117, 89, 50, 57, 116, 76, 50, 70, 107, 90, 72, 74, 108, 99, 51, 77, 112, 77, 82, 73, 119, 69, 65, 89, 68, 86, 81, 81, 70, 10, 69, 119, 108, 66, 79, 68, 73, 51, 78, 68, 77, 121, 79, 68, 99, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 111, 84, 69, 107, 70, 68, 73, 69, 78, 104, 98, 87, 86, 121, 90, 109, 108, 121, 98, 87, 69, 103, 85, 121, 53, 66, 76, 106, 69, 112, 77, 67, 99, 71, 65, 49, 85, 69, 65, 120, 77, 103, 81, 50, 104, 104, 98, 87, 74, 108, 10, 99, 110, 77, 103, 98, 50, 89, 103, 81, 50, 57, 116, 98, 87, 86, 121, 89, 50, 85, 103, 85, 109, 57, 118, 100, 67, 65, 116, 73, 68, 73, 119, 77, 68, 103, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 10, 65, 81, 67, 118, 65, 77, 116, 119, 78, 121, 117, 65, 87, 107, 111, 54, 98, 72, 105, 85, 102, 97, 78, 47, 71, 104, 47, 50, 78, 100, 87, 57, 50, 56, 115, 78, 82, 72, 73, 43, 74, 114, 75, 81, 85, 114, 112, 106, 79, 121, 104, 89, 98, 54, 87, 122, 98, 90, 83, 109, 56, 57, 49, 107, 68, 70, 88, 50, 57, 117, 102, 121, 73, 105, 75, 65, 10, 88, 117, 70, 105, 120, 114, 89, 112, 52, 89, 70, 115, 56, 114, 47, 108, 102, 84, 74, 113, 86, 75, 65, 121, 71, 86, 110, 43, 72, 52, 118, 88, 80, 87, 67, 71, 104, 83, 82, 118, 52, 120, 71, 122, 100, 122, 52, 103, 108, 106, 85, 104, 97, 55, 77, 73, 50, 88, 65, 117, 90, 80, 101, 69, 107, 108, 80, 87, 68, 114, 67, 81, 105, 111, 114, 106, 10, 104, 52, 48, 71, 48, 55, 50, 81, 68, 117, 75, 90, 111, 82, 117, 71, 68, 116, 113, 97, 67, 114, 115, 76, 89, 86, 65, 71, 85, 118, 71, 101, 102, 51, 98, 115, 121, 119, 47, 81, 72, 103, 51, 80, 109, 84, 65, 57, 72, 77, 82, 70, 69, 70, 105, 115, 49, 116, 80, 111, 49, 43, 88, 113, 120, 81, 69, 72, 100, 57, 90, 82, 53, 103, 78, 47, 10, 105, 107, 105, 108, 84, 87, 104, 49, 117, 101, 109, 56, 110, 107, 52, 90, 99, 102, 85, 121, 83, 53, 120, 116, 89, 66, 107, 76, 43, 56, 121, 100, 100, 100, 121, 47, 74, 115, 50, 80, 107, 51, 103, 53, 101, 88, 78, 101, 74, 81, 55, 75, 88, 79, 116, 51, 69, 103, 102, 76, 90, 69, 70, 72, 99, 112, 79, 114, 85, 77, 80, 114, 67, 88, 90, 107, 10, 78, 78, 73, 53, 116, 51, 89, 82, 67, 81, 49, 50, 82, 99, 83, 112, 114, 106, 49, 113, 114, 55, 86, 57, 90, 83, 43, 85, 87, 66, 68, 115, 88, 72, 121, 118, 102, 117, 75, 50, 71, 78, 110, 81, 109, 48, 53, 97, 83, 100, 43, 112, 90, 103, 118, 77, 80, 77, 90, 52, 102, 75, 101, 99, 72, 101, 80, 79, 106, 108, 79, 43, 66, 100, 53, 103, 10, 68, 50, 118, 108, 71, 116, 115, 47, 52, 43, 69, 104, 121, 83, 110, 66, 56, 101, 115, 72, 110, 70, 73, 98, 65, 85, 82, 82, 80, 72, 115, 108, 49, 56, 84, 108, 85, 108, 82, 100, 74, 81, 102, 75, 70, 105, 67, 52, 114, 101, 82, 66, 55, 110, 111, 73, 47, 112, 108, 118, 103, 54, 97, 82, 65, 114, 66, 115, 78, 108, 86, 113, 53, 51, 51, 49, 10, 108, 117, 98, 75, 103, 100, 97, 88, 56, 90, 83, 68, 54, 101, 50, 119, 115, 87, 115, 83, 97, 82, 54, 115, 43, 49, 50, 112, 120, 90, 106, 112, 116, 70, 116, 89, 101, 114, 52, 57, 111, 107, 81, 54, 89, 49, 110, 85, 67, 121, 88, 101, 71, 48, 43, 57, 53, 81, 71, 101, 122, 100, 73, 112, 49, 90, 56, 88, 71, 81, 112, 118, 118, 119, 121, 81, 10, 48, 119, 108, 102, 50, 101, 79, 75, 78, 99, 120, 53, 87, 107, 48, 90, 78, 53, 75, 51, 120, 77, 71, 116, 114, 47, 82, 53, 74, 74, 113, 121, 65, 81, 117, 120, 114, 49, 121, 87, 56, 52, 65, 121, 43, 49, 119, 57, 109, 80, 71, 103, 80, 48, 114, 101, 118, 113, 43, 85, 76, 116, 108, 86, 109, 104, 100, 117, 89, 74, 49, 106, 98, 76, 104, 106, 10, 121, 97, 54, 66, 88, 66, 103, 49, 52, 74, 67, 55, 118, 106, 120, 80, 78, 121, 75, 53, 102, 117, 118, 80, 110, 110, 99, 104, 112, 106, 48, 52, 103, 102, 116, 73, 50, 106, 69, 57, 75, 43, 79, 74, 57, 100, 67, 49, 118, 88, 55, 103, 85, 77, 81, 83, 105, 98, 77, 106, 109, 104, 65, 120, 104, 100, 117, 117, 98, 43, 56, 52, 77, 120, 104, 50, 10, 69, 81, 73, 68, 65, 81, 65, 66, 111, 52, 73, 66, 98, 68, 67, 67, 65, 87, 103, 119, 69, 103, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 103, 119, 66, 103, 69, 66, 47, 119, 73, 66, 68, 68, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 43, 83, 83, 115, 68, 55, 75, 49, 43, 72, 110, 65, 43, 109, 67, 73, 10, 71, 56, 84, 90, 84, 81, 75, 101, 70, 120, 107, 119, 103, 101, 77, 71, 65, 49, 85, 100, 73, 119, 83, 66, 50, 122, 67, 66, 50, 73, 65, 85, 43, 83, 83, 115, 68, 55, 75, 49, 43, 72, 110, 65, 43, 109, 67, 73, 71, 56, 84, 90, 84, 81, 75, 101, 70, 120, 109, 104, 103, 98, 83, 107, 103, 98, 69, 119, 103, 97, 52, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 86, 86, 77, 85, 77, 119, 81, 81, 89, 68, 86, 81, 81, 72, 69, 122, 112, 78, 89, 87, 82, 121, 97, 87, 81, 103, 75, 72, 78, 108, 90, 83, 66, 106, 100, 88, 74, 121, 90, 87, 53, 48, 73, 71, 70, 107, 90, 72, 74, 108, 99, 51, 77, 103, 89, 88, 81, 103, 100, 51, 100, 51, 76, 109, 78, 104, 10, 98, 87, 86, 121, 90, 109, 108, 121, 98, 87, 69, 117, 89, 50, 57, 116, 76, 50, 70, 107, 90, 72, 74, 108, 99, 51, 77, 112, 77, 82, 73, 119, 69, 65, 89, 68, 86, 81, 81, 70, 69, 119, 108, 66, 79, 68, 73, 51, 78, 68, 77, 121, 79, 68, 99, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 111, 84, 69, 107, 70, 68, 73, 69, 78, 104, 10, 98, 87, 86, 121, 90, 109, 108, 121, 98, 87, 69, 103, 85, 121, 53, 66, 76, 106, 69, 112, 77, 67, 99, 71, 65, 49, 85, 69, 65, 120, 77, 103, 81, 50, 104, 104, 98, 87, 74, 108, 99, 110, 77, 103, 98, 50, 89, 103, 81, 50, 57, 116, 98, 87, 86, 121, 89, 50, 85, 103, 85, 109, 57, 118, 100, 67, 65, 116, 73, 68, 73, 119, 77, 68, 105, 67, 10, 67, 81, 67, 106, 50, 107, 74, 43, 112, 76, 71, 117, 50, 106, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 80, 81, 89, 68, 86, 82, 48, 103, 66, 68, 89, 119, 78, 68, 65, 121, 66, 103, 82, 86, 72, 83, 65, 65, 77, 67, 111, 119, 75, 65, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 10, 65, 103, 69, 87, 72, 71, 104, 48, 100, 72, 65, 54, 76, 121, 57, 119, 98, 50, 120, 112, 89, 51, 107, 117, 89, 50, 70, 116, 90, 88, 74, 109, 97, 88, 74, 116, 89, 83, 53, 106, 98, 50, 48, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 73, 66, 65, 74, 65, 83, 114, 121, 73, 49, 10, 119, 113, 77, 53, 56, 67, 55, 101, 54, 98, 88, 112, 101, 72, 120, 73, 118, 106, 57, 57, 82, 90, 74, 101, 54, 100, 113, 120, 71, 102, 119, 87, 80, 74, 43, 48, 87, 50, 97, 101, 97, 117, 102, 68, 117, 86, 50, 73, 54, 65, 43, 116, 122, 121, 77, 80, 51, 105, 85, 54, 88, 115, 120, 80, 112, 99, 71, 49, 76, 97, 119, 107, 48, 108, 103, 72, 10, 51, 113, 76, 80, 97, 89, 82, 103, 77, 43, 103, 81, 68, 82, 79, 112, 73, 57, 67, 70, 53, 89, 53, 55, 112, 112, 52, 57, 99, 104, 78, 121, 77, 47, 87, 113, 102, 99, 90, 106, 72, 119, 106, 48, 47, 103, 70, 47, 74, 77, 56, 114, 76, 70, 81, 74, 51, 117, 73, 114, 98, 90, 76, 71, 79, 85, 56, 87, 54, 106, 120, 43, 101, 107, 98, 85, 10, 82, 87, 112, 71, 113, 79, 116, 49, 103, 108, 97, 110, 113, 54, 66, 56, 97, 66, 77, 122, 57, 112, 48, 119, 56, 71, 56, 110, 79, 83, 81, 106, 75, 112, 68, 57, 107, 67, 107, 49, 56, 112, 80, 102, 78, 75, 88, 71, 57, 47, 106, 118, 106, 65, 57, 105, 83, 110, 121, 117, 48, 47, 86, 85, 43, 73, 50, 50, 109, 108, 97, 72, 70, 111, 73, 54, 10, 77, 54, 116, 97, 73, 103, 106, 51, 103, 114, 114, 113, 76, 117, 66, 72, 109, 114, 83, 49, 82, 97, 77, 70, 79, 57, 110, 99, 76, 107, 86, 65, 79, 43, 114, 99, 102, 43, 103, 55, 54, 57, 72, 115, 74, 116, 103, 49, 112, 68, 68, 70, 79, 113, 120, 88, 110, 114, 78, 50, 112, 83, 66, 55, 43, 82, 53, 75, 66, 87, 73, 66, 112, 105, 104, 49, 10, 89, 74, 101, 83, 68, 87, 52, 43, 84, 84, 100, 68, 68, 90, 73, 86, 110, 66, 103, 105, 122, 86, 71, 90, 111, 67, 107, 97, 80, 70, 43, 75, 77, 106, 78, 98, 77, 77, 101, 74, 76, 48, 101, 89, 68, 54, 77, 68, 120, 118, 98, 120, 114, 78, 56, 121, 56, 78, 109, 66, 71, 117, 83, 99, 118, 102, 97, 65, 70, 80, 68, 82, 76, 76, 109, 70, 10, 57, 100, 105, 106, 115, 99, 105, 108, 73, 101, 85, 99, 69, 53, 102, 117, 68, 114, 51, 102, 75, 97, 110, 118, 78, 70, 78, 98, 48, 43, 82, 113, 69, 52, 81, 71, 116, 106, 73, 67, 120, 70, 75, 117, 73, 116, 76, 99, 115, 105, 70, 67, 71, 116, 112, 65, 56, 67, 110, 74, 55, 65, 111, 77, 88, 79, 76, 81, 117, 115, 120, 73, 48, 122, 99, 75, 10, 122, 66, 73, 75, 105, 110, 109, 119, 80, 81, 78, 47, 97, 85, 118, 48, 78, 67, 66, 57, 115, 122, 84, 113, 106, 107, 116, 107, 57, 84, 55, 57, 115, 121, 78, 110, 70, 81, 48, 69, 117, 80, 65, 116, 119, 81, 108, 82, 80, 76, 74, 115, 70, 102, 67, 108, 73, 57, 101, 68, 100, 79, 84, 108, 76, 115, 110, 43, 109, 67, 100, 67, 120, 113, 118, 71, 10, 110, 114, 68, 81, 87, 122, 105, 108, 109, 49, 68, 101, 102, 104, 105, 89, 116, 85, 85, 55, 57, 110, 109, 48, 54, 80, 99, 97, 101, 119, 97, 68, 43, 57, 67, 76, 50, 114, 118, 72, 118, 82, 105, 114, 67, 71, 56, 56, 103, 71, 116, 65, 80, 120, 107, 90, 117, 109, 87, 75, 53, 114, 55, 86, 88, 78, 77, 50, 49, 43, 57, 65, 85, 105, 82, 103, 10, 79, 71, 99, 69, 77, 101, 121, 80, 56, 52, 76, 71, 51, 114, 108, 86, 56, 122, 115, 120, 107, 86, 114, 99, 116, 81, 103, 86, 114, 88, 89, 108, 67, 103, 49, 55, 76, 111, 102, 105, 68, 75, 89, 71, 118, 67, 89, 81, 98, 84, 101, 100, 55, 78, 49, 52, 106, 72, 121, 65, 120, 102, 68, 90, 100, 48, 106, 81, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 108, 111, 98, 97, 108, 32, 67, 104, 97, 109, 98, 101, 114, 115, 105, 103, 110, 32, 82, 111, 111, 116, 32, 45, 32, 50, 48, 48, 56, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 72, 83, 84, 67, 67, 66, 84, 71, 103, 65, 119, 73, 66, 65, 103, 73, 74, 65, 77, 110, 78, 48, 43, 110, 86, 102, 83, 80, 79, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 77, 73, 71, 115, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 70, 86, 84, 70, 68, 10, 77, 69, 69, 71, 65, 49, 85, 69, 66, 120, 77, 54, 84, 87, 70, 107, 99, 109, 108, 107, 73, 67, 104, 122, 90, 87, 85, 103, 89, 51, 86, 121, 99, 109, 86, 117, 100, 67, 66, 104, 90, 71, 82, 121, 90, 88, 78, 122, 73, 71, 70, 48, 73, 72, 100, 51, 100, 121, 53, 106, 89, 87, 49, 108, 99, 109, 90, 112, 99, 109, 49, 104, 76, 109, 78, 118, 10, 98, 83, 57, 104, 90, 71, 82, 121, 90, 88, 78, 122, 75, 84, 69, 83, 77, 66, 65, 71, 65, 49, 85, 69, 66, 82, 77, 74, 81, 84, 103, 121, 78, 122, 81, 122, 77, 106, 103, 51, 77, 82, 115, 119, 71, 81, 89, 68, 86, 81, 81, 75, 69, 120, 74, 66, 81, 121, 66, 68, 89, 87, 49, 108, 99, 109, 90, 112, 99, 109, 49, 104, 73, 70, 77, 117, 10, 81, 83, 52, 120, 74, 122, 65, 108, 66, 103, 78, 86, 66, 65, 77, 84, 72, 107, 100, 115, 98, 50, 74, 104, 98, 67, 66, 68, 97, 71, 70, 116, 89, 109, 86, 121, 99, 50, 108, 110, 98, 105, 66, 83, 98, 50, 57, 48, 73, 67, 48, 103, 77, 106, 65, 119, 79, 68, 65, 101, 70, 119, 48, 119, 79, 68, 65, 52, 77, 68, 69, 120, 77, 106, 77, 120, 10, 78, 68, 66, 97, 70, 119, 48, 122, 79, 68, 65, 51, 77, 122, 69, 120, 77, 106, 77, 120, 78, 68, 66, 97, 77, 73, 71, 115, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 70, 86, 84, 70, 68, 77, 69, 69, 71, 65, 49, 85, 69, 66, 120, 77, 54, 84, 87, 70, 107, 99, 109, 108, 107, 73, 67, 104, 122, 90, 87, 85, 103, 10, 89, 51, 86, 121, 99, 109, 86, 117, 100, 67, 66, 104, 90, 71, 82, 121, 90, 88, 78, 122, 73, 71, 70, 48, 73, 72, 100, 51, 100, 121, 53, 106, 89, 87, 49, 108, 99, 109, 90, 112, 99, 109, 49, 104, 76, 109, 78, 118, 98, 83, 57, 104, 90, 71, 82, 121, 90, 88, 78, 122, 75, 84, 69, 83, 77, 66, 65, 71, 65, 49, 85, 69, 66, 82, 77, 74, 10, 81, 84, 103, 121, 78, 122, 81, 122, 77, 106, 103, 51, 77, 82, 115, 119, 71, 81, 89, 68, 86, 81, 81, 75, 69, 120, 74, 66, 81, 121, 66, 68, 89, 87, 49, 108, 99, 109, 90, 112, 99, 109, 49, 104, 73, 70, 77, 117, 81, 83, 52, 120, 74, 122, 65, 108, 66, 103, 78, 86, 66, 65, 77, 84, 72, 107, 100, 115, 98, 50, 74, 104, 98, 67, 66, 68, 10, 97, 71, 70, 116, 89, 109, 86, 121, 99, 50, 108, 110, 98, 105, 66, 83, 98, 50, 57, 48, 73, 67, 48, 103, 77, 106, 65, 119, 79, 68, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 77, 68, 102, 10, 86, 116, 80, 107, 79, 112, 116, 50, 82, 98, 81, 84, 50, 47, 47, 66, 116, 104, 109, 76, 78, 48, 69, 89, 108, 86, 74, 72, 54, 120, 101, 100, 75, 89, 105, 79, 78, 87, 119, 71, 77, 105, 53, 72, 89, 118, 78, 74, 66, 76, 57, 57, 82, 68, 97, 120, 99, 99, 121, 57, 87, 103, 108, 122, 49, 100, 109, 70, 82, 80, 43, 82, 86, 121, 88, 102, 10, 88, 106, 97, 79, 99, 78, 70, 99, 99, 85, 77, 100, 50, 100, 114, 118, 88, 78, 76, 55, 71, 55, 48, 54, 116, 99, 117, 116, 111, 56, 120, 69, 112, 119, 50, 117, 73, 82, 85, 47, 117, 88, 112, 98, 107, 110, 88, 89, 112, 66, 73, 52, 105, 82, 109, 75, 116, 52, 68, 83, 52, 106, 74, 118, 86, 112, 121, 82, 49, 111, 103, 81, 67, 55, 78, 48, 10, 90, 74, 74, 48, 89, 80, 80, 50, 122, 120, 104, 80, 89, 76, 73, 106, 48, 77, 99, 55, 122, 109, 70, 76, 109, 89, 47, 67, 68, 78, 66, 65, 115, 112, 106, 99, 68, 97, 104, 79, 111, 55, 107, 75, 114, 109, 67, 103, 114, 85, 86, 83, 89, 55, 112, 109, 118, 87, 106, 103, 43, 98, 52, 97, 113, 73, 71, 55, 72, 107, 70, 52, 100, 100, 80, 66, 10, 47, 103, 66, 86, 115, 73, 100, 85, 54, 67, 101, 81, 78, 82, 49, 77, 77, 54, 50, 88, 47, 74, 99, 117, 109, 73, 83, 47, 76, 77, 109, 106, 118, 57, 71, 89, 69, 82, 84, 116, 89, 47, 106, 75, 109, 73, 104, 89, 70, 53, 110, 116, 82, 81, 79, 88, 102, 106, 121, 71, 72, 111, 105, 77, 118, 118, 75, 82, 104, 73, 57, 108, 78, 78, 103, 65, 10, 84, 72, 50, 51, 77, 82, 100, 97, 75, 88, 111, 75, 71, 67, 81, 119, 111, 122, 101, 49, 101, 113, 107, 66, 102, 83, 98, 87, 43, 81, 54, 79, 87, 102, 72, 57, 71, 122, 79, 49, 75, 84, 115, 88, 79, 48, 71, 50, 73, 100, 51, 85, 119, 68, 50, 108, 110, 53, 56, 102, 81, 49, 68, 74, 117, 55, 120, 115, 101, 112, 101, 89, 55, 115, 50, 77, 10, 72, 47, 117, 99, 85, 97, 54, 76, 99, 76, 48, 110, 110, 51, 72, 65, 97, 54, 120, 57, 107, 71, 98, 111, 49, 49, 48, 54, 68, 98, 68, 86, 119, 111, 51, 86, 121, 74, 50, 100, 119, 87, 51, 81, 48, 76, 57, 82, 53, 79, 80, 52, 119, 122, 103, 50, 114, 116, 97, 110, 100, 101, 97, 118, 104, 69, 78, 100, 107, 53, 73, 77, 97, 103, 102, 101, 10, 79, 120, 50, 89, 73, 116, 97, 115, 119, 84, 88, 98, 111, 54, 65, 108, 47, 51, 75, 49, 100, 104, 51, 101, 98, 101, 107, 115, 90, 105, 120, 83, 104, 78, 66, 70, 107, 115, 52, 99, 53, 101, 85, 122, 72, 100, 119, 72, 85, 49, 83, 106, 113, 111, 73, 55, 109, 106, 99, 118, 51, 78, 50, 103, 90, 79, 110, 109, 51, 98, 50, 117, 47, 71, 83, 70, 10, 72, 84, 121, 110, 121, 81, 98, 101, 104, 80, 57, 114, 54, 71, 115, 97, 80, 77, 87, 105, 115, 48, 76, 55, 105, 119, 107, 43, 88, 119, 104, 83, 120, 50, 76, 69, 49, 65, 86, 120, 118, 56, 82, 107, 53, 80, 105, 104, 103, 43, 103, 43, 69, 112, 117, 111, 72, 116, 81, 50, 84, 83, 57, 120, 57, 111, 48, 111, 57, 111, 79, 112, 69, 57, 74, 104, 10, 119, 90, 71, 55, 83, 77, 65, 48, 106, 48, 71, 77, 83, 48, 122, 98, 97, 82, 76, 47, 85, 74, 83, 99, 73, 73, 78, 90, 99, 43, 49, 56, 111, 102, 76, 120, 47, 100, 51, 51, 83, 100, 78, 68, 87, 75, 66, 87, 89, 56, 111, 57, 80, 101, 85, 49, 86, 108, 110, 112, 68, 115, 111, 103, 122, 67, 116, 76, 107, 121, 107, 80, 65, 103, 77, 66, 10, 65, 65, 71, 106, 103, 103, 70, 113, 77, 73, 73, 66, 90, 106, 65, 83, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 67, 68, 65, 71, 65, 81, 72, 47, 65, 103, 69, 77, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 83, 53, 67, 99, 113, 99, 72, 116, 118, 84, 98, 68, 112, 114, 114, 117, 49, 85, 56, 86, 117, 84, 10, 66, 106, 85, 117, 88, 106, 67, 66, 52, 81, 89, 68, 86, 82, 48, 106, 66, 73, 72, 90, 77, 73, 72, 87, 103, 66, 83, 53, 67, 99, 113, 99, 72, 116, 118, 84, 98, 68, 112, 114, 114, 117, 49, 85, 56, 86, 117, 84, 66, 106, 85, 117, 88, 113, 71, 66, 115, 113, 83, 66, 114, 122, 67, 66, 114, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 82, 86, 85, 120, 81, 122, 66, 66, 66, 103, 78, 86, 66, 65, 99, 84, 79, 107, 49, 104, 90, 72, 74, 112, 90, 67, 65, 111, 99, 50, 86, 108, 73, 71, 78, 49, 99, 110, 74, 108, 98, 110, 81, 103, 89, 87, 82, 107, 99, 109, 86, 122, 99, 121, 66, 104, 100, 67, 66, 51, 100, 51, 99, 117, 89, 50, 70, 116, 90, 88, 74, 109, 10, 97, 88, 74, 116, 89, 83, 53, 106, 98, 50, 48, 118, 89, 87, 82, 107, 99, 109, 86, 122, 99, 121, 107, 120, 69, 106, 65, 81, 66, 103, 78, 86, 66, 65, 85, 84, 67, 85, 69, 52, 77, 106, 99, 48, 77, 122, 73, 52, 78, 122, 69, 98, 77, 66, 107, 71, 65, 49, 85, 69, 67, 104, 77, 83, 81, 85, 77, 103, 81, 50, 70, 116, 90, 88, 74, 109, 10, 97, 88, 74, 116, 89, 83, 66, 84, 76, 107, 69, 117, 77, 83, 99, 119, 74, 81, 89, 68, 86, 81, 81, 68, 69, 120, 53, 72, 98, 71, 57, 105, 89, 87, 119, 103, 81, 50, 104, 104, 98, 87, 74, 108, 99, 110, 78, 112, 90, 50, 52, 103, 85, 109, 57, 118, 100, 67, 65, 116, 73, 68, 73, 119, 77, 68, 105, 67, 67, 81, 68, 74, 122, 100, 80, 112, 10, 49, 88, 48, 106, 122, 106, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 80, 81, 89, 68, 86, 82, 48, 103, 66, 68, 89, 119, 78, 68, 65, 121, 66, 103, 82, 86, 72, 83, 65, 65, 77, 67, 111, 119, 75, 65, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 103, 69, 87, 72, 71, 104, 48, 10, 100, 72, 65, 54, 76, 121, 57, 119, 98, 50, 120, 112, 89, 51, 107, 117, 89, 50, 70, 116, 90, 88, 74, 109, 97, 88, 74, 116, 89, 83, 53, 106, 98, 50, 48, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 73, 66, 65, 73, 67, 73, 102, 51, 68, 101, 107, 105, 106, 90, 66, 90, 82, 71, 10, 47, 53, 66, 88, 113, 102, 69, 118, 51, 120, 111, 78, 97, 47, 112, 56, 68, 104, 120, 74, 74, 72, 107, 110, 50, 69, 97, 113, 98, 121, 108, 90, 85, 111, 104, 119, 69, 117, 114, 100, 80, 102, 87, 98, 85, 49, 82, 118, 52, 87, 67, 105, 113, 65, 109, 53, 55, 79, 116, 90, 102, 77, 89, 49, 56, 100, 119, 89, 54, 102, 70, 110, 53, 97, 43, 54, 10, 82, 101, 65, 74, 51, 115, 112, 69, 68, 56, 73, 88, 68, 110, 101, 82, 82, 88, 111, 122, 88, 49, 43, 87, 76, 71, 105, 76, 119, 85, 101, 80, 109, 74, 115, 57, 119, 79, 122, 76, 57, 100, 87, 67, 107, 111, 81, 49, 48, 98, 52, 50, 79, 70, 90, 121, 77, 86, 116, 72, 76, 97, 111, 88, 112, 71, 78, 82, 54, 119, 111, 66, 114, 88, 47, 115, 10, 100, 90, 55, 76, 111, 82, 47, 120, 102, 120, 75, 120, 117, 101, 82, 107, 102, 50, 102, 87, 73, 121, 114, 48, 117, 68, 108, 100, 109, 79, 103, 104, 112, 43, 71, 57, 80, 85, 73, 97, 100, 74, 112, 119, 114, 50, 104, 115, 85, 70, 49, 74, 122, 47, 47, 55, 68, 108, 51, 109, 76, 69, 102, 88, 103, 84, 112, 90, 65, 76, 86, 122, 97, 50, 77, 103, 10, 57, 106, 70, 70, 67, 68, 107, 79, 57, 72, 66, 43, 81, 72, 66, 97, 80, 57, 66, 114, 81, 113, 108, 48, 80, 83, 103, 118, 65, 109, 49, 49, 99, 112, 85, 74, 106, 85, 104, 106, 120, 115, 89, 106, 86, 53, 75, 84, 88, 106, 88, 66, 106, 102, 107, 75, 57, 121, 121, 100, 89, 104, 122, 50, 114, 88, 122, 100, 112, 106, 69, 101, 116, 114, 72, 72, 10, 102, 111, 85, 109, 43, 113, 82, 113, 116, 100, 112, 106, 77, 78, 72, 118, 107, 122, 101, 121, 90, 105, 57, 57, 66, 102, 102, 110, 116, 48, 117, 89, 108, 68, 88, 65, 50, 84, 111, 112, 119, 90, 50, 121, 85, 68, 77, 100, 83, 113, 108, 97, 112, 115, 107, 68, 55, 43, 51, 48, 53, 54, 104, 117, 105, 114, 82, 88, 104, 79, 117, 107, 80, 57, 68, 117, 10, 113, 113, 113, 72, 87, 50, 80, 111, 107, 43, 74, 114, 113, 78, 83, 52, 99, 110, 104, 114, 71, 43, 48, 53, 53, 70, 51, 76, 109, 54, 113, 72, 49, 85, 57, 79, 65, 80, 55, 90, 97, 112, 56, 56, 77, 81, 56, 111, 65, 103, 70, 57, 109, 79, 105, 110, 115, 75, 74, 107, 110, 110, 110, 52, 83, 80, 73, 86, 113, 99, 122, 109, 121, 69, 84, 114, 10, 80, 51, 105, 90, 56, 110, 116, 120, 80, 106, 122, 120, 109, 75, 102, 70, 71, 66, 73, 47, 53, 114, 115, 111, 77, 48, 76, 112, 82, 81, 112, 56, 98, 102, 75, 71, 101, 83, 47, 70, 103, 104, 108, 57, 67, 89, 108, 56, 115, 108, 82, 50, 105, 75, 55, 101, 119, 102, 80, 77, 52, 87, 55, 98, 77, 100, 97, 84, 114, 112, 109, 103, 55, 121, 86, 113, 10, 99, 53, 105, 74, 87, 122, 111, 117, 69, 52, 103, 101, 118, 56, 67, 83, 108, 68, 81, 98, 52, 121, 101, 51, 105, 120, 53, 118, 81, 118, 47, 110, 54, 84, 101, 98, 85, 66, 48, 116, 111, 118, 107, 67, 55, 115, 116, 89, 87, 68, 112, 120, 118, 71, 106, 106, 113, 115, 71, 118, 72, 67, 103, 102, 111, 116, 119, 106, 90, 84, 43, 66, 54, 113, 54, 90, 10, 48, 57, 103, 119, 122, 120, 77, 78, 84, 120, 88, 74, 104, 76, 121, 110, 83, 67, 51, 52, 77, 67, 78, 51, 50, 69, 90, 76, 101, 87, 51, 50, 106, 79, 48, 54, 102, 50, 65, 82, 101, 80, 84, 112, 109, 54, 55, 86, 86, 77, 66, 48, 103, 78, 69, 76, 81, 112, 47, 66, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 111, 32, 68, 97, 100, 100, 121, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 45, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 120, 84, 67, 67, 65, 113, 50, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 66, 103, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 69, 68, 65, 79, 66, 103, 78, 86, 66, 65, 103, 84, 10, 66, 48, 70, 121, 97, 88, 112, 118, 98, 109, 69, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 99, 84, 67, 108, 78, 106, 98, 51, 82, 48, 99, 50, 82, 104, 98, 71, 85, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 84, 69, 85, 100, 118, 82, 71, 70, 107, 90, 72, 107, 117, 89, 50, 57, 116, 76, 67, 66, 74, 98, 109, 77, 117, 10, 77, 84, 69, 119, 76, 119, 89, 68, 86, 81, 81, 68, 69, 121, 104, 72, 98, 121, 66, 69, 89, 87, 82, 107, 101, 83, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 83, 65, 116, 73, 69, 99, 121, 77, 66, 52, 88, 68, 84, 65, 53, 10, 77, 68, 107, 119, 77, 84, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 77, 51, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 103, 89, 77, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 65, 119, 68, 103, 89, 68, 86, 81, 81, 73, 69, 119, 100, 66, 99, 109, 108, 54, 10, 98, 50, 53, 104, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 72, 69, 119, 112, 84, 89, 50, 57, 48, 100, 72, 78, 107, 89, 87, 120, 108, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 69, 120, 70, 72, 98, 48, 82, 104, 90, 71, 82, 53, 76, 109, 78, 118, 98, 83, 119, 103, 83, 87, 53, 106, 76, 106, 69, 120, 77, 67, 56, 71, 10, 65, 49, 85, 69, 65, 120, 77, 111, 82, 50, 56, 103, 82, 71, 70, 107, 90, 72, 107, 103, 85, 109, 57, 118, 100, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 83, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 103, 76, 83, 66, 72, 77, 106, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 76, 57, 120, 89, 103, 106, 120, 43, 108, 107, 48, 57, 120, 118, 74, 71, 75, 80, 51, 103, 69, 108, 89, 54, 83, 75, 68, 69, 54, 98, 70, 73, 69, 77, 66, 79, 52, 84, 120, 53, 111, 86, 74, 110, 121, 102, 113, 10, 57, 111, 81, 98, 84, 113, 67, 48, 50, 51, 67, 89, 120, 122, 73, 66, 115, 81, 85, 43, 66, 48, 55, 117, 57, 80, 112, 80, 76, 49, 107, 119, 73, 117, 101, 114, 71, 86, 90, 114, 52, 111, 65, 72, 47, 80, 77, 87, 100, 89, 65, 53, 85, 88, 118, 108, 43, 84, 87, 50, 100, 69, 54, 112, 106, 89, 73, 84, 53, 76, 89, 47, 113, 81, 79, 68, 10, 43, 113, 75, 43, 105, 104, 86, 113, 102, 57, 52, 76, 119, 55, 89, 90, 70, 65, 88, 75, 54, 115, 79, 111, 66, 74, 81, 55, 82, 110, 119, 121, 68, 102, 77, 65, 90, 105, 76, 73, 106, 87, 108, 116, 78, 111, 119, 82, 71, 76, 102, 84, 115, 104, 120, 103, 116, 68, 106, 54, 65, 111, 122, 79, 48, 57, 49, 71, 66, 57, 52, 75, 80, 117, 116, 100, 10, 102, 77, 104, 56, 43, 55, 65, 114, 85, 54, 83, 83, 89, 109, 108, 82, 74, 81, 86, 104, 71, 107, 83, 66, 106, 67, 121, 112, 81, 53, 89, 106, 51, 54, 119, 54, 103, 90, 111, 79, 75, 99, 85, 99, 113, 101, 108, 100, 72, 114, 97, 101, 110, 106, 65, 75, 79, 99, 55, 120, 105, 73, 68, 55, 83, 49, 51, 77, 77, 117, 121, 70, 89, 107, 77, 108, 10, 78, 65, 74, 87, 74, 119, 71, 82, 116, 68, 116, 119, 75, 106, 57, 117, 115, 101, 105, 99, 105, 65, 70, 57, 110, 57, 84, 53, 50, 49, 78, 116, 89, 74, 50, 47, 76, 79, 100, 89, 113, 55, 104, 102, 82, 118, 122, 79, 120, 66, 115, 68, 80, 65, 110, 114, 83, 84, 70, 99, 97, 85, 97, 122, 52, 69, 99, 67, 65, 119, 69, 65, 65, 97, 78, 67, 10, 77, 69, 65, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 68, 113, 97, 104, 81, 99, 81, 90, 121, 105, 50, 55, 47, 97, 57, 10, 66, 85, 70, 117, 73, 77, 71, 85, 50, 103, 47, 101, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 66, 65, 81, 67, 90, 50, 49, 49, 53, 49, 102, 109, 88, 87, 87, 99, 68, 89, 102, 70, 43, 79, 119, 89, 120, 100, 83, 50, 104, 73, 73, 53, 80, 90, 89, 101, 48, 57, 54, 97, 99, 10, 118, 78, 106, 112, 76, 57, 68, 98, 87, 117, 55, 80, 100, 73, 120, 122, 116, 68, 104, 67, 50, 103, 86, 55, 43, 65, 74, 49, 117, 80, 50, 108, 115, 100, 101, 117, 57, 116, 102, 101, 69, 56, 116, 84, 69, 72, 54, 75, 82, 116, 71, 88, 43, 114, 99, 117, 75, 120, 71, 114, 107, 76, 65, 110, 103, 80, 110, 111, 110, 49, 114, 112, 78, 53, 43, 114, 10, 53, 78, 57, 115, 115, 52, 85, 88, 110, 84, 51, 90, 74, 69, 57, 53, 107, 84, 88, 87, 88, 119, 84, 114, 103, 73, 79, 114, 109, 103, 73, 116, 116, 82, 68, 48, 50, 74, 68, 72, 66, 72, 78, 65, 55, 88, 73, 108, 111, 75, 109, 102, 55, 74, 54, 114, 97, 66, 75, 90, 86, 56, 97, 80, 69, 106, 111, 74, 112, 76, 49, 69, 47, 81, 89, 86, 10, 78, 56, 71, 98, 53, 68, 75, 106, 55, 84, 106, 111, 50, 71, 84, 122, 76, 72, 52, 85, 47, 65, 76, 113, 110, 56, 51, 47, 66, 50, 103, 88, 50, 121, 75, 81, 79, 67, 49, 54, 106, 100, 70, 85, 56, 87, 110, 106, 88, 122, 80, 75, 101, 106, 49, 55, 67, 117, 80, 75, 102, 49, 56, 53, 53, 101, 74, 49, 117, 115, 86, 50, 71, 68, 80, 79, 10, 76, 80, 65, 118, 84, 75, 51, 51, 115, 101, 102, 79, 84, 54, 106, 69, 109, 48, 112, 85, 66, 115, 86, 47, 102, 100, 85, 73, 68, 43, 73, 99, 47, 110, 52, 88, 117, 75, 120, 101, 57, 116, 81, 87, 115, 107, 77, 74, 68, 69, 51, 50, 112, 50, 117, 48, 109, 89, 82, 108, 121, 110, 113, 73, 52, 117, 74, 69, 118, 108, 122, 51, 54, 104, 122, 49, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 116, 97, 114, 102, 105, 101, 108, 100, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 45, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 51, 84, 67, 67, 65, 115, 87, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 66, 106, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 69, 68, 65, 79, 66, 103, 78, 86, 66, 65, 103, 84, 10, 66, 48, 70, 121, 97, 88, 112, 118, 98, 109, 69, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 99, 84, 67, 108, 78, 106, 98, 51, 82, 48, 99, 50, 82, 104, 98, 71, 85, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 111, 84, 72, 70, 78, 48, 89, 88, 74, 109, 97, 87, 86, 115, 90, 67, 66, 85, 90, 87, 78, 111, 98, 109, 57, 115, 10, 98, 50, 100, 112, 90, 88, 77, 115, 73, 69, 108, 117, 89, 121, 52, 120, 77, 106, 65, 119, 66, 103, 78, 86, 66, 65, 77, 84, 75, 86, 78, 48, 89, 88, 74, 109, 97, 87, 86, 115, 90, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 10, 101, 83, 65, 116, 73, 69, 99, 121, 77, 66, 52, 88, 68, 84, 65, 53, 77, 68, 107, 119, 77, 84, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 77, 51, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 103, 89, 56, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 65, 119, 10, 68, 103, 89, 68, 86, 81, 81, 73, 69, 119, 100, 66, 99, 109, 108, 54, 98, 50, 53, 104, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 72, 69, 119, 112, 84, 89, 50, 57, 48, 100, 72, 78, 107, 89, 87, 120, 108, 77, 83, 85, 119, 73, 119, 89, 68, 86, 81, 81, 75, 69, 120, 120, 84, 100, 71, 70, 121, 90, 109, 108, 108, 98, 71, 81, 103, 10, 86, 71, 86, 106, 97, 71, 53, 118, 98, 71, 57, 110, 97, 87, 86, 122, 76, 67, 66, 74, 98, 109, 77, 117, 77, 84, 73, 119, 77, 65, 89, 68, 86, 81, 81, 68, 69, 121, 108, 84, 100, 71, 70, 121, 90, 109, 108, 108, 98, 71, 81, 103, 85, 109, 57, 118, 100, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 83, 66, 66, 10, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 103, 76, 83, 66, 72, 77, 106, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 76, 51, 116, 119, 81, 80, 56, 57, 111, 47, 56, 65, 114, 70, 118, 10, 87, 53, 57, 73, 50, 90, 49, 53, 52, 113, 75, 51, 65, 50, 70, 87, 71, 77, 78, 72, 116, 116, 102, 75, 80, 84, 85, 117, 105, 85, 80, 51, 111, 87, 109, 98, 51, 111, 111, 97, 47, 82, 77, 103, 110, 76, 82, 74, 100, 122, 73, 112, 86, 118, 50, 53, 55, 73, 122, 100, 73, 118, 112, 121, 51, 67, 100, 104, 108, 43, 55, 50, 87, 111, 84, 115, 10, 98, 104, 109, 53, 105, 83, 122, 99, 104, 70, 118, 86, 100, 80, 116, 114, 88, 56, 87, 74, 112, 82, 66, 83, 105, 85, 90, 86, 57, 76, 104, 49, 72, 79, 90, 47, 53, 70, 83, 117, 83, 47, 104, 86, 99, 108, 99, 67, 71, 102, 103, 88, 99, 86, 110, 114, 72, 105, 103, 72, 100, 77, 87, 100, 83, 76, 53, 115, 116, 80, 83, 107, 115, 80, 78, 107, 10, 78, 51, 109, 83, 119, 79, 120, 71, 88, 110, 47, 104, 98, 86, 78, 77, 89, 113, 47, 78, 72, 119, 116, 106, 117, 122, 113, 100, 43, 47, 120, 53, 65, 74, 104, 104, 100, 77, 56, 109, 103, 107, 66, 106, 56, 55, 74, 121, 97, 104, 107, 78, 109, 99, 114, 85, 68, 110, 88, 77, 78, 47, 117, 76, 105, 99, 70, 90, 56, 87, 74, 47, 88, 55, 78, 102, 10, 90, 84, 68, 52, 112, 55, 100, 78, 100, 108, 111, 101, 100, 108, 52, 48, 119, 79, 105, 87, 86, 112, 109, 75, 115, 47, 66, 47, 112, 77, 50, 57, 51, 68, 73, 120, 102, 74, 72, 80, 52, 70, 56, 82, 43, 71, 117, 113, 83, 86, 122, 82, 109, 90, 84, 82, 111, 117, 78, 106, 87, 119, 108, 50, 116, 86, 90, 105, 52, 85, 116, 48, 72, 90, 98, 85, 10, 74, 116, 81, 73, 66, 70, 110, 81, 109, 65, 52, 79, 53, 116, 55, 56, 119, 43, 119, 102, 107, 80, 69, 67, 65, 119, 69, 65, 65, 97, 78, 67, 77, 69, 65, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 10, 65, 81, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 72, 119, 77, 77, 104, 43, 110, 50, 84, 66, 47, 120, 72, 49, 111, 111, 50, 75, 111, 111, 99, 54, 114, 66, 49, 115, 110, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 66, 65, 81, 65, 82, 87, 102, 111, 108, 10, 84, 119, 78, 118, 108, 74, 107, 55, 109, 104, 43, 67, 104, 84, 110, 85, 100, 103, 87, 85, 88, 117, 69, 111, 107, 50, 49, 105, 88, 81, 110, 67, 111, 75, 106, 85, 115, 72, 85, 52, 56, 84, 82, 113, 110, 101, 83, 102, 105, 111, 89, 109, 85, 101, 89, 115, 48, 99, 89, 116, 98, 112, 85, 103, 83, 112, 73, 66, 55, 76, 105, 75, 90, 51, 115, 120, 10, 52, 109, 99, 117, 106, 74, 85, 68, 74, 105, 53, 68, 110, 85, 111, 120, 57, 103, 54, 49, 68, 76, 117, 51, 52, 106, 100, 47, 73, 114, 111, 65, 111, 119, 53, 55, 85, 118, 116, 114, 117, 122, 118, 69, 48, 51, 108, 82, 84, 115, 50, 81, 57, 71, 99, 72, 71, 99, 103, 56, 82, 110, 111, 78, 65, 88, 51, 70, 87, 79, 100, 116, 53, 111, 85, 119, 10, 70, 53, 111, 107, 120, 66, 68, 103, 66, 80, 102, 103, 56, 110, 47, 85, 113, 103, 114, 47, 81, 104, 48, 51, 55, 90, 84, 108, 90, 70, 107, 83, 73, 72, 99, 52, 48, 122, 73, 43, 79, 73, 70, 49, 108, 110, 80, 54, 97, 73, 43, 120, 121, 56, 52, 102, 120, 101, 122, 54, 110, 72, 55, 80, 102, 114, 72, 120, 66, 121, 50, 50, 47, 76, 47, 75, 10, 112, 76, 47, 81, 108, 119, 86, 75, 118, 79, 111, 89, 75, 65, 75, 81, 118, 86, 82, 52, 67, 83, 70, 120, 48, 57, 70, 57, 72, 100, 107, 87, 115, 75, 108, 104, 80, 100, 65, 75, 65, 67, 76, 56, 120, 51, 118, 76, 67, 87, 82, 70, 67, 122, 116, 65, 103, 102, 100, 57, 102, 68, 76, 49, 109, 77, 112, 89, 106, 110, 48, 113, 55, 112, 66, 90, 10, 99, 50, 84, 53, 78, 110, 82, 101, 74, 97, 72, 49, 90, 103, 85, 117, 102, 122, 107, 86, 113, 83, 114, 55, 85, 73, 117, 79, 104, 87, 110, 48, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 116, 97, 114, 102, 105, 101, 108, 100, 32, 83, 101, 114, 118, 105, 99, 101, 115, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 45, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 55, 122, 67, 67, 65, 116, 101, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 66, 109, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 69, 68, 65, 79, 66, 103, 78, 86, 66, 65, 103, 84, 10, 66, 48, 70, 121, 97, 88, 112, 118, 98, 109, 69, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 99, 84, 67, 108, 78, 106, 98, 51, 82, 48, 99, 50, 82, 104, 98, 71, 85, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 111, 84, 72, 70, 78, 48, 89, 88, 74, 109, 97, 87, 86, 115, 90, 67, 66, 85, 90, 87, 78, 111, 98, 109, 57, 115, 10, 98, 50, 100, 112, 90, 88, 77, 115, 73, 69, 108, 117, 89, 121, 52, 120, 79, 122, 65, 53, 66, 103, 78, 86, 66, 65, 77, 84, 77, 108, 78, 48, 89, 88, 74, 109, 97, 87, 86, 115, 90, 67, 66, 84, 90, 88, 74, 50, 97, 87, 78, 108, 99, 121, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 10, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 83, 65, 116, 73, 69, 99, 121, 77, 66, 52, 88, 68, 84, 65, 53, 77, 68, 107, 119, 77, 84, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 77, 51, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 103, 90, 103, 120, 67, 122, 65, 74, 66, 103, 78, 86, 10, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 65, 119, 68, 103, 89, 68, 86, 81, 81, 73, 69, 119, 100, 66, 99, 109, 108, 54, 98, 50, 53, 104, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 72, 69, 119, 112, 84, 89, 50, 57, 48, 100, 72, 78, 107, 89, 87, 120, 108, 77, 83, 85, 119, 73, 119, 89, 68, 86, 81, 81, 75, 69, 120, 120, 84, 10, 100, 71, 70, 121, 90, 109, 108, 108, 98, 71, 81, 103, 86, 71, 86, 106, 97, 71, 53, 118, 98, 71, 57, 110, 97, 87, 86, 122, 76, 67, 66, 74, 98, 109, 77, 117, 77, 84, 115, 119, 79, 81, 89, 68, 86, 81, 81, 68, 69, 122, 74, 84, 100, 71, 70, 121, 90, 109, 108, 108, 98, 71, 81, 103, 85, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 103, 10, 85, 109, 57, 118, 100, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 83, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 103, 76, 83, 66, 72, 77, 106, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 10, 65, 81, 111, 67, 103, 103, 69, 66, 65, 78, 85, 77, 79, 115, 81, 113, 43, 85, 55, 105, 57, 98, 52, 90, 108, 49, 43, 79, 105, 70, 79, 120, 72, 122, 47, 76, 122, 53, 56, 103, 69, 50, 48, 112, 79, 115, 103, 80, 102, 84, 122, 51, 97, 51, 89, 52, 89, 57, 107, 50, 89, 75, 105, 98, 88, 108, 119, 65, 103, 76, 73, 118, 87, 88, 47, 50, 10, 104, 47, 107, 108, 81, 52, 98, 110, 97, 82, 116, 83, 109, 112, 68, 104, 99, 101, 80, 89, 76, 81, 49, 79, 98, 47, 98, 73, 83, 100, 109, 50, 56, 120, 112, 87, 114, 105, 117, 50, 100, 66, 84, 114, 122, 47, 115, 109, 52, 120, 113, 54, 72, 90, 89, 117, 97, 106, 116, 89, 108, 73, 108, 72, 86, 118, 56, 108, 111, 74, 78, 119, 85, 52, 80, 97, 10, 104, 72, 81, 85, 119, 50, 101, 101, 66, 71, 103, 54, 51, 52, 53, 65, 87, 104, 49, 75, 84, 115, 57, 68, 107, 84, 118, 110, 86, 116, 89, 65, 99, 77, 116, 83, 55, 110, 116, 57, 114, 106, 114, 110, 118, 68, 72, 53, 82, 102, 98, 67, 89, 77, 56, 84, 87, 81, 73, 114, 103, 77, 119, 48, 82, 57, 43, 53, 51, 112, 66, 108, 98, 81, 76, 80, 10, 76, 74, 71, 109, 112, 117, 102, 101, 104, 82, 104, 74, 102, 71, 90, 79, 111, 122, 112, 116, 113, 98, 88, 117, 78, 67, 54, 54, 68, 81, 79, 52, 77, 57, 57, 72, 54, 55, 70, 114, 106, 83, 88, 90, 109, 56, 54, 66, 48, 85, 86, 71, 77, 112, 90, 119, 104, 57, 52, 67, 68, 107, 108, 68, 104, 98, 90, 115, 99, 55, 116, 107, 54, 109, 70, 66, 10, 114, 77, 110, 85, 86, 78, 43, 72, 76, 56, 99, 105, 115, 105, 98, 77, 110, 49, 108, 85, 97, 74, 47, 56, 118, 105, 111, 118, 120, 70, 85, 99, 100, 85, 66, 103, 70, 52, 85, 67, 86, 84, 109, 76, 102, 119, 85, 67, 65, 119, 69, 65, 65, 97, 78, 67, 77, 69, 65, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 10, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 74, 120, 102, 65, 78, 43, 113, 65, 100, 99, 119, 75, 122, 105, 73, 111, 114, 104, 116, 83, 112, 122, 121, 69, 90, 71, 68, 77, 65, 48, 71, 67, 83, 113, 71, 10, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 66, 65, 81, 66, 76, 78, 113, 97, 69, 100, 50, 110, 100, 79, 120, 109, 102, 90, 121, 77, 73, 98, 119, 53, 104, 121, 102, 50, 69, 51, 70, 47, 89, 78, 111, 72, 78, 50, 66, 116, 66, 76, 90, 57, 103, 51, 99, 99, 97, 97, 78, 110, 82, 98, 111, 98, 104, 105, 67, 80, 80, 10, 69, 57, 53, 68, 122, 43, 73, 48, 115, 119, 83, 100, 72, 121, 110, 86, 118, 47, 104, 101, 121, 78, 88, 66, 118, 101, 54, 83, 98, 122, 74, 48, 56, 112, 71, 67, 76, 55, 50, 67, 81, 110, 113, 116, 75, 114, 99, 103, 102, 85, 50, 56, 101, 108, 85, 83, 119, 104, 88, 113, 118, 102, 100, 113, 108, 83, 53, 115, 100, 74, 47, 80, 72, 76, 84, 121, 10, 120, 81, 71, 106, 104, 100, 66, 121, 80, 113, 49, 122, 113, 119, 117, 98, 100, 81, 120, 116, 82, 98, 101, 79, 108, 75, 121, 87, 78, 55, 87, 103, 48, 73, 56, 86, 82, 119, 55, 106, 54, 73, 80, 100, 106, 47, 51, 118, 81, 81, 70, 51, 122, 67, 101, 112, 89, 111, 85, 122, 56, 106, 99, 73, 55, 51, 72, 80, 100, 119, 98, 101, 121, 66, 107, 100, 10, 105, 69, 68, 80, 102, 85, 89, 100, 47, 120, 55, 72, 52, 99, 55, 47, 73, 57, 118, 71, 43, 111, 49, 86, 84, 113, 107, 67, 53, 48, 99, 82, 82, 106, 55, 48, 47, 98, 49, 55, 75, 83, 97, 55, 113, 87, 70, 105, 78, 121, 105, 50, 76, 83, 114, 50, 69, 73, 90, 107, 121, 88, 67, 110, 48, 113, 50, 51, 75, 88, 66, 53, 54, 106, 122, 97, 10, 89, 121, 87, 102, 47, 87, 105, 51, 77, 79, 120, 119, 43, 51, 87, 75, 116, 50, 49, 103, 90, 55, 73, 101, 121, 76, 110, 112, 50, 75, 104, 118, 65, 111, 116, 110, 68, 85, 48, 109, 86, 51, 72, 97, 73, 80, 122, 66, 83, 108, 67, 78, 115, 83, 105, 54, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 102, 102, 105, 114, 109, 84, 114, 117, 115, 116, 32, 67, 111, 109, 109, 101, 114, 99, 105, 97, 108, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 84, 68, 67, 67, 65, 106, 83, 103, 65, 119, 73, 66, 65, 103, 73, 73, 100, 51, 99, 71, 74, 121, 97, 112, 115, 88, 119, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 82, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 68, 65, 83, 10, 66, 103, 78, 86, 66, 65, 111, 77, 67, 48, 70, 109, 90, 109, 108, 121, 98, 86, 82, 121, 100, 88, 78, 48, 77, 82, 56, 119, 72, 81, 89, 68, 86, 81, 81, 68, 68, 66, 90, 66, 90, 109, 90, 112, 99, 109, 49, 85, 99, 110, 86, 122, 100, 67, 66, 68, 98, 50, 49, 116, 90, 88, 74, 106, 97, 87, 70, 115, 77, 66, 52, 88, 68, 84, 69, 119, 10, 77, 68, 69, 121, 79, 84, 69, 48, 77, 68, 89, 119, 78, 108, 111, 88, 68, 84, 77, 119, 77, 84, 73, 122, 77, 84, 69, 48, 77, 68, 89, 119, 78, 108, 111, 119, 82, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 111, 77, 67, 48, 70, 109, 90, 109, 108, 121, 10, 98, 86, 82, 121, 100, 88, 78, 48, 77, 82, 56, 119, 72, 81, 89, 68, 86, 81, 81, 68, 68, 66, 90, 66, 90, 109, 90, 112, 99, 109, 49, 85, 99, 110, 86, 122, 100, 67, 66, 68, 98, 50, 49, 116, 90, 88, 74, 106, 97, 87, 70, 115, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 10, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 57, 104, 116, 80, 90, 119, 99, 114, 111, 82, 88, 49, 66, 105, 76, 76, 72, 119, 71, 121, 52, 51, 78, 70, 66, 107, 82, 74, 76, 76, 116, 74, 74, 82, 84, 87, 122, 115, 79, 51, 113, 121, 120, 80, 120, 107, 69, 121, 108, 70, 102, 54, 69, 113, 100, 98, 10, 68, 117, 75, 80, 72, 120, 54, 71, 71, 97, 101, 113, 116, 83, 50, 53, 88, 119, 50, 75, 119, 113, 43, 70, 78, 88, 107, 121, 76, 98, 115, 99, 89, 106, 102, 121, 115, 86, 116, 75, 80, 99, 114, 78, 99, 86, 47, 112, 81, 114, 54, 85, 54, 77, 106, 101, 43, 83, 74, 73, 90, 77, 98, 108, 113, 56, 89, 114, 98, 97, 48, 70, 56, 80, 114, 86, 10, 67, 56, 43, 97, 53, 102, 66, 81, 112, 73, 115, 55, 82, 54, 85, 106, 87, 51, 112, 54, 43, 68, 77, 47, 117, 79, 43, 90, 108, 43, 77, 103, 119, 100, 89, 111, 105, 99, 43, 85, 43, 55, 108, 70, 55, 101, 78, 65, 70, 120, 72, 85, 100, 80, 65, 76, 77, 101, 73, 114, 74, 109, 113, 98, 84, 70, 101, 117, 114, 67, 65, 43, 117, 107, 86, 54, 10, 66, 102, 79, 57, 109, 50, 107, 86, 114, 110, 49, 79, 73, 71, 80, 69, 78, 88, 89, 54, 66, 119, 76, 74, 78, 47, 51, 72, 82, 43, 55, 111, 56, 88, 89, 100, 99, 120, 88, 121, 108, 54, 83, 49, 121, 72, 112, 53, 50, 85, 75, 113, 75, 51, 57, 99, 47, 115, 52, 109, 84, 54, 78, 109, 103, 84, 87, 118, 82, 76, 112, 85, 72, 104, 119, 119, 10, 77, 109, 87, 100, 53, 106, 121, 84, 88, 108, 66, 79, 101, 117, 77, 54, 49, 71, 55, 77, 71, 118, 118, 53, 48, 106, 101, 117, 74, 67, 113, 114, 86, 119, 77, 105, 75, 65, 49, 74, 100, 88, 43, 51, 75, 78, 112, 49, 118, 52, 55, 106, 51, 65, 53, 53, 77, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 100, 66, 103, 78, 86, 10, 72, 81, 52, 69, 70, 103, 81, 85, 110, 90, 80, 71, 85, 52, 116, 101, 121, 113, 56, 47, 110, 120, 52, 80, 53, 90, 109, 86, 118, 67, 84, 50, 108, 73, 56, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 10, 65, 81, 89, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 69, 66, 65, 70, 105, 115, 57, 65, 81, 79, 122, 99, 65, 78, 47, 119, 114, 57, 49, 76, 111, 87, 88, 121, 109, 57, 101, 50, 105, 90, 87, 69, 110, 83, 116, 66, 48, 51, 84, 88, 56, 110, 102, 85, 89, 71, 88, 85, 80, 71, 10, 104, 105, 52, 43, 99, 55, 73, 109, 102, 85, 43, 84, 113, 98, 98, 69, 75, 112, 113, 114, 73, 90, 99, 85, 115, 100, 54, 77, 48, 54, 117, 74, 70, 100, 104, 114, 74, 78, 84, 120, 70, 113, 55, 89, 112, 70, 122, 85, 102, 49, 71, 79, 55, 82, 103, 66, 115, 90, 78, 106, 118, 98, 122, 52, 89, 89, 67, 97, 110, 114, 72, 79, 81, 110, 68, 105, 10, 113, 88, 48, 71, 74, 88, 48, 110, 111, 102, 53, 118, 55, 76, 77, 101, 74, 78, 114, 106, 83, 49, 85, 97, 65, 68, 115, 49, 116, 68, 118, 90, 49, 49, 48, 119, 47, 89, 69, 84, 105, 102, 76, 67, 66, 105, 118, 116, 90, 56, 83, 79, 121, 85, 79, 121, 88, 71, 115, 86, 105, 81, 75, 56, 89, 118, 120, 79, 56, 114, 85, 122, 113, 114, 74, 118, 10, 48, 119, 113, 105, 85, 79, 80, 50, 79, 43, 103, 117, 82, 77, 76, 98, 90, 106, 105, 112, 77, 49, 90, 73, 56, 87, 48, 98, 77, 52, 48, 78, 106, 68, 57, 103, 78, 53, 51, 84, 121, 109, 49, 43, 78, 72, 52, 78, 110, 51, 74, 50, 105, 120, 117, 102, 99, 118, 49, 83, 78, 85, 70, 70, 65, 112, 89, 118, 72, 76, 75, 97, 99, 48, 107, 104, 10, 115, 85, 108, 72, 82, 85, 101, 48, 55, 50, 111, 48, 69, 99, 108, 78, 109, 115, 120, 90, 116, 57, 89, 67, 110, 108, 112, 79, 90, 98, 87, 85, 114, 104, 118, 102, 75, 98, 65, 87, 56, 98, 56, 65, 110, 103, 99, 54, 70, 50, 83, 49, 66, 76, 85, 106, 73, 90, 107, 75, 108, 84, 117, 88, 102, 79, 56, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 102, 102, 105, 114, 109, 84, 114, 117, 115, 116, 32, 78, 101, 116, 119, 111, 114, 107, 105, 110, 103, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 84, 68, 67, 67, 65, 106, 83, 103, 65, 119, 73, 66, 65, 103, 73, 73, 102, 69, 56, 69, 79, 82, 122, 85, 109, 83, 48, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 82, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 68, 65, 83, 10, 66, 103, 78, 86, 66, 65, 111, 77, 67, 48, 70, 109, 90, 109, 108, 121, 98, 86, 82, 121, 100, 88, 78, 48, 77, 82, 56, 119, 72, 81, 89, 68, 86, 81, 81, 68, 68, 66, 90, 66, 90, 109, 90, 112, 99, 109, 49, 85, 99, 110, 86, 122, 100, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 97, 87, 53, 110, 77, 66, 52, 88, 68, 84, 69, 119, 10, 77, 68, 69, 121, 79, 84, 69, 48, 77, 68, 103, 121, 78, 70, 111, 88, 68, 84, 77, 119, 77, 84, 73, 122, 77, 84, 69, 48, 77, 68, 103, 121, 78, 70, 111, 119, 82, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 111, 77, 67, 48, 70, 109, 90, 109, 108, 121, 10, 98, 86, 82, 121, 100, 88, 78, 48, 77, 82, 56, 119, 72, 81, 89, 68, 86, 81, 81, 68, 68, 66, 90, 66, 90, 109, 90, 112, 99, 109, 49, 85, 99, 110, 86, 122, 100, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 97, 87, 53, 110, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 10, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 116, 73, 84, 77, 77, 120, 99, 117, 97, 53, 82, 115, 97, 50, 70, 83, 111, 79, 117, 106, 122, 51, 109, 85, 84, 79, 87, 85, 103, 74, 110, 76, 86, 87, 82, 69, 90, 89, 57, 110, 90, 79, 73, 71, 52, 49, 119, 51, 83, 102, 89, 118, 109, 52, 83, 69, 10, 72, 105, 51, 121, 89, 74, 48, 119, 84, 115, 121, 69, 104, 101, 73, 115, 122, 120, 54, 101, 47, 106, 97, 114, 77, 51, 99, 49, 82, 78, 103, 49, 108, 104, 111, 57, 78, 117, 104, 54, 68, 116, 106, 86, 82, 54, 70, 113, 97, 89, 118, 90, 47, 76, 115, 54, 114, 110, 108, 97, 49, 102, 84, 87, 99, 98, 117, 97, 107, 67, 78, 114, 109, 114, 101, 73, 10, 100, 73, 99, 77, 72, 108, 43, 53, 110, 105, 51, 54, 113, 49, 77, 114, 51, 76, 116, 50, 80, 112, 78, 77, 67, 65, 105, 77, 72, 113, 73, 106, 72, 78, 82, 113, 114, 83, 75, 54, 109, 81, 69, 117, 98, 87, 88, 76, 118, 105, 82, 109, 86, 83, 82, 76, 81, 69, 83, 120, 71, 57, 102, 104, 119, 111, 88, 65, 51, 104, 65, 47, 80, 101, 50, 52, 10, 47, 80, 72, 120, 73, 49, 80, 99, 118, 50, 87, 88, 98, 57, 110, 53, 81, 72, 71, 78, 102, 98, 50, 86, 49, 77, 54, 43, 111, 70, 52, 110, 73, 57, 55, 57, 112, 116, 65, 109, 68, 103, 65, 112, 54, 122, 120, 71, 56, 68, 49, 103, 118, 122, 57, 81, 48, 116, 119, 109, 81, 86, 71, 101, 70, 68, 100, 67, 66, 75, 78, 119, 86, 54, 103, 98, 10, 104, 43, 48, 116, 43, 110, 118, 117, 106, 65, 114, 106, 113, 87, 97, 74, 71, 99, 116, 66, 43, 100, 49, 69, 78, 109, 72, 80, 52, 110, 100, 71, 121, 72, 51, 50, 57, 74, 75, 66, 78, 118, 51, 98, 78, 80, 70, 121, 102, 118, 77, 77, 70, 114, 50, 48, 70, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 100, 66, 103, 78, 86, 10, 72, 81, 52, 69, 70, 103, 81, 85, 66, 120, 47, 83, 53, 53, 122, 97, 119, 109, 54, 105, 81, 76, 83, 119, 101, 108, 65, 81, 85, 72, 84, 69, 121, 76, 48, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 10, 65, 81, 89, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 73, 108, 88, 115, 104, 90, 54, 113, 77, 76, 57, 49, 116, 109, 98, 109, 122, 84, 67, 110, 76, 81, 121, 70, 69, 50, 110, 112, 78, 47, 115, 118, 113, 101, 43, 43, 69, 80, 98, 107, 84, 102, 79, 116, 68, 73, 117, 10, 85, 70, 85, 97, 78, 85, 53, 50, 81, 51, 69, 103, 55, 53, 78, 51, 84, 104, 86, 119, 76, 111, 102, 68, 119, 82, 49, 116, 51, 77, 117, 49, 74, 57, 81, 115, 86, 116, 70, 83, 85, 122, 112, 69, 48, 110, 80, 73, 120, 66, 115, 70, 90, 86, 112, 105, 107, 112, 122, 117, 81, 89, 48, 120, 50, 43, 99, 48, 54, 108, 107, 104, 49, 81, 70, 54, 10, 49, 50, 83, 52, 90, 68, 110, 78, 121, 101, 50, 118, 55, 85, 115, 68, 83, 75, 101, 103, 109, 81, 71, 65, 51, 71, 87, 106, 78, 113, 53, 108, 87, 85, 104, 80, 103, 107, 118, 73, 90, 102, 70, 88, 72, 101, 86, 90, 76, 103, 111, 47, 98, 78, 106, 82, 57, 101, 85, 74, 116, 71, 120, 85, 65, 65, 114, 103, 70, 85, 50, 72, 100, 87, 50, 51, 10, 87, 74, 90, 97, 51, 87, 51, 83, 65, 75, 68, 48, 109, 48, 105, 43, 119, 122, 101, 107, 117, 106, 98, 103, 102, 73, 101, 70, 108, 120, 111, 86, 111, 116, 52, 117, 111, 108, 117, 57, 114, 120, 106, 53, 107, 70, 68, 78, 99, 70, 110, 52, 74, 50, 100, 72, 121, 56, 101, 103, 66, 122, 112, 57, 48, 83, 120, 100, 98, 66, 107, 54, 90, 114, 86, 57, 10, 47, 90, 70, 118, 103, 114, 71, 43, 67, 74, 80, 98, 70, 69, 102, 120, 111, 106, 102, 72, 82, 90, 52, 56, 120, 51, 101, 118, 90, 75, 105, 84, 51, 47, 90, 112, 103, 52, 74, 103, 56, 107, 108, 67, 78, 79, 49, 97, 65, 70, 83, 70, 72, 66, 89, 50, 107, 103, 120, 99, 43, 113, 97, 116, 118, 57, 115, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 102, 102, 105, 114, 109, 84, 114, 117, 115, 116, 32, 80, 114, 101, 109, 105, 117, 109, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 82, 106, 67, 67, 65, 121, 54, 103, 65, 119, 73, 66, 65, 103, 73, 73, 98, 89, 119, 85, 82, 114, 71, 109, 67, 117, 52, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 77, 66, 81, 65, 119, 81, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 68, 65, 83, 10, 66, 103, 78, 86, 66, 65, 111, 77, 67, 48, 70, 109, 90, 109, 108, 121, 98, 86, 82, 121, 100, 88, 78, 48, 77, 82, 119, 119, 71, 103, 89, 68, 86, 81, 81, 68, 68, 66, 78, 66, 90, 109, 90, 112, 99, 109, 49, 85, 99, 110, 86, 122, 100, 67, 66, 81, 99, 109, 86, 116, 97, 88, 86, 116, 77, 66, 52, 88, 68, 84, 69, 119, 77, 68, 69, 121, 10, 79, 84, 69, 48, 77, 84, 65, 122, 78, 108, 111, 88, 68, 84, 81, 119, 77, 84, 73, 122, 77, 84, 69, 48, 77, 84, 65, 122, 78, 108, 111, 119, 81, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 111, 77, 67, 48, 70, 109, 90, 109, 108, 121, 98, 86, 82, 121, 10, 100, 88, 78, 48, 77, 82, 119, 119, 71, 103, 89, 68, 86, 81, 81, 68, 68, 66, 78, 66, 90, 109, 90, 112, 99, 109, 49, 85, 99, 110, 86, 122, 100, 67, 66, 81, 99, 109, 86, 116, 97, 88, 86, 116, 77, 73, 73, 67, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 103, 56, 65, 10, 77, 73, 73, 67, 67, 103, 75, 67, 65, 103, 69, 65, 120, 66, 76, 102, 113, 86, 47, 43, 81, 100, 51, 100, 57, 90, 43, 75, 52, 47, 97, 115, 52, 84, 120, 52, 109, 114, 122, 89, 56, 72, 57, 54, 111, 68, 77, 113, 51, 73, 48, 103, 87, 54, 52, 116, 98, 43, 101, 84, 50, 84, 90, 119, 97, 109, 106, 80, 106, 108, 71, 106, 104, 86, 116, 110, 10, 66, 75, 65, 81, 74, 71, 57, 100, 75, 73, 76, 66, 108, 49, 102, 89, 83, 67, 107, 84, 116, 117, 71, 43, 107, 85, 51, 102, 104, 81, 120, 84, 71, 74, 111, 101, 74, 75, 74, 80, 106, 47, 67, 105, 104, 81, 118, 76, 57, 67, 108, 47, 48, 113, 82, 89, 55, 105, 90, 78, 121, 97, 113, 111, 101, 53, 114, 90, 43, 106, 106, 101, 82, 70, 99, 86, 10, 53, 102, 105, 77, 121, 78, 108, 73, 52, 103, 48, 87, 74, 120, 48, 101, 121, 73, 79, 70, 74, 98, 101, 54, 113, 108, 86, 66, 122, 65, 77, 105, 83, 121, 50, 82, 106, 89, 118, 109, 105, 97, 57, 109, 120, 43, 110, 47, 75, 43, 107, 56, 114, 78, 114, 83, 115, 56, 80, 104, 97, 74, 121, 74, 43, 72, 111, 65, 86, 116, 55, 48, 86, 90, 86, 115, 10, 43, 55, 112, 107, 51, 87, 75, 76, 51, 119, 116, 51, 77, 117, 116, 105, 122, 67, 97, 97, 109, 55, 117, 113, 89, 111, 78, 77, 116, 65, 90, 54, 77, 77, 103, 112, 118, 43, 48, 71, 84, 90, 101, 53, 72, 77, 81, 120, 75, 57, 86, 102, 118, 70, 77, 83, 70, 53, 121, 90, 86, 121, 108, 109, 100, 50, 69, 104, 77, 81, 99, 117, 74, 85, 109, 100, 10, 71, 80, 76, 117, 56, 121, 116, 120, 106, 76, 87, 54, 79, 81, 100, 74, 100, 47, 122, 118, 76, 112, 75, 81, 66, 89, 48, 116, 76, 51, 100, 55, 55, 48, 79, 47, 78, 98, 117, 97, 50, 80, 108, 122, 112, 121, 122, 121, 48, 70, 102, 117, 75, 69, 52, 109, 88, 52, 43, 81, 97, 65, 107, 118, 117, 80, 106, 99, 66, 117, 107, 117, 109, 106, 53, 82, 10, 112, 57, 69, 105, 120, 65, 113, 110, 79, 69, 104, 115, 115, 47, 110, 47, 102, 97, 117, 71, 86, 43, 79, 54, 49, 111, 86, 52, 100, 55, 112, 68, 54, 107, 104, 47, 57, 116, 105, 43, 73, 50, 48, 101, 118, 57, 69, 50, 98, 70, 104, 99, 56, 101, 54, 107, 71, 86, 81, 97, 57, 81, 80, 83, 100, 117, 98, 104, 106, 76, 48, 56, 115, 57, 78, 73, 10, 83, 43, 76, 73, 43, 72, 43, 83, 113, 72, 90, 71, 110, 69, 74, 108, 80, 113, 81, 101, 119, 81, 99, 68, 87, 107, 89, 116, 117, 74, 102, 122, 116, 57, 87, 121, 86, 83, 72, 118, 117, 116, 120, 77, 65, 74, 102, 55, 70, 74, 85, 110, 77, 55, 47, 111, 81, 48, 100, 71, 48, 103, 105, 90, 70, 109, 65, 55, 109, 110, 55, 83, 53, 117, 48, 52, 10, 54, 117, 119, 66, 72, 106, 120, 73, 86, 107, 107, 74, 120, 48, 119, 51, 65, 74, 54, 73, 68, 115, 66, 122, 52, 87, 57, 109, 54, 88, 74, 72, 77, 68, 52, 81, 53, 81, 115, 68, 121, 90, 112, 67, 65, 71, 122, 70, 108, 72, 53, 104, 120, 73, 114, 102, 102, 52, 73, 97, 67, 49, 110, 69, 87, 84, 74, 51, 115, 55, 120, 103, 97, 86, 89, 53, 10, 47, 98, 81, 71, 101, 121, 122, 87, 90, 68, 98, 90, 118, 85, 106, 116, 104, 66, 57, 43, 112, 83, 75, 80, 75, 114, 104, 67, 57, 73, 75, 51, 49, 70, 79, 81, 101, 69, 52, 116, 71, 118, 50, 66, 98, 48, 84, 88, 79, 119, 70, 48, 108, 107, 76, 103, 65, 79, 73, 117, 97, 43, 114, 70, 55, 110, 75, 115, 117, 55, 47, 43, 54, 113, 113, 111, 10, 43, 78, 122, 50, 115, 110, 109, 75, 116, 109, 99, 67, 65, 119, 69, 65, 65, 97, 78, 67, 77, 69, 65, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 74, 51, 65, 90, 54, 89, 77, 73, 116, 107, 109, 57, 85, 87, 114, 112, 109, 86, 83, 69, 83, 102, 89, 82, 97, 120, 106, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 10, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 68, 65, 85, 65, 65, 52, 73, 67, 65, 81, 67, 122, 86, 48, 48, 81, 89, 107, 52, 54, 53, 75, 122, 113, 117, 66, 121, 118, 10, 77, 105, 80, 73, 115, 48, 108, 97, 85, 90, 120, 50, 75, 73, 49, 53, 113, 108, 100, 71, 70, 57, 88, 49, 85, 118, 97, 51, 82, 79, 103, 73, 82, 76, 56, 89, 104, 78, 73, 76, 103, 77, 51, 70, 69, 118, 48, 65, 86, 81, 86, 104, 104, 48, 72, 99, 116, 83, 83, 101, 80, 77, 84, 89, 121, 80, 116, 119, 110, 105, 57, 52, 108, 111, 77, 103, 10, 78, 116, 53, 56, 68, 50, 107, 84, 105, 75, 86, 49, 78, 112, 103, 73, 112, 115, 98, 102, 114, 77, 55, 106, 87, 78, 97, 51, 80, 116, 54, 54, 56, 43, 115, 48, 81, 78, 105, 105, 103, 102, 86, 52, 80, 121, 47, 86, 112, 102, 122, 90, 111, 116, 82, 101, 66, 65, 52, 88, 114, 102, 53, 66, 56, 79, 87, 121, 99, 118, 112, 69, 103, 106, 78, 67, 10, 54, 67, 49, 89, 57, 49, 97, 77, 89, 106, 43, 54, 81, 114, 67, 99, 68, 70, 120, 43, 76, 109, 85, 109, 88, 70, 78, 80, 65, 76, 74, 52, 102, 113, 69, 78, 109, 83, 50, 78, 117, 66, 50, 79, 111, 115, 83, 119, 47, 87, 68, 81, 77, 75, 83, 79, 121, 65, 82, 105, 113, 99, 84, 116, 78, 100, 53, 54, 108, 43, 48, 79, 79, 70, 54, 83, 10, 76, 53, 78, 119, 112, 97, 109, 99, 98, 54, 100, 57, 69, 120, 49, 43, 120, 103, 104, 73, 115, 86, 53, 110, 54, 49, 69, 73, 74, 101, 110, 109, 74, 87, 116, 83, 75, 90, 71, 99, 48, 106, 108, 122, 67, 70, 102, 101, 109, 81, 97, 48, 87, 53, 48, 81, 66, 117, 72, 67, 65, 75, 105, 52, 72, 69, 111, 67, 67, 104, 84, 81, 119, 85, 72, 75, 10, 43, 52, 119, 49, 73, 88, 50, 67, 79, 80, 75, 112, 86, 74, 69, 90, 78, 90, 79, 85, 98, 87, 111, 54, 120, 98, 76, 81, 117, 52, 109, 71, 107, 43, 105, 98, 121, 81, 56, 54, 112, 51, 113, 52, 111, 102, 66, 52, 82, 118, 114, 56, 78, 121, 47, 108, 105, 111, 84, 122, 51, 47, 52, 69, 50, 97, 70, 111, 111, 67, 56, 107, 52, 103, 109, 86, 10, 66, 116, 87, 86, 121, 117, 69, 107, 108, 117, 116, 56, 57, 112, 77, 70, 117, 43, 49, 122, 54, 83, 51, 82, 100, 84, 110, 88, 53, 121, 84, 98, 50, 69, 53, 102, 81, 52, 43, 101, 48, 66, 81, 53, 118, 49, 86, 119, 83, 74, 108, 88, 77, 98, 83, 99, 55, 107, 113, 89, 65, 53, 89, 119, 72, 50, 65, 71, 55, 104, 115, 106, 47, 111, 70, 103, 10, 73, 120, 112, 72, 89, 111, 87, 108, 122, 66, 107, 48, 103, 71, 43, 122, 114, 66, 114, 106, 110, 47, 66, 55, 83, 75, 51, 86, 65, 100, 108, 110, 116, 113, 108, 121, 107, 43, 111, 116, 90, 114, 87, 121, 117, 79, 81, 57, 80, 76, 76, 118, 84, 73, 122, 113, 54, 119, 101, 47, 113, 122, 87, 97, 86, 89, 97, 56, 71, 75, 97, 49, 113, 70, 54, 48, 10, 103, 50, 120, 114, 97, 85, 68, 84, 110, 57, 122, 120, 119, 50, 108, 114, 117, 101, 70, 116, 67, 102, 84, 120, 113, 108, 66, 50, 67, 110, 112, 57, 101, 104, 101, 104, 86, 90, 90, 67, 109, 84, 69, 74, 51, 87, 65, 82, 106, 81, 85, 119, 102, 117, 97, 79, 82, 116, 71, 100, 70, 78, 114, 72, 70, 43, 81, 70, 108, 111, 122, 69, 74, 76, 85, 98, 10, 122, 120, 81, 72, 115, 107, 68, 52, 111, 53, 53, 66, 104, 114, 119, 69, 48, 71, 117, 87, 121, 67, 113, 65, 78, 80, 50, 47, 55, 119, 97, 106, 51, 86, 106, 70, 104, 84, 48, 43, 106, 47, 54, 101, 75, 101, 67, 50, 117, 65, 108, 111, 71, 82, 119, 89, 81, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 102, 102, 105, 114, 109, 84, 114, 117, 115, 116, 32, 80, 114, 101, 109, 105, 117, 109, 32, 69, 67, 67, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 66, 47, 106, 67, 67, 65, 89, 87, 103, 65, 119, 73, 66, 65, 103, 73, 73, 100, 74, 99, 108, 105, 115, 99, 47, 101, 108, 81, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 77, 119, 82, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 68, 65, 83, 66, 103, 78, 86, 10, 66, 65, 111, 77, 67, 48, 70, 109, 90, 109, 108, 121, 98, 86, 82, 121, 100, 88, 78, 48, 77, 83, 65, 119, 72, 103, 89, 68, 86, 81, 81, 68, 68, 66, 100, 66, 90, 109, 90, 112, 99, 109, 49, 85, 99, 110, 86, 122, 100, 67, 66, 81, 99, 109, 86, 116, 97, 88, 86, 116, 73, 69, 86, 68, 81, 122, 65, 101, 70, 119, 48, 120, 77, 68, 65, 120, 10, 77, 106, 107, 120, 78, 68, 73, 119, 77, 106, 82, 97, 70, 119, 48, 48, 77, 68, 69, 121, 77, 122, 69, 120, 78, 68, 73, 119, 77, 106, 82, 97, 77, 69, 85, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 75, 68, 65, 116, 66, 90, 109, 90, 112, 99, 109, 49, 85, 10, 99, 110, 86, 122, 100, 68, 69, 103, 77, 66, 52, 71, 65, 49, 85, 69, 65, 119, 119, 88, 81, 87, 90, 109, 97, 88, 74, 116, 86, 72, 74, 49, 99, 51, 81, 103, 85, 72, 74, 108, 98, 87, 108, 49, 98, 83, 66, 70, 81, 48, 77, 119, 100, 106, 65, 81, 66, 103, 99, 113, 104, 107, 106, 79, 80, 81, 73, 66, 66, 103, 85, 114, 103, 81, 81, 65, 10, 73, 103, 78, 105, 65, 65, 81, 78, 77, 70, 52, 98, 70, 90, 48, 68, 48, 75, 70, 53, 78, 98, 99, 54, 80, 74, 74, 54, 121, 104, 85, 99, 122, 87, 76, 122, 110, 67, 90, 99, 66, 122, 51, 108, 86, 80, 113, 106, 49, 115, 119, 83, 54, 118, 81, 85, 88, 43, 105, 79, 71, 97, 115, 118, 76, 107, 106, 109, 114, 66, 104, 68, 101, 75, 122, 81, 10, 78, 56, 79, 57, 115, 115, 48, 115, 53, 107, 102, 105, 71, 117, 90, 106, 117, 68, 48, 117, 76, 51, 106, 69, 84, 57, 118, 48, 68, 54, 82, 111, 84, 70, 86, 121, 97, 53, 85, 100, 84, 104, 104, 67, 108, 88, 106, 77, 78, 122, 121, 82, 52, 112, 116, 108, 75, 121, 109, 106, 81, 106, 66, 65, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 10, 66, 66, 83, 97, 114, 121, 108, 54, 119, 66, 69, 49, 78, 83, 90, 82, 77, 65, 68, 68, 97, 118, 53, 65, 49, 97, 55, 87, 80, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 75, 10, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 119, 78, 110, 65, 68, 66, 107, 65, 106, 65, 88, 67, 102, 79, 72, 105, 70, 66, 97, 114, 56, 106, 65, 81, 114, 57, 72, 88, 47, 86, 115, 97, 111, 98, 103, 120, 67, 100, 48, 53, 68, 104, 84, 49, 119, 86, 47, 71, 122, 84, 106, 120, 105, 43, 122, 121, 103, 107, 56, 78, 53, 51, 88, 10, 53, 55, 104, 71, 56, 102, 50, 104, 52, 110, 69, 67, 77, 69, 74, 90, 104, 48, 80, 85, 85, 100, 43, 54, 48, 119, 107, 121, 87, 115, 54, 73, 102, 108, 99, 57, 110, 70, 57, 67, 97, 47, 85, 72, 76, 98, 88, 119, 103, 112, 80, 53, 87, 87, 43, 117, 90, 80, 112, 89, 53, 89, 115, 101, 52, 50, 79, 43, 116, 89, 72, 78, 98, 119, 75, 77, 10, 101, 81, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 101, 114, 116, 117, 109, 32, 84, 114, 117, 115, 116, 101, 100, 32, 78, 101, 116, 119, 111, 114, 107, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 117, 122, 67, 67, 65, 113, 79, 103, 65, 119, 73, 66, 65, 103, 73, 68, 66, 69, 84, 65, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 77, 72, 52, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 66, 77, 77, 83, 73, 119, 73, 65, 89, 68, 86, 81, 81, 75, 10, 69, 120, 108, 86, 98, 109, 108, 54, 90, 88, 82, 118, 73, 70, 82, 108, 89, 50, 104, 117, 98, 50, 120, 118, 90, 50, 108, 108, 99, 121, 66, 84, 76, 107, 69, 117, 77, 83, 99, 119, 74, 81, 89, 68, 86, 81, 81, 76, 69, 120, 53, 68, 90, 88, 74, 48, 100, 87, 48, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 10, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 120, 73, 106, 65, 103, 66, 103, 78, 86, 66, 65, 77, 84, 71, 85, 78, 108, 99, 110, 82, 49, 98, 83, 66, 85, 99, 110, 86, 122, 100, 71, 86, 107, 73, 69, 53, 108, 100, 72, 100, 118, 99, 109, 115, 103, 81, 48, 69, 119, 72, 104, 99, 78, 77, 68, 103, 120, 77, 68, 73, 121, 10, 77, 84, 73, 119, 78, 122, 77, 51, 87, 104, 99, 78, 77, 106, 107, 120, 77, 106, 77, 120, 77, 84, 73, 119, 78, 122, 77, 51, 87, 106, 66, 43, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 81, 84, 68, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 67, 104, 77, 90, 86, 87, 53, 112, 101, 109, 86, 48, 98, 121, 66, 85, 10, 90, 87, 78, 111, 98, 109, 57, 115, 98, 50, 100, 112, 90, 88, 77, 103, 85, 121, 53, 66, 76, 106, 69, 110, 77, 67, 85, 71, 65, 49, 85, 69, 67, 120, 77, 101, 81, 50, 86, 121, 100, 72, 86, 116, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 10, 77, 83, 73, 119, 73, 65, 89, 68, 86, 81, 81, 68, 69, 120, 108, 68, 90, 88, 74, 48, 100, 87, 48, 103, 86, 72, 74, 49, 99, 51, 82, 108, 90, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 73, 69, 78, 66, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 10, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 52, 47, 116, 57, 111, 51, 75, 54, 119, 118, 68, 74, 70, 73, 102, 49, 97, 119, 70, 79, 52, 87, 53, 65, 66, 55, 112, 116, 74, 49, 49, 47, 57, 49, 115, 116, 115, 49, 114, 72, 85, 86, 43, 114, 112, 68, 75, 109, 89, 89, 101, 50, 98, 103, 43, 71, 48, 106, 65, 67, 10, 108, 47, 106, 88, 97, 86, 101, 104, 71, 68, 108, 100, 97, 109, 82, 53, 120, 103, 70, 90, 114, 68, 119, 120, 83, 106, 104, 56, 48, 103, 84, 83, 83, 121, 106, 111, 73, 70, 56, 55, 66, 54, 76, 77, 84, 88, 80, 98, 56, 54, 53, 80, 120, 49, 98, 86, 87, 113, 101, 87, 105, 102, 114, 122, 113, 50, 106, 85, 73, 52, 90, 90, 74, 56, 56, 74, 10, 74, 55, 121, 115, 98, 110, 75, 68, 72, 68, 66, 121, 51, 43, 67, 105, 54, 100, 76, 104, 100, 72, 85, 90, 118, 83, 113, 101, 101, 120, 86, 85, 66, 66, 118, 88, 81, 122, 109, 116, 86, 83, 106, 70, 52, 104, 113, 55, 57, 77, 68, 107, 114, 106, 104, 74, 77, 56, 120, 50, 104, 90, 56, 53, 82, 100, 75, 107, 110, 118, 73, 83, 106, 70, 72, 52, 10, 102, 79, 81, 116, 102, 47, 87, 115, 88, 43, 115, 87, 110, 55, 69, 116, 48, 98, 114, 77, 107, 85, 74, 51, 84, 67, 88, 74, 107, 68, 104, 118, 50, 47, 68, 77, 43, 52, 52, 101, 108, 49, 107, 43, 49, 87, 66, 79, 53, 103, 85, 111, 55, 85, 108, 53, 69, 48, 117, 54, 83, 78, 115, 118, 43, 88, 76, 84, 79, 99, 114, 43, 72, 57, 103, 48, 10, 99, 118, 87, 48, 81, 77, 56, 120, 65, 99, 80, 115, 51, 104, 69, 116, 70, 49, 48, 102, 117, 70, 68, 82, 88, 104, 109, 110, 97, 100, 52, 72, 77, 121, 106, 75, 85, 74, 88, 53, 112, 49, 84, 76, 86, 73, 90, 81, 82, 97, 110, 53, 83, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 10, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 81, 73, 100, 115, 51, 76, 66, 47, 56, 107, 57, 115, 88, 78, 55, 98, 117, 81, 118, 79, 75, 69, 78, 48, 90, 49, 57, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 10, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 75, 97, 111, 114, 83, 76, 79, 65, 84, 50, 109, 111, 47, 57, 105, 48, 69, 105, 100, 105, 49, 53, 121, 115, 72, 104, 69, 52, 57, 119, 99, 114, 119, 110, 57, 73, 48, 106, 54, 118, 83, 114, 69, 117, 86, 85, 69, 116, 82, 67, 106, 10, 106, 83, 102, 101, 67, 52, 74, 106, 48, 79, 55, 101, 68, 68, 100, 53, 81, 86, 115, 105, 115, 114, 67, 97, 81, 86, 121, 109, 99, 79, 68, 85, 48, 72, 102, 76, 73, 57, 77, 65, 52, 71, 120, 87, 76, 43, 70, 112, 68, 81, 51, 90, 113, 114, 56, 104, 103, 86, 68, 90, 66, 113, 87, 111, 47, 53, 85, 51, 48, 75, 114, 43, 52, 114, 80, 49, 10, 109, 83, 49, 70, 104, 73, 114, 108, 81, 103, 110, 88, 100, 65, 73, 118, 57, 52, 110, 89, 109, 101, 109, 56, 74, 57, 82, 72, 106, 98, 111, 78, 82, 104, 120, 51, 122, 120, 83, 107, 72, 76, 109, 107, 77, 99, 83, 99, 75, 72, 81, 68, 78, 80, 56, 122, 71, 83, 97, 108, 54, 81, 49, 48, 116, 122, 54, 88, 120, 110, 98, 111, 74, 53, 97, 106, 10, 90, 116, 51, 104, 114, 118, 74, 66, 87, 56, 113, 89, 86, 111, 78, 122, 99, 79, 83, 71, 71, 116, 73, 120, 81, 98, 111, 118, 118, 105, 48, 84, 87, 110, 90, 118, 84, 117, 104, 79, 103, 81, 52, 47, 87, 119, 77, 105, 111, 66, 75, 43, 90, 108, 103, 82, 83, 115, 115, 68, 120, 76, 81, 113, 75, 105, 50, 87, 70, 43, 65, 53, 86, 76, 120, 73, 10, 48, 51, 89, 110, 110, 90, 111, 116, 66, 113, 98, 74, 55, 68, 110, 83, 113, 57, 117, 102, 109, 103, 115, 110, 65, 106, 85, 112, 115, 85, 67, 86, 53, 47, 110, 111, 110, 70, 87, 73, 71, 85, 98, 87, 116, 122, 84, 49, 102, 115, 52, 53, 109, 116, 107, 52, 56, 86, 72, 51, 84, 121, 119, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 101, 114, 116, 105, 110, 111, 109, 105, 115, 32, 45, 32, 65, 117, 116, 111, 114, 105, 116, 195, 169, 32, 82, 97, 99, 105, 110, 101, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 110, 68, 67, 67, 65, 52, 83, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 106, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 71, 85, 106, 69, 84, 77, 66, 69, 71, 65, 49, 85, 69, 67, 104, 77, 75, 10, 81, 50, 86, 121, 100, 71, 108, 117, 98, 50, 49, 112, 99, 122, 69, 88, 77, 66, 85, 71, 65, 49, 85, 69, 67, 120, 77, 79, 77, 68, 65, 119, 77, 105, 65, 48, 77, 122, 77, 53, 79, 84, 103, 53, 77, 68, 77, 120, 74, 106, 65, 107, 66, 103, 78, 86, 66, 65, 77, 77, 72, 85, 78, 108, 99, 110, 82, 112, 98, 109, 57, 116, 97, 88, 77, 103, 10, 76, 83, 66, 66, 100, 88, 82, 118, 99, 109, 108, 48, 119, 54, 107, 103, 85, 109, 70, 106, 97, 87, 53, 108, 77, 66, 52, 88, 68, 84, 65, 52, 77, 68, 107, 120, 78, 122, 65, 52, 77, 106, 103, 49, 79, 86, 111, 88, 68, 84, 73, 52, 77, 68, 107, 120, 78, 122, 65, 52, 77, 106, 103, 49, 79, 86, 111, 119, 89, 122, 69, 76, 77, 65, 107, 71, 10, 65, 49, 85, 69, 66, 104, 77, 67, 82, 108, 73, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 111, 84, 67, 107, 78, 108, 99, 110, 82, 112, 98, 109, 57, 116, 97, 88, 77, 120, 70, 122, 65, 86, 66, 103, 78, 86, 66, 65, 115, 84, 68, 106, 65, 119, 77, 68, 73, 103, 78, 68, 77, 122, 79, 84, 107, 52, 79, 84, 65, 122, 77, 83, 89, 119, 10, 74, 65, 89, 68, 86, 81, 81, 68, 68, 66, 49, 68, 90, 88, 74, 48, 97, 87, 53, 118, 98, 87, 108, 122, 73, 67, 48, 103, 81, 88, 86, 48, 98, 51, 74, 112, 100, 77, 79, 112, 73, 70, 74, 104, 89, 50, 108, 117, 90, 84, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 10, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 74, 50, 70, 110, 52, 98, 84, 52, 54, 47, 72, 115, 109, 116, 117, 77, 43, 67, 101, 116, 48, 73, 48, 86, 90, 51, 53, 103, 98, 53, 106, 50, 67, 78, 50, 68, 112, 100, 85, 122, 90, 108, 77, 71, 118, 69, 53, 120, 52, 106, 89, 70, 49, 65, 77, 110, 109, 72, 97, 10, 119, 69, 53, 86, 51, 117, 100, 97, 117, 72, 112, 79, 100, 52, 99, 78, 53, 98, 106, 114, 43, 112, 53, 101, 101, 120, 55, 69, 122, 121, 104, 48, 120, 53, 80, 49, 70, 77, 89, 105, 75, 65, 84, 53, 107, 99, 79, 114, 74, 51, 78, 113, 68, 105, 53, 78, 56, 121, 52, 111, 72, 51, 68, 102, 86, 83, 57, 79, 55, 99, 100, 120, 98, 119, 108, 121, 10, 76, 117, 51, 86, 77, 112, 102, 81, 56, 86, 104, 51, 48, 87, 67, 56, 84, 108, 55, 98, 109, 111, 84, 50, 82, 50, 70, 70, 75, 47, 90, 81, 112, 110, 57, 113, 99, 83, 100, 73, 104, 68, 87, 101, 114, 80, 53, 112, 113, 90, 53, 54, 88, 106, 85, 108, 43, 114, 83, 110, 83, 84, 86, 51, 108, 113, 99, 50, 87, 43, 72, 78, 51, 121, 78, 119, 10, 50, 70, 49, 77, 112, 81, 105, 68, 56, 97, 89, 107, 79, 66, 79, 111, 55, 67, 43, 111, 111, 87, 102, 72, 112, 105, 50, 71, 82, 43, 54, 75, 47, 79, 121, 98, 68, 110, 84, 48, 75, 48, 107, 67, 101, 53, 66, 49, 106, 80, 121, 90, 79, 81, 69, 53, 49, 107, 113, 74, 53, 90, 53, 50, 113, 122, 54, 87, 75, 68, 103, 109, 105, 57, 50, 78, 10, 106, 77, 68, 50, 65, 82, 53, 118, 112, 84, 69, 83, 79, 72, 50, 86, 119, 110, 72, 117, 55, 88, 83, 117, 53, 68, 97, 105, 81, 51, 88, 86, 56, 81, 67, 98, 52, 117, 84, 88, 122, 69, 73, 68, 83, 51, 104, 54, 53, 88, 50, 55, 117, 75, 52, 117, 73, 74, 80, 84, 53, 71, 72, 102, 99, 101, 70, 50, 90, 53, 99, 47, 116, 116, 57, 113, 10, 99, 49, 112, 107, 73, 117, 86, 67, 50, 56, 43, 66, 65, 53, 80, 89, 57, 79, 77, 81, 52, 72, 76, 50, 65, 72, 67, 115, 56, 77, 70, 54, 68, 119, 86, 47, 122, 122, 82, 112, 82, 98, 87, 84, 53, 66, 110, 98, 85, 104, 89, 106, 66, 89, 107, 79, 106, 85, 106, 107, 74, 87, 43, 122, 101, 76, 57, 105, 57, 81, 102, 54, 108, 83, 84, 67, 10, 108, 114, 76, 111, 111, 121, 80, 67, 88, 81, 80, 56, 119, 57, 80, 108, 102, 77, 108, 49, 73, 57, 102, 48, 57, 98, 122, 101, 53, 78, 47, 78, 103, 76, 43, 82, 105, 72, 50, 110, 69, 55, 81, 53, 117, 105, 121, 54, 118, 100, 70, 114, 122, 80, 79, 108, 75, 79, 49, 69, 110, 110, 49, 83, 111, 50, 43, 87, 76, 104, 108, 43, 72, 80, 78, 98, 10, 120, 120, 97, 79, 117, 50, 66, 57, 100, 50, 90, 72, 86, 73, 73, 65, 69, 87, 66, 115, 77, 115, 71, 111, 79, 66, 118, 114, 98, 112, 103, 84, 49, 117, 52, 52, 57, 102, 67, 102, 68, 117, 47, 43, 77, 89, 72, 66, 48, 105, 83, 86, 76, 49, 78, 54, 97, 97, 76, 119, 68, 52, 90, 70, 106, 108, 105, 67, 75, 48, 119, 105, 49, 70, 54, 103, 10, 53, 51, 48, 109, 74, 48, 106, 102, 74, 85, 97, 78, 83, 105, 104, 56, 104, 112, 55, 53, 109, 120, 112, 90, 117, 87, 87, 47, 66, 100, 50, 50, 81, 108, 48, 57, 53, 103, 66, 73, 103, 108, 52, 103, 57, 120, 71, 67, 51, 115, 114, 89, 110, 43, 89, 51, 82, 121, 89, 101, 54, 51, 106, 51, 89, 99, 78, 66, 90, 70, 103, 67, 81, 102, 110, 97, 10, 52, 78, 72, 52, 43, 101, 106, 57, 85, 106, 105, 50, 57, 89, 110, 102, 65, 103, 77, 66, 65, 65, 71, 106, 87, 122, 66, 90, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 48, 71, 10, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 81, 78, 106, 76, 90, 104, 50, 107, 83, 52, 48, 82, 82, 57, 119, 55, 53, 57, 88, 107, 106, 119, 122, 115, 112, 113, 115, 68, 65, 88, 66, 103, 78, 86, 72, 83, 65, 69, 69, 68, 65, 79, 77, 65, 119, 71, 67, 105, 113, 66, 101, 103, 70, 87, 65, 103, 73, 65, 65, 81, 69, 119, 68, 81, 89, 74, 10, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 73, 66, 65, 67, 81, 43, 89, 65, 90, 43, 72, 101, 56, 54, 80, 116, 118, 113, 114, 120, 121, 97, 76, 65, 69, 76, 57, 77, 87, 49, 50, 85, 107, 120, 57, 70, 49, 66, 106, 89, 107, 77, 84, 118, 57, 115, 111, 118, 51, 47, 52, 103, 98, 73, 79, 90, 47, 120, 10, 87, 113, 110, 100, 73, 108, 103, 86, 113, 73, 114, 84, 115, 101, 89, 121, 67, 89, 73, 68, 98, 78, 99, 47, 67, 77, 102, 52, 117, 98, 111, 65, 98, 98, 110, 87, 47, 70, 73, 121, 88, 97, 82, 47, 112, 68, 71, 85, 117, 55, 90, 77, 79, 72, 56, 111, 77, 68, 88, 47, 110, 121, 78, 84, 116, 55, 98, 117, 70, 72, 65, 65, 81, 67, 118, 97, 10, 82, 54, 115, 48, 102, 108, 54, 110, 86, 106, 66, 104, 75, 52, 116, 68, 114, 80, 50, 50, 105, 67, 106, 49, 97, 55, 89, 43, 89, 69, 113, 54, 81, 112, 65, 48, 90, 52, 51, 113, 54, 49, 57, 70, 86, 68, 115, 88, 114, 73, 118, 107, 120, 109, 85, 80, 55, 116, 67, 77, 88, 87, 89, 53, 122, 106, 75, 110, 50, 66, 67, 88, 119, 72, 52, 48, 10, 110, 74, 43, 85, 56, 47, 97, 71, 72, 56, 56, 98, 99, 54, 50, 85, 101, 89, 100, 111, 99, 77, 77, 122, 112, 88, 68, 110, 50, 78, 85, 52, 108, 71, 57, 106, 101, 101, 117, 47, 67, 103, 52, 73, 53, 56, 85, 118, 68, 48, 75, 103, 75, 120, 82, 65, 47, 121, 72, 103, 66, 99, 85, 110, 52, 89, 81, 82, 69, 55, 114, 87, 104, 104, 49, 66, 10, 67, 120, 77, 106, 105, 100, 80, 74, 67, 43, 105, 75, 117, 110, 113, 106, 111, 51, 77, 51, 78, 89, 66, 57, 69, 114, 103, 122, 100, 48, 65, 52, 119, 80, 112, 101, 77, 78, 76, 121, 116, 113, 79, 120, 49, 113, 75, 86, 108, 52, 71, 98, 85, 117, 49, 112, 84, 80, 43, 65, 53, 70, 80, 98, 86, 70, 115, 68, 98, 86, 82, 102, 115, 98, 106, 118, 10, 74, 76, 49, 118, 110, 120, 72, 68, 120, 50, 84, 67, 68, 121, 104, 105, 104, 87, 90, 101, 71, 110, 117, 121, 116, 43, 43, 117, 78, 99, 107, 90, 77, 54, 105, 52, 74, 57, 115, 122, 86, 98, 57, 111, 52, 88, 86, 73, 82, 70, 98, 55, 122, 100, 78, 73, 117, 48, 101, 74, 79, 113, 120, 112, 57, 89, 68, 71, 53, 69, 82, 81, 76, 49, 84, 69, 10, 113, 107, 80, 70, 77, 84, 70, 89, 118, 90, 98, 70, 54, 110, 86, 115, 109, 110, 87, 120, 84, 102, 106, 51, 108, 47, 43, 87, 70, 118, 75, 88, 84, 101, 106, 50, 56, 120, 72, 53, 79, 110, 50, 75, 79, 71, 52, 69, 121, 43, 72, 84, 82, 82, 87, 113, 112, 100, 69, 100, 110, 86, 49, 106, 54, 67, 84, 109, 78, 104, 84, 105, 104, 54, 48, 98, 10, 87, 102, 86, 69, 109, 47, 118, 88, 100, 51, 119, 102, 65, 88, 66, 105, 111, 83, 65, 97, 111, 115, 85, 97, 75, 80, 81, 104, 65, 43, 52, 117, 50, 99, 71, 65, 54, 114, 110, 90, 103, 116, 90, 98, 100, 115, 76, 76, 79, 55, 88, 83, 65, 80, 67, 106, 68, 117, 71, 116, 98, 107, 68, 51, 50, 54, 67, 48, 48, 69, 97, 117, 70, 100, 100, 69, 10, 119, 107, 48, 49, 43, 100, 73, 76, 56, 104, 102, 50, 114, 71, 98, 86, 74, 76, 74, 80, 48, 82, 121, 90, 119, 71, 55, 49, 102, 101, 116, 48, 66, 76, 106, 53, 84, 88, 99, 74, 49, 55, 84, 80, 66, 122, 65, 74, 56, 98, 103, 65, 86, 116, 107, 88, 70, 104, 89, 75, 75, 52, 98, 102, 106, 119, 69, 90, 71, 117, 87, 55, 103, 109, 80, 47, 10, 118, 103, 116, 50, 70, 108, 52, 51, 78, 43, 98, 89, 100, 74, 101, 105, 109, 85, 86, 53, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 84, 87, 67, 65, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 101, 122, 67, 67, 65, 109, 79, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 102, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 85, 86, 122, 69, 83, 77, 66, 65, 71, 65, 49, 85, 69, 67, 103, 119, 74, 10, 86, 69, 70, 74, 86, 48, 70, 79, 76, 85, 78, 66, 77, 82, 65, 119, 68, 103, 89, 68, 86, 81, 81, 76, 68, 65, 100, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 83, 111, 119, 75, 65, 89, 68, 86, 81, 81, 68, 68, 67, 70, 85, 86, 48, 78, 66, 73, 70, 74, 118, 98, 51, 81, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 10, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 72, 104, 99, 78, 77, 68, 103, 119, 79, 68, 73, 52, 77, 68, 99, 121, 78, 68, 77, 122, 87, 104, 99, 78, 77, 122, 65, 120, 77, 106, 77, 120, 77, 84, 85, 49, 79, 84, 85, 53, 87, 106, 66, 102, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 85, 86, 122, 69, 83, 77, 66, 65, 71, 65, 49, 85, 69, 67, 103, 119, 74, 86, 69, 70, 74, 86, 48, 70, 79, 76, 85, 78, 66, 77, 82, 65, 119, 68, 103, 89, 68, 86, 81, 81, 76, 68, 65, 100, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 83, 111, 119, 75, 65, 89, 68, 86, 81, 81, 68, 68, 67, 70, 85, 86, 48, 78, 66, 10, 73, 70, 74, 118, 98, 51, 81, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 10, 65, 111, 73, 66, 65, 81, 67, 119, 102, 110, 75, 52, 112, 65, 79, 85, 53, 113, 102, 101, 67, 84, 105, 82, 83, 104, 70, 65, 104, 54, 100, 56, 87, 87, 81, 85, 101, 55, 85, 82, 69, 78, 51, 43, 118, 57, 88, 65, 117, 49, 98, 105, 104, 83, 88, 48, 78, 88, 73, 80, 43, 70, 80, 81, 81, 101, 70, 69, 65, 99, 75, 48, 72, 77, 77, 120, 10, 81, 104, 90, 72, 104, 84, 77, 105, 100, 114, 73, 75, 98, 119, 47, 108, 74, 86, 66, 80, 104, 89, 97, 43, 118, 53, 103, 117, 69, 71, 99, 101, 118, 104, 69, 70, 104, 103, 87, 81, 120, 70, 110, 81, 102, 72, 103, 81, 115, 73, 66, 99, 116, 43, 72, 72, 75, 51, 88, 76, 102, 74, 43, 117, 116, 100, 71, 100, 73, 122, 100, 106, 112, 57, 120, 67, 10, 111, 105, 50, 83, 66, 66, 116, 81, 119, 88, 117, 52, 80, 104, 118, 74, 86, 103, 83, 76, 76, 49, 75, 98, 114, 97, 108, 87, 54, 99, 72, 47, 114, 97, 108, 89, 104, 122, 67, 50, 103, 102, 101, 88, 82, 102, 119, 90, 86, 122, 115, 114, 98, 43, 82, 72, 57, 74, 108, 70, 47, 104, 51, 120, 43, 74, 101, 106, 105, 66, 48, 51, 72, 70, 121, 80, 10, 52, 72, 89, 108, 109, 108, 68, 52, 111, 70, 84, 47, 82, 74, 66, 50, 73, 57, 73, 121, 120, 115, 79, 114, 66, 114, 47, 56, 43, 55, 47, 122, 114, 88, 50, 83, 89, 103, 74, 98, 75, 100, 77, 49, 111, 53, 79, 97, 81, 50, 82, 103, 88, 98, 76, 54, 77, 118, 56, 55, 66, 75, 57, 78, 81, 71, 114, 53, 120, 43, 80, 118, 73, 47, 49, 114, 10, 121, 43, 85, 80, 105, 122, 103, 78, 55, 103, 114, 56, 47, 103, 43, 89, 110, 122, 65, 120, 51, 87, 120, 83, 90, 102, 109, 76, 103, 98, 52, 105, 52, 82, 120, 89, 65, 55, 113, 82, 71, 52, 107, 72, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 10, 66, 106, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 113, 79, 70, 115, 109, 106, 100, 54, 76, 87, 118, 74, 80, 101, 108, 83, 68, 71, 82, 106, 106, 67, 68, 87, 109, 117, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 10, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 81, 69, 65, 80, 78, 86, 51, 80, 100, 114, 102, 105, 98, 113, 72, 68, 65, 104, 85, 97, 105, 66, 81, 107, 114, 54, 119, 81, 84, 50, 53, 74, 109, 83, 68, 67, 105, 47, 111, 81, 77, 67, 88, 75, 67, 101, 67, 77, 69, 114, 74, 107, 47, 57, 113, 53, 54, 89, 65, 102, 52, 108, 67, 10, 109, 116, 89, 82, 53, 86, 80, 79, 76, 56, 122, 121, 50, 103, 88, 69, 47, 117, 74, 81, 120, 68, 113, 71, 102, 99, 122, 97, 102, 104, 65, 74, 79, 53, 73, 49, 75, 108, 79, 121, 47, 117, 115, 114, 66, 100, 108, 115, 88, 101, 98, 81, 55, 57, 78, 113, 90, 112, 52, 86, 75, 73, 86, 54, 54, 73, 73, 65, 114, 66, 54, 110, 67, 87, 108, 87, 10, 81, 116, 78, 111, 85, 82, 105, 43, 86, 74, 113, 47, 82, 69, 71, 54, 83, 98, 52, 103, 117, 109, 108, 99, 55, 114, 104, 51, 122, 99, 53, 115, 72, 54, 50, 68, 108, 104, 104, 57, 68, 114, 85, 85, 79, 89, 84, 120, 75, 79, 107, 116, 111, 53, 53, 55, 72, 110, 112, 121, 87, 111, 79, 122, 101, 87, 47, 118, 116, 80, 122, 81, 67, 113, 86, 89, 10, 84, 48, 98, 102, 43, 50, 49, 53, 87, 102, 75, 69, 73, 108, 75, 117, 68, 56, 122, 55, 102, 68, 118, 110, 97, 115, 112, 72, 89, 99, 78, 54, 43, 78, 79, 83, 66, 66, 43, 52, 73, 73, 84, 104, 78, 108, 81, 87, 120, 48, 68, 101, 79, 52, 112, 122, 51, 78, 47, 71, 67, 85, 122, 102, 55, 78, 114, 47, 49, 70, 78, 67, 111, 99, 110, 121, 10, 89, 104, 48, 105, 103, 122, 121, 88, 120, 102, 107, 90, 89, 105, 101, 115, 90, 83, 76, 88, 48, 122, 122, 71, 53, 89, 54, 121, 85, 56, 120, 74, 122, 114, 119, 119, 47, 110, 115, 79, 77, 53, 68, 55, 55, 100, 73, 85, 107, 82, 56, 72, 114, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 101, 99, 117, 114, 105, 116, 121, 32, 67, 111, 109, 109, 117, 110, 105, 99, 97, 116, 105, 111, 110, 32, 82, 111, 111, 116, 67, 65, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 100, 122, 67, 67, 65, 108, 43, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 100, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 75, 85, 68, 69, 108, 77, 67, 77, 71, 65, 49, 85, 69, 67, 104, 77, 99, 10, 85, 48, 86, 68, 84, 48, 48, 103, 86, 72, 74, 49, 99, 51, 81, 103, 85, 51, 108, 122, 100, 71, 86, 116, 99, 121, 66, 68, 84, 121, 52, 115, 84, 70, 82, 69, 76, 106, 69, 110, 77, 67, 85, 71, 65, 49, 85, 69, 67, 120, 77, 101, 85, 50, 86, 106, 100, 88, 74, 112, 100, 72, 107, 103, 81, 50, 57, 116, 98, 88, 86, 117, 97, 87, 78, 104, 10, 100, 71, 108, 118, 98, 105, 66, 83, 98, 50, 57, 48, 81, 48, 69, 121, 77, 66, 52, 88, 68, 84, 65, 53, 77, 68, 85, 121, 79, 84, 65, 49, 77, 68, 65, 122, 79, 86, 111, 88, 68, 84, 73, 53, 77, 68, 85, 121, 79, 84, 65, 49, 77, 68, 65, 122, 79, 86, 111, 119, 88, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 10, 83, 108, 65, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 111, 84, 72, 70, 78, 70, 81, 48, 57, 78, 73, 70, 82, 121, 100, 88, 78, 48, 73, 70, 78, 53, 99, 51, 82, 108, 98, 88, 77, 103, 81, 48, 56, 117, 76, 69, 120, 85, 82, 67, 52, 120, 74, 122, 65, 108, 66, 103, 78, 86, 66, 65, 115, 84, 72, 108, 78, 108, 89, 51, 86, 121, 10, 97, 88, 82, 53, 73, 69, 78, 118, 98, 87, 49, 49, 98, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 85, 109, 57, 118, 100, 69, 78, 66, 77, 106, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 10, 65, 78, 65, 86, 79, 86, 75, 120, 85, 114, 79, 54, 120, 86, 109, 67, 120, 70, 49, 83, 114, 106, 112, 68, 90, 89, 66, 76, 120, 47, 75, 87, 118, 78, 115, 50, 108, 57, 97, 109, 90, 73, 121, 111, 88, 118, 68, 106, 67, 104, 122, 51, 51, 53, 99, 57, 83, 54, 55, 50, 88, 101, 119, 104, 116, 85, 71, 114, 122, 98, 108, 43, 100, 112, 43, 43, 10, 43, 84, 52, 50, 78, 75, 65, 55, 119, 102, 89, 120, 69, 85, 86, 48, 107, 122, 49, 88, 103, 77, 88, 53, 105, 90, 110, 75, 53, 97, 116, 113, 49, 76, 88, 97, 81, 90, 65, 81, 119, 100, 98, 87, 81, 111, 110, 67, 118, 47, 81, 52, 69, 112, 86, 77, 86, 65, 88, 51, 78, 117, 82, 70, 103, 51, 115, 85, 90, 100, 98, 99, 68, 69, 51, 82, 10, 51, 110, 52, 77, 113, 122, 118, 69, 70, 98, 52, 54, 86, 113, 90, 97, 98, 51, 90, 112, 85, 113, 108, 54, 117, 99, 106, 114, 97, 112, 112, 100, 85, 116, 65, 116, 67, 109, 115, 49, 70, 103, 107, 81, 104, 78, 66, 113, 121, 106, 111, 71, 65, 68, 100, 72, 53, 72, 53, 88, 84, 122, 43, 76, 54, 50, 101, 52, 105, 75, 114, 70, 118, 108, 78, 86, 10, 115, 112, 72, 69, 102, 98, 109, 119, 104, 82, 107, 71, 101, 67, 55, 98, 89, 82, 114, 54, 104, 102, 86, 75, 107, 97, 72, 110, 70, 116, 87, 79, 111, 106, 110, 102, 108, 76, 104, 119, 72, 121, 103, 47, 105, 47, 120, 65, 88, 109, 79, 68, 80, 73, 77, 113, 71, 112, 108, 114, 122, 57, 53, 90, 97, 106, 118, 56, 98, 120, 98, 88, 72, 47, 49, 75, 10, 69, 79, 116, 79, 103, 104, 89, 54, 114, 67, 99, 77, 85, 47, 71, 116, 49, 83, 83, 119, 97, 119, 78, 81, 119, 83, 48, 56, 70, 116, 49, 69, 78, 67, 99, 97, 100, 102, 115, 67, 65, 119, 69, 65, 65, 97, 78, 67, 77, 69, 65, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 65, 113, 70, 113, 88, 100, 108, 66, 90, 104, 56, 10, 81, 73, 72, 52, 68, 53, 99, 115, 79, 80, 69, 75, 55, 68, 122, 80, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 10, 67, 119, 85, 65, 65, 52, 73, 66, 65, 81, 66, 77, 79, 113, 78, 69, 114, 76, 108, 70, 115, 99, 101, 84, 102, 115, 103, 76, 67, 107, 76, 102, 90, 79, 111, 99, 55, 108, 108, 115, 67, 76, 113, 74, 88, 50, 114, 75, 83, 112, 87, 101, 101, 111, 56, 72, 120, 100, 112, 70, 99, 111, 74, 120, 68, 106, 114, 83, 122, 71, 43, 110, 116, 75, 69, 106, 10, 117, 47, 89, 107, 110, 56, 115, 88, 47, 111, 121, 109, 122, 115, 76, 83, 50, 56, 121, 78, 47, 72, 72, 56, 65, 121, 110, 66, 98, 70, 48, 122, 88, 50, 83, 50, 90, 84, 117, 74, 98, 120, 104, 50, 101, 80, 88, 99, 111, 107, 103, 102, 71, 84, 43, 79, 107, 43, 118, 120, 43, 104, 102, 117, 122, 85, 55, 106, 66, 66, 74, 86, 49, 117, 88, 107, 10, 51, 102, 115, 43, 66, 88, 122, 105, 72, 86, 55, 71, 112, 55, 121, 88, 84, 50, 103, 54, 57, 101, 107, 117, 67, 107, 79, 50, 114, 49, 100, 99, 89, 109, 104, 56, 116, 47, 50, 106, 105, 111, 83, 103, 114, 71, 75, 43, 75, 119, 109, 72, 78, 80, 66, 113, 65, 98, 117, 98, 75, 86, 89, 56, 47, 103, 65, 51, 122, 121, 78, 115, 56, 85, 54, 113, 10, 116, 110, 82, 71, 69, 109, 121, 82, 55, 106, 84, 86, 55, 74, 113, 82, 53, 48, 83, 43, 107, 68, 70, 121, 49, 85, 107, 67, 57, 103, 76, 108, 57, 66, 47, 114, 102, 78, 109, 87, 86, 97, 110, 47, 55, 73, 114, 53, 109, 85, 102, 47, 78, 86, 111, 67, 113, 103, 84, 76, 105, 108, 117, 72, 99, 83, 109, 82, 118, 97, 83, 48, 101, 103, 50, 57, 10, 109, 118, 86, 88, 73, 119, 65, 72, 73, 82, 99, 47, 83, 106, 110, 82, 66, 85, 107, 76, 112, 55, 89, 51, 103, 97, 86, 100, 106, 75, 111, 122, 88, 111, 69, 111, 102, 75, 100, 57, 74, 43, 115, 65, 114, 111, 48, 51, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 69, 67, 45, 65, 67, 67, 10, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 86, 106, 67, 67, 66, 68, 54, 103, 65, 119, 73, 66, 65, 103, 73, 81, 55, 105, 115, 57, 54, 57, 81, 104, 51, 104, 83, 111, 89, 113, 119, 69, 56, 57, 51, 69, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 66, 56, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 82, 86, 77, 120, 79, 122, 65, 53, 66, 103, 78, 86, 66, 65, 111, 84, 77, 107, 70, 110, 90, 87, 53, 106, 97, 87, 69, 103, 81, 50, 70, 48, 89, 87, 120, 104, 98, 109, 69, 103, 90, 71, 85, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 89, 50, 108, 118, 73, 67, 104, 79, 83, 85, 89, 103, 85, 83, 48, 119, 10, 79, 68, 65, 120, 77, 84, 99, 50, 76, 85, 107, 112, 77, 83, 103, 119, 74, 103, 89, 68, 86, 81, 81, 76, 69, 120, 57, 84, 90, 88, 74, 50, 90, 87, 108, 122, 73, 70, 66, 49, 89, 109, 120, 112, 89, 51, 77, 103, 90, 71, 85, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 89, 50, 108, 118, 77, 84, 85, 119, 77, 119, 89, 68, 10, 86, 81, 81, 76, 69, 121, 120, 87, 90, 87, 100, 108, 100, 83, 66, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 51, 100, 51, 100, 121, 53, 106, 89, 88, 82, 106, 90, 88, 74, 48, 76, 109, 53, 108, 100, 67, 57, 50, 90, 88, 74, 104, 99, 110, 74, 108, 98, 67, 65, 111, 89, 121, 107, 119, 77, 122, 69, 49, 77, 68, 77, 71, 65, 49, 85, 69, 10, 67, 120, 77, 115, 83, 109, 86, 121, 89, 88, 74, 120, 100, 87, 108, 104, 73, 69, 86, 117, 100, 71, 108, 48, 89, 88, 82, 122, 73, 71, 82, 108, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 87, 78, 112, 98, 121, 66, 68, 89, 88, 82, 104, 98, 71, 70, 117, 90, 88, 77, 120, 68, 122, 65, 78, 66, 103, 78, 86, 66, 65, 77, 84, 10, 66, 107, 86, 68, 76, 85, 70, 68, 81, 122, 65, 101, 70, 119, 48, 119, 77, 122, 65, 120, 77, 68, 99, 121, 77, 122, 65, 119, 77, 68, 66, 97, 70, 119, 48, 122, 77, 84, 65, 120, 77, 68, 99, 121, 77, 106, 85, 53, 78, 84, 108, 97, 77, 73, 72, 122, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 70, 85, 122, 69, 55, 10, 77, 68, 107, 71, 65, 49, 85, 69, 67, 104, 77, 121, 81, 87, 100, 108, 98, 109, 78, 112, 89, 83, 66, 68, 89, 88, 82, 104, 98, 71, 70, 117, 89, 83, 66, 107, 90, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 106, 97, 87, 56, 103, 75, 69, 53, 74, 82, 105, 66, 82, 76, 84, 65, 52, 77, 68, 69, 120, 78, 122, 89, 116, 10, 83, 83, 107, 120, 75, 68, 65, 109, 66, 103, 78, 86, 66, 65, 115, 84, 72, 49, 78, 108, 99, 110, 90, 108, 97, 88, 77, 103, 85, 72, 86, 105, 98, 71, 108, 106, 99, 121, 66, 107, 90, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 106, 97, 87, 56, 120, 78, 84, 65, 122, 66, 103, 78, 86, 66, 65, 115, 84, 76, 70, 90, 108, 10, 90, 50, 86, 49, 73, 71, 104, 48, 100, 72, 66, 122, 79, 105, 56, 118, 100, 51, 100, 51, 76, 109, 78, 104, 100, 71, 78, 108, 99, 110, 81, 117, 98, 109, 86, 48, 76, 51, 90, 108, 99, 109, 70, 121, 99, 109, 86, 115, 73, 67, 104, 106, 75, 84, 65, 122, 77, 84, 85, 119, 77, 119, 89, 68, 86, 81, 81, 76, 69, 121, 120, 75, 90, 88, 74, 104, 10, 99, 110, 70, 49, 97, 87, 69, 103, 82, 87, 53, 48, 97, 88, 82, 104, 100, 72, 77, 103, 90, 71, 85, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 89, 50, 108, 118, 73, 69, 78, 104, 100, 71, 70, 115, 89, 87, 53, 108, 99, 122, 69, 80, 77, 65, 48, 71, 65, 49, 85, 69, 65, 120, 77, 71, 82, 85, 77, 116, 81, 85, 78, 68, 10, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 115, 121, 76, 72, 84, 43, 75, 88, 81, 112, 87, 73, 82, 52, 78, 65, 57, 104, 48, 88, 56, 52, 78, 122, 74, 66, 53, 82, 56, 53, 105, 75, 10, 119, 53, 75, 52, 47, 48, 67, 81, 66, 88, 67, 72, 89, 77, 107, 65, 113, 98, 87, 85, 90, 82, 107, 105, 70, 82, 102, 67, 81, 50, 120, 109, 82, 74, 111, 78, 66, 68, 52, 53, 98, 54, 86, 76, 101, 113, 112, 106, 116, 52, 112, 69, 110, 100, 108, 106, 107, 89, 82, 109, 52, 67, 103, 80, 117, 107, 76, 106, 98, 111, 55, 51, 70, 67, 101, 84, 10, 97, 101, 54, 82, 68, 113, 78, 102, 68, 114, 72, 114, 90, 113, 74, 121, 84, 120, 73, 84, 104, 109, 86, 54, 80, 116, 116, 80, 66, 47, 83, 110, 67, 87, 68, 97, 79, 107, 75, 90, 120, 55, 74, 47, 115, 120, 97, 86, 72, 77, 102, 53, 78, 76, 87, 85, 104, 100, 87, 90, 88, 113, 66, 73, 111, 72, 55, 110, 70, 50, 87, 52, 111, 110, 87, 52, 10, 72, 118, 80, 108, 81, 110, 50, 118, 55, 102, 79, 75, 83, 71, 82, 100, 103, 104, 83, 84, 50, 77, 68, 107, 47, 55, 78, 81, 99, 118, 74, 50, 57, 114, 78, 100, 81, 108, 66, 53, 48, 74, 81, 43, 97, 119, 119, 65, 118, 116, 104, 114, 68, 107, 52, 113, 55, 68, 55, 83, 122, 73, 75, 105, 71, 71, 85, 122, 69, 51, 101, 101, 109, 108, 48, 97, 10, 69, 57, 106, 68, 50, 122, 51, 73, 108, 51, 114, 117, 99, 79, 50, 110, 53, 110, 122, 98, 99, 99, 56, 116, 108, 71, 76, 102, 98, 100, 98, 49, 79, 76, 52, 47, 112, 89, 85, 75, 71, 98, 105, 111, 50, 65, 108, 49, 81, 110, 68, 69, 54, 117, 47, 76, 68, 115, 103, 48, 113, 66, 73, 105, 109, 65, 121, 52, 69, 53, 83, 50, 83, 43, 122, 119, 10, 48, 74, 68, 110, 74, 119, 73, 68, 65, 81, 65, 66, 111, 52, 72, 106, 77, 73, 72, 103, 77, 66, 48, 71, 65, 49, 85, 100, 69, 81, 81, 87, 77, 66, 83, 66, 69, 109, 86, 106, 88, 50, 70, 106, 89, 48, 66, 106, 89, 88, 82, 106, 90, 88, 74, 48, 76, 109, 53, 108, 100, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 10, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 111, 77, 79, 76, 82, 75, 111, 51, 112, 85, 87, 47, 108, 52, 66, 97, 48, 102, 70, 52, 111, 112, 118, 112, 88, 89, 48, 119, 102, 119, 89, 68, 10, 86, 82, 48, 103, 66, 72, 103, 119, 100, 106, 66, 48, 66, 103, 115, 114, 66, 103, 69, 69, 65, 102, 86, 52, 65, 81, 77, 66, 67, 106, 66, 108, 77, 67, 119, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 73, 66, 70, 105, 66, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 51, 100, 51, 100, 121, 53, 106, 89, 88, 82, 106, 90, 88, 74, 48, 10, 76, 109, 53, 108, 100, 67, 57, 50, 90, 88, 74, 104, 99, 110, 74, 108, 98, 68, 65, 49, 66, 103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 67, 65, 106, 65, 112, 71, 105, 100, 87, 90, 87, 100, 108, 100, 83, 66, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 51, 100, 51, 100, 121, 53, 106, 89, 88, 82, 106, 90, 88, 74, 48, 76, 109, 53, 108, 10, 100, 67, 57, 50, 90, 88, 74, 104, 99, 110, 74, 108, 98, 67, 65, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 75, 66, 73, 87, 52, 73, 66, 57, 107, 49, 73, 117, 68, 108, 86, 78, 90, 121, 65, 101, 108, 79, 90, 49, 86, 114, 47, 115, 88, 69, 55, 122, 68, 107, 74, 10, 108, 70, 55, 87, 50, 117, 43, 43, 65, 86, 116, 100, 48, 120, 55, 89, 47, 88, 49, 80, 122, 97, 66, 66, 52, 68, 83, 84, 118, 56, 118, 105, 104, 112, 119, 51, 107, 112, 66, 87, 72, 78, 122, 114, 75, 81, 88, 108, 120, 74, 55, 72, 78, 100, 43, 75, 68, 77, 51, 70, 73, 85, 80, 112, 113, 111, 106, 108, 78, 99, 65, 90, 81, 109, 78, 97, 10, 65, 108, 54, 107, 83, 66, 103, 54, 104, 87, 47, 99, 110, 98, 119, 47, 110, 90, 122, 66, 104, 55, 104, 54, 89, 81, 106, 112, 100, 119, 116, 47, 99, 75, 116, 54, 51, 100, 109, 88, 76, 71, 81, 101, 104, 98, 43, 56, 100, 74, 97, 104, 119, 51, 111, 83, 55, 65, 119, 97, 98, 111, 77, 77, 80, 79, 104, 121, 82, 112, 47, 55, 83, 78, 86, 101, 10, 108, 43, 97, 120, 111, 102, 106, 107, 55, 48, 89, 108, 108, 74, 121, 74, 50, 50, 107, 52, 118, 117, 120, 99, 68, 108, 98, 72, 90, 86, 72, 108, 85, 73, 105, 73, 118, 48, 76, 86, 75, 122, 51, 108, 43, 98, 113, 101, 76, 114, 80, 75, 57, 72, 79, 83, 65, 103, 117, 43, 84, 71, 98, 114, 73, 80, 54, 53, 121, 55, 87, 90, 102, 43, 97, 50, 10, 69, 47, 114, 75, 83, 48, 51, 90, 55, 108, 78, 71, 66, 106, 118, 71, 84, 113, 50, 84, 87, 111, 70, 43, 98, 67, 112, 76, 97, 103, 86, 70, 106, 80, 73, 104, 112, 68, 71, 81, 104, 50, 120, 108, 110, 74, 50, 108, 89, 74, 85, 54, 85, 110, 47, 49, 48, 97, 115, 73, 98, 118, 80, 117, 87, 47, 109, 73, 80, 88, 54, 52, 98, 50, 52, 68, 10, 53, 69, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 72, 101, 108, 108, 101, 110, 105, 99, 32, 65, 99, 97, 100, 101, 109, 105, 99, 32, 97, 110, 100, 32, 82, 101, 115, 101, 97, 114, 99, 104, 32, 73, 110, 115, 116, 105, 116, 117, 116, 105, 111, 110, 115, 32, 82, 111, 111, 116, 67, 65, 32, 50, 48, 49, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 77, 84, 67, 67, 65, 120, 109, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 66, 108, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 49, 73, 120, 82, 68, 66, 67, 66, 103, 78, 86, 66, 65, 111, 84, 10, 79, 48, 104, 108, 98, 71, 120, 108, 98, 109, 108, 106, 73, 69, 70, 106, 89, 87, 82, 108, 98, 87, 108, 106, 73, 71, 70, 117, 90, 67, 66, 83, 90, 88, 78, 108, 89, 88, 74, 106, 97, 67, 66, 74, 98, 110, 78, 48, 97, 88, 82, 49, 100, 71, 108, 118, 98, 110, 77, 103, 81, 50, 86, 121, 100, 67, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 10, 97, 88, 82, 53, 77, 85, 65, 119, 80, 103, 89, 68, 86, 81, 81, 68, 69, 122, 100, 73, 90, 87, 120, 115, 90, 87, 53, 112, 89, 121, 66, 66, 89, 50, 70, 107, 90, 87, 49, 112, 89, 121, 66, 104, 98, 109, 81, 103, 85, 109, 86, 122, 90, 87, 70, 121, 89, 50, 103, 103, 83, 87, 53, 122, 100, 71, 108, 48, 100, 88, 82, 112, 98, 50, 53, 122, 10, 73, 70, 74, 118, 98, 51, 82, 68, 81, 83, 65, 121, 77, 68, 69, 120, 77, 66, 52, 88, 68, 84, 69, 120, 77, 84, 73, 119, 78, 106, 69, 122, 78, 68, 107, 49, 77, 108, 111, 88, 68, 84, 77, 120, 77, 84, 73, 119, 77, 84, 69, 122, 78, 68, 107, 49, 77, 108, 111, 119, 103, 90, 85, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 10, 65, 107, 100, 83, 77, 85, 81, 119, 81, 103, 89, 68, 86, 81, 81, 75, 69, 122, 116, 73, 90, 87, 120, 115, 90, 87, 53, 112, 89, 121, 66, 66, 89, 50, 70, 107, 90, 87, 49, 112, 89, 121, 66, 104, 98, 109, 81, 103, 85, 109, 86, 122, 90, 87, 70, 121, 89, 50, 103, 103, 83, 87, 53, 122, 100, 71, 108, 48, 100, 88, 82, 112, 98, 50, 53, 122, 10, 73, 69, 78, 108, 99, 110, 81, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 84, 70, 65, 77, 68, 52, 71, 65, 49, 85, 69, 65, 120, 77, 51, 83, 71, 86, 115, 98, 71, 86, 117, 97, 87, 77, 103, 81, 87, 78, 104, 90, 71, 86, 116, 97, 87, 77, 103, 89, 87, 53, 107, 73, 70, 74, 108, 99, 50, 86, 104, 99, 109, 78, 111, 10, 73, 69, 108, 117, 99, 51, 82, 112, 100, 72, 86, 48, 97, 87, 57, 117, 99, 121, 66, 83, 98, 50, 57, 48, 81, 48, 69, 103, 77, 106, 65, 120, 77, 84, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 10, 65, 75, 108, 84, 65, 79, 77, 117, 112, 118, 97, 79, 43, 109, 68, 89, 76, 90, 85, 43, 43, 67, 119, 113, 86, 69, 55, 78, 117, 89, 82, 104, 108, 70, 104, 80, 106, 122, 50, 76, 53, 69, 80, 122, 100, 89, 109, 78, 85, 101, 84, 68, 78, 57, 75, 75, 105, 69, 49, 53, 72, 114, 99, 83, 51, 85, 78, 52, 83, 111, 113, 83, 53, 116, 100, 73, 10, 49, 81, 43, 107, 79, 105, 108, 69, 78, 98, 103, 72, 57, 109, 103, 100, 86, 99, 48, 52, 85, 102, 67, 77, 74, 68, 71, 70, 114, 52, 80, 74, 102, 101, 108, 51, 114, 43, 48, 97, 101, 53, 48, 88, 43, 98, 79, 100, 79, 70, 65, 80, 112, 108, 112, 53, 107, 89, 67, 118, 78, 54, 54, 109, 48, 122, 72, 55, 116, 83, 89, 74, 110, 84, 120, 97, 10, 55, 49, 72, 70, 75, 57, 43, 87, 88, 101, 115, 121, 72, 103, 76, 97, 99, 69, 110, 115, 98, 103, 122, 73, 109, 106, 101, 78, 57, 47, 69, 50, 89, 69, 115, 109, 76, 73, 75, 101, 48, 72, 106, 122, 68, 81, 57, 106, 112, 70, 69, 119, 52, 102, 107, 114, 74, 120, 73, 72, 50, 79, 113, 57, 71, 71, 75, 89, 115, 70, 107, 51, 102, 98, 55, 117, 10, 56, 121, 66, 82, 81, 108, 113, 68, 55, 53, 79, 54, 97, 82, 88, 120, 89, 112, 50, 102, 109, 84, 109, 67, 111, 98, 100, 48, 76, 111, 118, 85, 120, 81, 116, 55, 76, 47, 68, 73, 67, 116, 111, 57, 101, 81, 113, 97, 107, 120, 121, 108, 75, 72, 74, 122, 107, 85, 79, 97, 112, 57, 70, 78, 104, 89, 83, 53, 113, 88, 83, 80, 70, 69, 68, 72, 10, 51, 78, 54, 115, 81, 87, 82, 115, 116, 66, 109, 98, 65, 109, 78, 116, 74, 71, 83, 80, 82, 76, 73, 108, 54, 115, 53, 100, 100, 65, 120, 106, 77, 108, 121, 78, 104, 43, 85, 67, 65, 119, 69, 65, 65, 97, 79, 66, 105, 84, 67, 66, 104, 106, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 10, 77, 65, 115, 71, 65, 49, 85, 100, 68, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 112, 112, 70, 67, 47, 82, 78, 104, 83, 105, 79, 101, 67, 75, 81, 112, 53, 100, 103, 84, 66, 67, 80, 117, 81, 83, 85, 119, 82, 119, 89, 68, 86, 82, 48, 101, 66, 69, 65, 119, 80, 113, 65, 56, 10, 77, 65, 87, 67, 65, 121, 53, 110, 99, 106, 65, 70, 103, 103, 77, 117, 90, 88, 85, 119, 66, 111, 73, 69, 76, 109, 86, 107, 100, 84, 65, 71, 103, 103, 81, 117, 98, 51, 74, 110, 77, 65, 87, 66, 65, 121, 53, 110, 99, 106, 65, 70, 103, 81, 77, 117, 90, 88, 85, 119, 66, 111, 69, 69, 76, 109, 86, 107, 100, 84, 65, 71, 103, 81, 81, 117, 10, 98, 51, 74, 110, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 66, 65, 81, 65, 102, 55, 51, 108, 66, 52, 88, 116, 117, 80, 55, 75, 77, 104, 106, 100, 67, 83, 107, 52, 99, 78, 120, 54, 78, 90, 114, 111, 107, 103, 99, 108, 80, 69, 103, 56, 104, 119, 65, 79, 88, 104, 105, 86, 116, 10, 88, 100, 77, 105, 75, 97, 104, 115, 111, 103, 50, 112, 54, 122, 48, 71, 87, 53, 107, 54, 120, 56, 122, 68, 109, 106, 82, 47, 113, 119, 55, 73, 84, 104, 122, 104, 43, 117, 84, 99, 122, 81, 50, 43, 118, 121, 84, 43, 98, 79, 100, 114, 119, 103, 51, 73, 66, 112, 53, 79, 106, 87, 69, 111, 112, 109, 114, 57, 53, 102, 90, 105, 54, 104, 103, 56, 10, 84, 113, 66, 84, 110, 98, 73, 54, 110, 79, 117, 108, 110, 74, 69, 87, 116, 107, 50, 67, 52, 65, 119, 70, 83, 75, 108, 115, 57, 99, 122, 52, 121, 53, 49, 74, 116, 80, 65, 67, 112, 102, 49, 119, 65, 43, 50, 75, 73, 97, 87, 117, 69, 52, 90, 74, 119, 122, 78, 122, 118, 111, 99, 55, 100, 73, 115, 88, 82, 83, 90, 77, 70, 112, 71, 68, 10, 47, 109, 100, 57, 122, 85, 49, 106, 90, 47, 114, 122, 65, 120, 75, 87, 101, 65, 97, 78, 115, 87, 102, 116, 106, 106, 43, 43, 110, 48, 56, 67, 57, 98, 77, 74, 76, 47, 78, 77, 104, 57, 56, 113, 121, 53, 86, 56, 65, 99, 121, 115, 78, 110, 113, 47, 111, 110, 78, 54, 57, 52, 47, 66, 116, 90, 113, 104, 70, 76, 75, 80, 77, 53, 56, 78, 10, 55, 121, 76, 99, 90, 110, 117, 69, 118, 85, 85, 88, 66, 106, 48, 56, 121, 114, 108, 51, 78, 73, 47, 75, 54, 115, 56, 47, 77, 84, 55, 106, 105, 79, 79, 65, 83, 83, 88, 73, 108, 55, 87, 100, 109, 112, 108, 78, 115, 68, 122, 52, 83, 103, 67, 98, 90, 78, 50, 102, 79, 85, 118, 82, 74, 57, 101, 52, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 99, 116, 97, 108, 105, 115, 32, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 117, 122, 67, 67, 65, 54, 79, 103, 65, 119, 73, 66, 65, 103, 73, 73, 86, 119, 111, 82, 108, 48, 76, 69, 52, 56, 119, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 97, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 83, 86, 81, 120, 68, 106, 65, 77, 10, 66, 103, 78, 86, 66, 65, 99, 77, 66, 85, 49, 112, 98, 71, 70, 117, 77, 83, 77, 119, 73, 81, 89, 68, 86, 81, 81, 75, 68, 66, 112, 66, 89, 51, 82, 104, 98, 71, 108, 122, 73, 70, 77, 117, 99, 67, 53, 66, 76, 105, 56, 119, 77, 122, 77, 49, 79, 68, 85, 121, 77, 68, 107, 50, 78, 122, 69, 110, 77, 67, 85, 71, 65, 49, 85, 69, 10, 65, 119, 119, 101, 81, 87, 78, 48, 89, 87, 120, 112, 99, 121, 66, 66, 100, 88, 82, 111, 90, 87, 53, 48, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 66, 52, 88, 68, 84, 69, 120, 77, 68, 107, 121, 77, 106, 69, 120, 77, 106, 73, 119, 77, 108, 111, 88, 68, 84, 77, 119, 77, 68, 107, 121, 10, 77, 106, 69, 120, 77, 106, 73, 119, 77, 108, 111, 119, 97, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 83, 86, 81, 120, 68, 106, 65, 77, 66, 103, 78, 86, 66, 65, 99, 77, 66, 85, 49, 112, 98, 71, 70, 117, 77, 83, 77, 119, 73, 81, 89, 68, 86, 81, 81, 75, 68, 66, 112, 66, 89, 51, 82, 104, 98, 71, 108, 122, 10, 73, 70, 77, 117, 99, 67, 53, 66, 76, 105, 56, 119, 77, 122, 77, 49, 79, 68, 85, 121, 77, 68, 107, 50, 78, 122, 69, 110, 77, 67, 85, 71, 65, 49, 85, 69, 65, 119, 119, 101, 81, 87, 78, 48, 89, 87, 120, 112, 99, 121, 66, 66, 100, 88, 82, 111, 90, 87, 53, 48, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 83, 98, 50, 57, 48, 10, 73, 69, 78, 66, 77, 73, 73, 67, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 103, 56, 65, 77, 73, 73, 67, 67, 103, 75, 67, 65, 103, 69, 65, 112, 56, 98, 69, 112, 83, 109, 107, 76, 79, 47, 108, 71, 77, 87, 119, 85, 75, 78, 118, 85, 84, 117, 102, 67, 108, 114, 74, 10, 119, 107, 103, 52, 67, 115, 73, 99, 111, 66, 104, 47, 107, 98, 87, 72, 117, 85, 65, 47, 51, 82, 49, 111, 72, 119, 105, 68, 49, 83, 48, 101, 105, 75, 68, 52, 106, 49, 97, 80, 98, 90, 107, 67, 107, 112, 65, 87, 49, 86, 56, 73, 98, 73, 110, 88, 52, 97, 121, 56, 73, 77, 75, 120, 52, 73, 78, 82, 105, 109, 108, 78, 65, 74, 90, 97, 10, 98, 121, 47, 65, 82, 72, 54, 106, 68, 117, 83, 82, 122, 86, 106, 117, 51, 80, 118, 72, 72, 107, 86, 72, 51, 83, 101, 53, 67, 65, 71, 102, 112, 105, 69, 100, 57, 85, 69, 116, 76, 48, 122, 57, 75, 75, 51, 103, 105, 113, 48, 105, 116, 70, 90, 108, 106, 111, 90, 85, 106, 53, 78, 68, 75, 100, 52, 53, 82, 110, 105, 106, 77, 67, 79, 54, 10, 122, 102, 66, 57, 69, 49, 102, 65, 88, 100, 75, 68, 97, 48, 104, 77, 120, 75, 117, 102, 103, 70, 112, 98, 79, 114, 51, 74, 112, 121, 73, 47, 103, 67, 99, 122, 87, 119, 54, 51, 105, 103, 120, 100, 66, 122, 99, 73, 121, 50, 122, 83, 101, 107, 99, 105, 82, 68, 88, 70, 122, 77, 119, 117, 106, 116, 48, 113, 55, 98, 100, 57, 90, 103, 49, 102, 10, 89, 86, 69, 105, 86, 82, 118, 106, 82, 117, 80, 106, 80, 100, 65, 49, 89, 112, 114, 98, 114, 120, 84, 73, 87, 54, 72, 77, 105, 82, 118, 104, 77, 67, 98, 56, 111, 74, 115, 102, 103, 97, 100, 72, 72, 119, 84, 114, 111, 122, 109, 83, 66, 112, 43, 90, 48, 55, 47, 84, 54, 107, 57, 81, 110, 66, 110, 43, 108, 111, 99, 101, 80, 71, 88, 50, 10, 111, 120, 103, 107, 103, 52, 89, 81, 53, 49, 81, 43, 113, 68, 112, 50, 74, 69, 43, 66, 73, 99, 88, 106, 68, 119, 76, 52, 107, 53, 82, 72, 73, 76, 118, 43, 49, 65, 55, 84, 97, 76, 110, 100, 120, 72, 113, 69, 103, 117, 78, 84, 86, 72, 110, 100, 50, 53, 122, 83, 56, 103, 101, 98, 76, 114, 97, 56, 80, 117, 50, 70, 98, 101, 56, 108, 10, 69, 102, 75, 88, 71, 107, 74, 104, 57, 48, 113, 88, 54, 73, 117, 120, 69, 65, 102, 54, 90, 89, 71, 121, 111, 106, 110, 80, 57, 122, 122, 47, 71, 80, 118, 71, 56, 86, 113, 76, 87, 101, 73, 67, 114, 72, 117, 83, 48, 69, 52, 85, 84, 49, 108, 70, 57, 103, 120, 101, 75, 70, 43, 119, 54, 68, 57, 70, 122, 56, 43, 118, 109, 50, 47, 55, 10, 104, 78, 78, 51, 87, 112, 86, 118, 114, 74, 83, 69, 110, 117, 54, 56, 119, 69, 113, 80, 83, 112, 80, 52, 82, 67, 72, 105, 77, 85, 86, 104, 85, 69, 52, 81, 50, 79, 77, 49, 102, 69, 119, 90, 116, 78, 52, 70, 118, 54, 77, 71, 110, 56, 105, 49, 122, 101, 81, 102, 49, 120, 99, 71, 68, 88, 113, 86, 100, 70, 85, 78, 97, 66, 114, 56, 10, 69, 66, 116, 105, 90, 74, 49, 116, 52, 74, 87, 103, 119, 53, 81, 72, 86, 119, 48, 85, 53, 114, 48, 70, 43, 55, 105, 102, 53, 116, 43, 76, 52, 115, 98, 110, 102, 112, 98, 50, 85, 56, 87, 65, 78, 70, 65, 111, 87, 80, 65, 83, 85, 72, 69, 88, 77, 76, 114, 109, 101, 71, 79, 56, 57, 76, 75, 116, 109, 121, 117, 121, 47, 117, 69, 53, 10, 106, 70, 54, 54, 67, 121, 67, 85, 51, 110, 117, 68, 117, 80, 47, 106, 86, 111, 50, 51, 69, 101, 107, 55, 106, 80, 75, 120, 119, 86, 50, 100, 112, 65, 116, 77, 75, 57, 109, 121, 71, 80, 87, 49, 110, 48, 115, 67, 65, 119, 69, 65, 65, 97, 78, 106, 77, 71, 69, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 70, 76, 89, 10, 105, 68, 114, 73, 110, 51, 104, 109, 55, 89, 110, 122, 101, 122, 104, 119, 108, 77, 107, 67, 65, 106, 98, 81, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 119, 89, 68, 86, 82, 48, 106, 66, 66, 103, 119, 70, 111, 65, 85, 85, 116, 105, 73, 79, 115, 105, 102, 101, 71, 98, 116, 10, 105, 102, 78, 55, 79, 72, 67, 85, 121, 81, 73, 67, 78, 116, 65, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 67, 65, 81, 65, 76, 101, 51, 75, 72, 119, 71, 67, 109, 83, 85, 121, 73, 10, 87, 79, 89, 100, 105, 80, 99, 85, 90, 69, 105, 109, 50, 70, 103, 75, 68, 107, 56, 84, 78, 100, 56, 49, 72, 100, 84, 116, 66, 106, 72, 73, 103, 84, 53, 113, 49, 100, 48, 55, 71, 106, 76, 117, 107, 68, 48, 82, 48, 105, 55, 48, 106, 115, 78, 106, 76, 105, 78, 109, 115, 71, 101, 43, 98, 55, 98, 65, 69, 122, 108, 103, 113, 113, 73, 48, 10, 74, 90, 78, 49, 85, 116, 54, 110, 110, 97, 48, 79, 104, 52, 108, 83, 99, 87, 111, 87, 80, 66, 107, 100, 103, 47, 105, 97, 75, 87, 87, 43, 57, 68, 43, 97, 50, 102, 68, 122, 87, 111, 99, 104, 99, 89, 66, 78, 121, 43, 65, 52, 109, 122, 43, 55, 43, 117, 65, 119, 84, 99, 43, 71, 48, 50, 85, 81, 71, 82, 106, 82, 108, 119, 75, 120, 10, 75, 51, 74, 67, 97, 75, 121, 103, 118, 85, 53, 97, 50, 104, 105, 47, 97, 53, 105, 66, 48, 80, 50, 97, 118, 108, 52, 86, 83, 77, 48, 82, 70, 98, 110, 65, 75, 86, 121, 48, 54, 73, 106, 51, 80, 106, 97, 117, 116, 50, 76, 57, 72, 109, 76, 101, 99, 72, 103, 81, 72, 69, 104, 98, 50, 114, 121, 107, 79, 76, 112, 110, 55, 86, 85, 43, 10, 88, 108, 102, 102, 49, 65, 78, 65, 84, 73, 71, 107, 48, 107, 57, 106, 112, 119, 108, 67, 67, 82, 84, 56, 65, 75, 110, 67, 103, 72, 78, 80, 76, 115, 66, 65, 50, 82, 70, 55, 83, 79, 112, 54, 65, 115, 68, 84, 54, 121, 103, 66, 74, 108, 104, 48, 119, 99, 66, 122, 73, 109, 50, 84, 108, 102, 48, 53, 102, 98, 115, 113, 52, 47, 97, 67, 10, 52, 121, 121, 88, 88, 48, 52, 102, 107, 90, 84, 54, 47, 105, 121, 106, 50, 72, 89, 97, 117, 69, 50, 121, 79, 69, 43, 98, 43, 104, 49, 73, 89, 72, 107, 109, 52, 118, 80, 57, 113, 100, 67, 97, 54, 72, 67, 80, 83, 88, 114, 87, 53, 98, 48, 75, 68, 116, 115, 116, 56, 52, 50, 47, 54, 43, 79, 107, 102, 99, 118, 72, 108, 88, 72, 111, 10, 50, 113, 78, 56, 120, 99, 76, 52, 100, 74, 73, 69, 71, 52, 97, 115, 112, 67, 74, 84, 81, 76, 97, 115, 47, 107, 120, 50, 122, 47, 117, 85, 77, 115, 65, 49, 110, 51, 89, 47, 98, 117, 87, 81, 98, 113, 67, 109, 74, 113, 75, 52, 76, 76, 55, 82, 75, 52, 88, 57, 112, 50, 106, 73, 117, 103, 69, 114, 115, 87, 120, 48, 72, 98, 104, 122, 10, 108, 101, 102, 117, 116, 56, 99, 108, 56, 65, 66, 77, 65, 76, 74, 43, 116, 103, 117, 76, 72, 80, 80, 65, 85, 74, 52, 108, 117, 101, 65, 73, 51, 106, 90, 109, 47, 122, 101, 108, 48, 98, 116, 85, 90, 67, 122, 74, 74, 55, 86, 76, 107, 110, 53, 108, 47, 57, 77, 116, 52, 98, 108, 79, 118, 72, 43, 107, 81, 83, 71, 81, 81, 88, 101, 109, 10, 79, 82, 47, 113, 110, 117, 79, 102, 48, 71, 90, 118, 66, 101, 121, 113, 100, 110, 54, 47, 97, 120, 97, 103, 54, 55, 88, 72, 47, 74, 74, 85, 76, 121, 115, 82, 74, 121, 85, 51, 101, 69, 120, 82, 97, 114, 68, 122, 122, 70, 104, 100, 70, 80, 70, 113, 83, 66, 88, 47, 119, 103, 101, 50, 115, 89, 48, 80, 106, 108, 120, 81, 82, 114, 77, 57, 10, 118, 119, 71, 89, 84, 55, 74, 90, 86, 69, 99, 43, 78, 72, 116, 52, 98, 86, 97, 84, 76, 110, 80, 113, 90, 105, 104, 52, 122, 82, 48, 85, 118, 54, 67, 80, 76, 121, 54, 52, 76, 111, 55, 121, 70, 73, 114, 77, 54, 98, 86, 56, 43, 50, 121, 100, 68, 75, 88, 104, 108, 103, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 84, 114, 117, 115, 116, 105, 115, 32, 70, 80, 83, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 90, 122, 67, 67, 65, 107, 43, 103, 65, 119, 73, 66, 65, 103, 73, 81, 71, 120, 43, 116, 116, 105, 68, 53, 74, 78, 77, 50, 97, 47, 102, 72, 56, 89, 121, 103, 87, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 70, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 72, 81, 106, 69, 89, 77, 66, 89, 71, 65, 49, 85, 69, 67, 104, 77, 80, 86, 72, 74, 49, 99, 51, 82, 112, 99, 121, 66, 77, 97, 87, 49, 112, 100, 71, 86, 107, 77, 82, 119, 119, 71, 103, 89, 68, 86, 81, 81, 76, 69, 120, 78, 85, 99, 110, 86, 122, 100, 71, 108, 122, 73, 69, 90, 81, 85, 121, 66, 83, 98, 50, 57, 48, 10, 73, 69, 78, 66, 77, 66, 52, 88, 68, 84, 65, 122, 77, 84, 73, 121, 77, 122, 69, 121, 77, 84, 81, 119, 78, 108, 111, 88, 68, 84, 73, 48, 77, 68, 69, 121, 77, 84, 69, 120, 77, 122, 89, 49, 78, 70, 111, 119, 82, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 48, 73, 120, 71, 68, 65, 87, 66, 103, 78, 86, 10, 66, 65, 111, 84, 68, 49, 82, 121, 100, 88, 78, 48, 97, 88, 77, 103, 84, 71, 108, 116, 97, 88, 82, 108, 90, 68, 69, 99, 77, 66, 111, 71, 65, 49, 85, 69, 67, 120, 77, 84, 86, 72, 74, 49, 99, 51, 82, 112, 99, 121, 66, 71, 85, 70, 77, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 84, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 10, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 77, 86, 81, 101, 53, 52, 55, 78, 100, 68, 102, 120, 73, 122, 78, 106, 112, 118, 116, 111, 56, 65, 50, 109, 102, 82, 67, 54, 113, 99, 43, 103, 73, 77, 80, 112, 113, 100, 90, 104, 56, 109, 81, 10, 82, 85, 78, 43, 65, 79, 113, 71, 101, 83, 111, 68, 118, 84, 48, 51, 109, 89, 108, 109, 116, 43, 87, 75, 86, 111, 97, 84, 110, 71, 104, 76, 97, 65, 83, 77, 107, 53, 77, 67, 80, 106, 68, 83, 78, 122, 111, 105, 89, 89, 107, 99, 104, 85, 53, 57, 106, 57, 87, 118, 101, 122, 88, 50, 102, 105, 104, 72, 105, 84, 72, 99, 68, 110, 108, 107, 10, 72, 53, 110, 83, 87, 55, 114, 43, 102, 50, 67, 47, 114, 101, 118, 110, 80, 68, 103, 112, 97, 105, 47, 108, 107, 81, 116, 86, 47, 43, 120, 118, 87, 78, 85, 116, 121, 100, 53, 77, 90, 110, 71, 80, 68, 78, 99, 69, 50, 103, 102, 109, 72, 104, 106, 106, 118, 83, 107, 67, 113, 80, 111, 99, 52, 86, 117, 53, 103, 54, 104, 66, 83, 76, 119, 97, 10, 99, 89, 51, 110, 89, 117, 85, 116, 115, 117, 118, 102, 102, 77, 47, 98, 113, 49, 114, 75, 77, 102, 70, 77, 73, 118, 77, 70, 69, 47, 101, 67, 43, 88, 78, 53, 68, 76, 55, 88, 83, 120, 122, 65, 48, 82, 85, 56, 107, 48, 70, 107, 48, 101, 97, 43, 73, 120, 99, 105, 65, 73, 108, 101, 72, 50, 117, 108, 114, 71, 54, 110, 83, 52, 122, 116, 10, 111, 51, 76, 109, 114, 50, 78, 78, 76, 52, 88, 83, 70, 68, 87, 97, 76, 107, 54, 77, 54, 106, 75, 89, 75, 73, 97, 104, 107, 81, 108, 66, 79, 114, 84, 104, 52, 47, 76, 54, 56, 77, 107, 75, 111, 107, 72, 100, 113, 101, 77, 68, 120, 52, 103, 86, 79, 120, 122, 85, 71, 112, 84, 88, 110, 50, 82, 90, 69, 109, 48, 67, 65, 119, 69, 65, 10, 65, 97, 78, 84, 77, 70, 69, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 83, 54, 43, 110, 69, 108, 101, 89, 116, 88, 81, 83, 85, 104, 104, 103, 116, 120, 54, 55, 74, 107, 68, 111, 115, 104, 90, 122, 65, 100, 10, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 117, 118, 112, 120, 74, 88, 109, 76, 86, 48, 69, 108, 73, 89, 89, 76, 99, 101, 117, 121, 90, 65, 54, 76, 73, 87, 99, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 72, 53, 89, 47, 47, 48, 49, 71, 88, 50, 99, 10, 71, 69, 43, 101, 115, 67, 117, 56, 106, 111, 119, 85, 47, 121, 121, 103, 50, 107, 100, 98, 119, 43, 43, 66, 76, 97, 56, 70, 54, 110, 82, 73, 87, 47, 77, 43, 84, 103, 102, 72, 98, 99, 87, 122, 107, 56, 56, 105, 78, 86, 121, 50, 80, 51, 85, 110, 88, 119, 109, 87, 122, 97, 68, 43, 118, 107, 65, 77, 88, 66, 74, 86, 43, 74, 79, 67, 10, 121, 105, 110, 112, 88, 106, 57, 87, 86, 52, 115, 52, 78, 118, 100, 70, 71, 107, 119, 111, 122, 90, 53, 66, 117, 79, 49, 87, 84, 73, 83, 107, 81, 77, 105, 52, 115, 75, 85, 114, 97, 88, 65, 69, 97, 115, 80, 52, 49, 66, 73, 121, 43, 81, 55, 68, 115, 100, 119, 121, 104, 69, 81, 115, 98, 56, 116, 71, 68, 43, 112, 109, 81, 81, 57, 80, 10, 56, 86, 105, 108, 112, 103, 48, 78, 68, 50, 72, 101, 112, 90, 53, 100, 102, 87, 87, 104, 80, 66, 102, 110, 113, 70, 86, 79, 55, 54, 68, 72, 55, 99, 90, 69, 102, 49, 84, 49, 111, 43, 67, 80, 56, 72, 120, 86, 73, 111, 56, 112, 116, 111, 71, 106, 52, 87, 49, 79, 76, 66, 117, 65, 90, 43, 121, 116, 73, 74, 56, 77, 89, 109, 72, 86, 10, 108, 47, 57, 68, 55, 83, 51, 66, 50, 108, 48, 112, 75, 111, 85, 47, 114, 71, 88, 117, 104, 103, 56, 70, 106, 90, 66, 102, 51, 43, 54, 102, 57, 76, 47, 117, 72, 102, 117, 89, 53, 72, 43, 81, 75, 52, 82, 52, 69, 65, 53, 115, 83, 86, 80, 118, 70, 86, 116, 108, 82, 107, 112, 100, 114, 55, 114, 55, 79, 110, 73, 100, 122, 102, 89, 108, 10, 105, 66, 54, 88, 122, 67, 71, 99, 75, 81, 69, 78, 90, 101, 116, 88, 50, 102, 78, 88, 108, 114, 116, 73, 122, 89, 69, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 116, 97, 114, 116, 67, 111, 109, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 72, 104, 122, 67, 67, 66, 87, 43, 103, 65, 119, 73, 66, 65, 103, 73, 66, 76, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 57, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 74, 84, 68, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 67, 104, 77, 78, 10, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 103, 84, 72, 82, 107, 76, 106, 69, 114, 77, 67, 107, 71, 65, 49, 85, 69, 67, 120, 77, 105, 85, 50, 86, 106, 100, 88, 74, 108, 73, 69, 82, 112, 90, 50, 108, 48, 89, 87, 119, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 85, 103, 85, 50, 108, 110, 98, 109, 108, 117, 10, 90, 122, 69, 112, 77, 67, 99, 71, 65, 49, 85, 69, 65, 120, 77, 103, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 72, 104, 99, 78, 77, 68, 89, 119, 79, 84, 69, 51, 77, 84, 107, 48, 10, 78, 106, 77, 51, 87, 104, 99, 78, 77, 122, 89, 119, 79, 84, 69, 51, 77, 84, 107, 48, 78, 106, 77, 50, 87, 106, 66, 57, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 74, 84, 68, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 67, 104, 77, 78, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 103, 84, 72, 82, 107, 10, 76, 106, 69, 114, 77, 67, 107, 71, 65, 49, 85, 69, 67, 120, 77, 105, 85, 50, 86, 106, 100, 88, 74, 108, 73, 69, 82, 112, 90, 50, 108, 48, 89, 87, 119, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 85, 103, 85, 50, 108, 110, 98, 109, 108, 117, 90, 122, 69, 112, 77, 67, 99, 71, 65, 49, 85, 69, 65, 120, 77, 103, 10, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 10, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 68, 66, 105, 78, 115, 74, 118, 71, 120, 71, 102, 72, 105, 102, 108, 88, 117, 49, 77, 53, 68, 121, 99, 109, 76, 87, 119, 84, 89, 103, 73, 105, 82, 101, 122, 117, 108, 51, 56, 107, 77, 75, 111, 103, 90, 107, 112, 77, 121, 79, 78, 118, 103, 52, 53, 105, 80, 119, 98, 109, 50, 120, 80, 78, 49, 121, 10, 111, 52, 85, 99, 111, 100, 77, 57, 116, 68, 77, 114, 48, 121, 43, 118, 47, 117, 113, 119, 81, 86, 108, 110, 116, 115, 81, 71, 102, 81, 113, 101, 100, 73, 88, 87, 101, 85, 121, 65, 78, 51, 114, 102, 79, 81, 86, 83, 87, 102, 102, 48, 71, 48, 90, 68, 112, 78, 75, 70, 104, 100, 76, 68, 99, 102, 78, 49, 89, 106, 83, 54, 76, 73, 112, 47, 10, 72, 111, 47, 117, 55, 84, 84, 81, 69, 99, 101, 87, 122, 86, 73, 57, 117, 106, 80, 87, 51, 85, 51, 101, 67, 122, 116, 75, 83, 53, 47, 67, 74, 105, 47, 54, 116, 82, 89, 99, 99, 106, 86, 51, 121, 106, 120, 100, 53, 115, 114, 104, 74, 111, 115, 97, 78, 110, 90, 99, 65, 100, 116, 48, 70, 67, 88, 43, 55, 98, 87, 103, 105, 65, 47, 100, 10, 101, 77, 111, 116, 72, 119, 101, 88, 77, 65, 69, 116, 99, 110, 110, 54, 82, 116, 89, 84, 75, 113, 105, 53, 112, 113, 117, 68, 83, 82, 51, 108, 56, 117, 47, 100, 53, 65, 71, 79, 71, 65, 113, 80, 89, 49, 77, 87, 104, 87, 75, 112, 68, 104, 107, 54, 122, 76, 86, 109, 112, 115, 74, 114, 100, 65, 102, 107, 75, 43, 70, 50, 80, 114, 82, 116, 10, 50, 80, 90, 69, 52, 88, 78, 105, 72, 122, 118, 69, 118, 113, 66, 84, 86, 105, 86, 115, 85, 81, 110, 51, 113, 113, 118, 75, 118, 51, 98, 57, 98, 90, 118, 122, 110, 100, 117, 47, 80, 87, 97, 56, 68, 70, 97, 113, 114, 53, 104, 73, 108, 84, 112, 76, 51, 54, 100, 89, 85, 78, 107, 52, 100, 97, 108, 98, 54, 107, 77, 77, 65, 118, 43, 90, 10, 54, 43, 104, 115, 84, 88, 66, 98, 75, 87, 87, 99, 51, 97, 112, 100, 122, 75, 56, 66, 77, 101, 119, 77, 54, 57, 75, 78, 54, 79, 113, 99, 101, 43, 90, 117, 57, 121, 100, 109, 68, 66, 112, 73, 49, 50, 53, 67, 52, 122, 47, 101, 73, 84, 53, 55, 52, 81, 49, 119, 43, 50, 79, 113, 113, 71, 119, 97, 86, 76, 82, 99, 74, 88, 114, 74, 10, 111, 115, 109, 76, 70, 113, 97, 55, 76, 72, 52, 88, 88, 103, 86, 78, 87, 71, 52, 83, 72, 81, 72, 117, 69, 104, 65, 78, 120, 106, 74, 47, 71, 80, 47, 56, 57, 80, 114, 78, 98, 112, 72, 111, 78, 107, 109, 43, 71, 107, 104, 112, 105, 56, 75, 87, 84, 82, 111, 83, 115, 109, 107, 88, 119, 81, 113, 81, 49, 118, 112, 53, 73, 107, 105, 47, 10, 117, 110, 116, 112, 43, 72, 68, 72, 43, 110, 111, 51, 50, 78, 103, 78, 48, 110, 90, 80, 86, 47, 43, 81, 116, 43, 79, 82, 48, 116, 51, 118, 119, 109, 67, 51, 90, 122, 114, 100, 47, 113, 113, 99, 56, 78, 83, 76, 102, 51, 73, 105, 122, 115, 97, 102, 108, 55, 98, 52, 114, 52, 113, 103, 69, 75, 106, 90, 43, 120, 106, 71, 116, 114, 86, 99, 10, 85, 106, 121, 74, 116, 104, 107, 113, 99, 119, 69, 75, 68, 119, 79, 122, 69, 109, 68, 121, 101, 105, 43, 66, 50, 54, 78, 117, 47, 121, 89, 119, 108, 47, 87, 76, 51, 89, 108, 88, 116, 113, 48, 57, 115, 54, 56, 114, 120, 98, 100, 50, 65, 118, 67, 108, 49, 105, 117, 97, 104, 104, 81, 113, 99, 118, 98, 106, 77, 52, 120, 100, 67, 85, 115, 84, 10, 51, 55, 117, 77, 100, 66, 78, 83, 83, 119, 73, 68, 65, 81, 65, 66, 111, 52, 73, 67, 69, 68, 67, 67, 65, 103, 119, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 10, 86, 82, 48, 79, 66, 66, 89, 69, 70, 69, 52, 76, 55, 120, 113, 107, 81, 70, 117, 108, 70, 50, 109, 72, 77, 77, 111, 48, 97, 69, 80, 81, 81, 97, 55, 121, 77, 66, 56, 71, 65, 49, 85, 100, 73, 119, 81, 89, 77, 66, 97, 65, 70, 69, 52, 76, 55, 120, 113, 107, 81, 70, 117, 108, 70, 50, 109, 72, 77, 77, 111, 48, 97, 69, 80, 81, 10, 81, 97, 55, 121, 77, 73, 73, 66, 87, 103, 89, 68, 86, 82, 48, 103, 66, 73, 73, 66, 85, 84, 67, 67, 65, 85, 48, 119, 103, 103, 70, 74, 66, 103, 115, 114, 66, 103, 69, 69, 65, 89, 71, 49, 78, 119, 69, 66, 65, 84, 67, 67, 65, 84, 103, 119, 76, 103, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 103, 69, 87, 73, 109, 104, 48, 10, 100, 72, 65, 54, 76, 121, 57, 51, 100, 51, 99, 117, 99, 51, 82, 104, 99, 110, 82, 122, 99, 50, 119, 117, 89, 50, 57, 116, 76, 51, 66, 118, 98, 71, 108, 106, 101, 83, 53, 119, 90, 71, 89, 119, 78, 65, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 103, 69, 87, 75, 71, 104, 48, 100, 72, 65, 54, 76, 121, 57, 51, 100, 51, 99, 117, 10, 99, 51, 82, 104, 99, 110, 82, 122, 99, 50, 119, 117, 89, 50, 57, 116, 76, 50, 108, 117, 100, 71, 86, 121, 98, 87, 86, 107, 97, 87, 70, 48, 90, 83, 53, 119, 90, 71, 89, 119, 103, 99, 56, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 73, 67, 77, 73, 72, 67, 77, 67, 99, 87, 73, 70, 78, 48, 89, 88, 74, 48, 73, 69, 78, 118, 10, 98, 87, 49, 108, 99, 109, 78, 112, 89, 87, 119, 103, 75, 70, 78, 48, 89, 88, 74, 48, 81, 50, 57, 116, 75, 83, 66, 77, 100, 71, 81, 117, 77, 65, 77, 67, 65, 81, 69, 97, 103, 90, 90, 77, 97, 87, 49, 112, 100, 71, 86, 107, 73, 69, 120, 112, 89, 87, 74, 112, 98, 71, 108, 48, 101, 83, 119, 103, 99, 109, 86, 104, 90, 67, 66, 48, 10, 97, 71, 85, 103, 99, 50, 86, 106, 100, 71, 108, 118, 98, 105, 65, 113, 84, 71, 86, 110, 89, 87, 119, 103, 84, 71, 108, 116, 97, 88, 82, 104, 100, 71, 108, 118, 98, 110, 77, 113, 73, 71, 57, 109, 73, 72, 82, 111, 90, 83, 66, 84, 100, 71, 70, 121, 100, 69, 78, 118, 98, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 10, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 83, 66, 81, 98, 50, 120, 112, 89, 51, 107, 103, 89, 88, 90, 104, 97, 87, 120, 104, 89, 109, 120, 108, 73, 71, 70, 48, 73, 71, 104, 48, 100, 72, 65, 54, 76, 121, 57, 51, 100, 51, 99, 117, 99, 51, 82, 104, 99, 110, 82, 122, 99, 50, 119, 117, 89, 50, 57, 116, 10, 76, 51, 66, 118, 98, 71, 108, 106, 101, 83, 53, 119, 90, 71, 89, 119, 69, 81, 89, 74, 89, 73, 90, 73, 65, 89, 98, 52, 81, 103, 69, 66, 66, 65, 81, 68, 65, 103, 65, 72, 77, 68, 103, 71, 67, 87, 67, 71, 83, 65, 71, 71, 43, 69, 73, 66, 68, 81, 81, 114, 70, 105, 108, 84, 100, 71, 70, 121, 100, 69, 78, 118, 98, 83, 66, 71, 10, 99, 109, 86, 108, 73, 70, 78, 84, 84, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, 67, 65, 103, 69, 65, 106, 111, 47, 110, 51, 74, 82, 53, 10, 102, 80, 71, 70, 102, 53, 57, 74, 98, 50, 118, 75, 88, 102, 117, 77, 47, 103, 84, 70, 119, 87, 76, 82, 102, 85, 75, 75, 118, 70, 79, 51, 108, 65, 78, 109, 77, 68, 43, 120, 53, 119, 113, 110, 85, 67, 66, 86, 74, 88, 57, 50, 101, 104, 81, 78, 54, 119, 81, 79, 81, 79, 89, 43, 50, 73, 105, 114, 66, 121, 101, 68, 113, 88, 87, 109, 10, 78, 51, 80, 72, 47, 85, 118, 83, 84, 97, 48, 88, 81, 77, 104, 71, 118, 106, 116, 47, 85, 102, 122, 68, 116, 103, 85, 120, 51, 77, 50, 70, 73, 107, 53, 120, 116, 47, 74, 120, 88, 114, 65, 97, 120, 114, 113, 84, 105, 51, 105, 83, 83, 111, 88, 52, 101, 65, 43, 68, 47, 105, 43, 116, 76, 80, 102, 107, 112, 76, 115, 116, 48, 79, 99, 78, 10, 79, 114, 103, 43, 122, 118, 90, 52, 57, 113, 53, 72, 74, 77, 113, 106, 78, 84, 98, 79, 120, 56, 97, 72, 109, 78, 114, 115, 43, 43, 109, 121, 122, 105, 101, 98, 105, 77, 77, 69, 111, 102, 89, 76, 87, 87, 105, 118, 121, 100, 115, 81, 68, 48, 51, 50, 90, 71, 78, 99, 112, 82, 74, 118, 107, 114, 75, 84, 108, 77, 101, 73, 70, 119, 54, 84, 10, 116, 110, 53, 105, 105, 53, 66, 47, 113, 48, 54, 102, 47, 79, 78, 49, 70, 69, 56, 113, 77, 116, 57, 98, 68, 101, 68, 49, 101, 53, 77, 78, 113, 54, 72, 80, 104, 43, 71, 108, 66, 69, 88, 111, 80, 66, 75, 108, 67, 99, 87, 119, 48, 98, 100, 84, 56, 50, 65, 85, 117, 111, 86, 112, 97, 105, 70, 56, 72, 51, 86, 104, 70, 121, 65, 88, 10, 101, 50, 119, 55, 81, 83, 108, 99, 52, 97, 120, 97, 48, 99, 50, 77, 109, 43, 116, 103, 72, 82, 110, 115, 57, 43, 87, 119, 50, 118, 108, 53, 71, 75, 86, 70, 80, 48, 108, 68, 86, 57, 76, 100, 74, 78, 85, 115, 111, 47, 50, 82, 106, 83, 101, 49, 53, 101, 115, 85, 66, 112, 112, 77, 101, 121, 71, 55, 79, 113, 48, 119, 66, 104, 106, 65, 10, 50, 77, 70, 114, 76, 72, 57, 90, 88, 70, 50, 82, 115, 88, 65, 105, 86, 43, 117, 75, 97, 48, 104, 75, 49, 81, 56, 112, 55, 77, 90, 65, 119, 67, 43, 73, 84, 71, 103, 66, 70, 51, 102, 48, 74, 66, 108, 80, 118, 102, 114, 104, 115, 105, 65, 104, 83, 57, 48, 97, 50, 67, 108, 57, 113, 114, 106, 101, 86, 79, 119, 104, 86, 89, 66, 115, 10, 72, 118, 85, 119, 121, 75, 77, 81, 53, 98, 76, 109, 75, 104, 81, 120, 119, 52, 85, 116, 106, 74, 105, 120, 104, 108, 112, 80, 105, 86, 107, 116, 117, 99, 102, 51, 72, 77, 105, 75, 102, 56, 67, 100, 66, 85, 114, 109, 81, 107, 57, 105, 111, 50, 48, 112, 112, 66, 43, 70, 113, 57, 118, 108, 103, 99, 105, 116, 75, 106, 49, 77, 88, 86, 117, 69, 10, 74, 110, 72, 69, 104, 86, 53, 120, 74, 77, 113, 108, 71, 50, 122, 89, 89, 100, 77, 97, 52, 70, 84, 98, 122, 114, 113, 112, 77, 114, 85, 105, 57, 110, 78, 66, 67, 86, 50, 52, 70, 49, 48, 79, 68, 53, 109, 81, 49, 107, 102, 97, 98, 119, 111, 54, 89, 105, 103, 85, 90, 52, 76, 90, 56, 100, 67, 65, 87, 90, 118, 76, 77, 100, 105, 98, 10, 68, 52, 120, 51, 84, 114, 86, 111, 105, 118, 74, 115, 57, 105, 81, 79, 76, 87, 120, 119, 120, 88, 80, 82, 51, 104, 84, 81, 99, 89, 43, 50, 48, 51, 115, 67, 57, 117, 79, 52, 49, 65, 108, 117, 97, 53, 53, 49, 104, 68, 110, 109, 102, 121, 87, 108, 56, 107, 103, 65, 119, 75, 81, 66, 50, 106, 56, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 116, 97, 114, 116, 67, 111, 109, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 89, 122, 67, 67, 65, 48, 117, 103, 65, 119, 73, 66, 65, 103, 73, 66, 79, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 84, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 74, 84, 68, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 67, 104, 77, 78, 10, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 103, 84, 72, 82, 107, 76, 106, 69, 115, 77, 67, 111, 71, 65, 49, 85, 69, 65, 120, 77, 106, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 103, 10, 82, 122, 73, 119, 72, 104, 99, 78, 77, 84, 65, 119, 77, 84, 65, 120, 77, 68, 69, 119, 77, 68, 65, 120, 87, 104, 99, 78, 77, 122, 107, 120, 77, 106, 77, 120, 77, 106, 77, 49, 79, 84, 65, 120, 87, 106, 66, 84, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 74, 84, 68, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, 10, 67, 104, 77, 78, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 103, 84, 72, 82, 107, 76, 106, 69, 115, 77, 67, 111, 71, 65, 49, 85, 69, 65, 120, 77, 106, 85, 51, 82, 104, 99, 110, 82, 68, 98, 50, 48, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 10, 100, 72, 107, 103, 82, 122, 73, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 50, 105, 84, 90, 98, 66, 55, 99, 103, 78, 114, 50, 67, 117, 43, 69, 87, 73, 65, 79, 86, 101, 113, 56, 79, 10, 111, 49, 88, 74, 74, 90, 108, 75, 120, 100, 66, 87, 81, 89, 101, 81, 84, 83, 70, 103, 112, 66, 83, 72, 79, 56, 51, 57, 115, 106, 54, 48, 90, 119, 78, 113, 55, 101, 69, 80, 83, 56, 67, 82, 104, 88, 66, 70, 52, 69, 75, 101, 51, 105, 107, 106, 49, 65, 69, 78, 111, 66, 66, 53, 117, 78, 115, 68, 118, 102, 79, 112, 76, 57, 72, 71, 10, 52, 65, 47, 76, 110, 111, 111, 85, 67, 114, 105, 57, 57, 108, 90, 105, 56, 99, 86, 121, 116, 106, 73, 108, 50, 98, 76, 122, 118, 87, 88, 70, 68, 83, 120, 117, 49, 90, 74, 118, 71, 73, 115, 65, 81, 82, 83, 67, 98, 48, 65, 103, 74, 110, 111, 111, 68, 47, 85, 101, 102, 121, 102, 51, 108, 76, 69, 51, 80, 98, 102, 72, 107, 102, 102, 105, 10, 65, 101, 122, 57, 108, 73, 110, 104, 122, 71, 55, 84, 78, 116, 89, 75, 71, 88, 109, 117, 49, 122, 83, 67, 90, 102, 57, 56, 81, 114, 117, 50, 51, 81, 117, 109, 78, 75, 57, 76, 89, 80, 53, 47, 81, 48, 107, 71, 105, 52, 120, 68, 117, 70, 98, 121, 50, 88, 56, 104, 81, 120, 102, 113, 112, 48, 105, 86, 65, 88, 86, 49, 54, 105, 117, 108, 10, 81, 53, 88, 113, 70, 89, 83, 100, 67, 73, 48, 109, 98, 108, 87, 98, 113, 57, 122, 83, 79, 100, 73, 120, 72, 87, 68, 105, 114, 77, 120, 87, 82, 83, 84, 49, 72, 70, 83, 114, 55, 111, 98, 100, 108, 106, 75, 70, 43, 69, 120, 80, 54, 74, 86, 50, 116, 103, 88, 100, 78, 105, 78, 110, 118, 80, 56, 86, 52, 115, 111, 55, 53, 113, 98, 115, 10, 79, 43, 119, 109, 69, 84, 82, 73, 106, 102, 97, 65, 75, 120, 111, 106, 65, 117, 117, 75, 72, 68, 112, 50, 75, 110, 116, 87, 70, 104, 120, 121, 75, 114, 79, 113, 52, 50, 67, 108, 65, 74, 56, 69, 109, 43, 74, 118, 72, 104, 82, 89, 87, 54, 86, 115, 105, 49, 103, 56, 119, 55, 112, 79, 79, 108, 122, 51, 52, 90, 89, 114, 80, 117, 56, 72, 10, 118, 75, 84, 108, 88, 99, 120, 78, 110, 119, 51, 104, 51, 75, 113, 55, 52, 87, 52, 97, 55, 73, 47, 104, 116, 107, 120, 78, 101, 88, 74, 100, 70, 122, 85, 76, 72, 100, 102, 66, 82, 57, 113, 87, 74, 79, 68, 81, 99, 113, 104, 97, 88, 50, 89, 116, 69, 78, 119, 118, 75, 104, 79, 117, 74, 118, 52, 75, 72, 66, 110, 77, 48, 68, 52, 76, 10, 110, 77, 103, 74, 76, 118, 108, 98, 108, 110, 112, 72, 110, 79, 108, 54, 56, 119, 86, 81, 100, 74, 86, 122, 110, 106, 65, 74, 56, 53, 101, 67, 88, 117, 97, 80, 79, 81, 103, 101, 87, 101, 85, 49, 70, 69, 73, 84, 47, 119, 67, 99, 57, 55, 54, 113, 85, 77, 47, 105, 85, 85, 106, 88, 117, 71, 43, 118, 43, 69, 53, 43, 77, 53, 105, 83, 10, 70, 71, 73, 54, 100, 87, 80, 80, 101, 47, 114, 101, 103, 106, 117, 112, 117, 122, 110, 105, 120, 76, 48, 115, 65, 65, 55, 73, 70, 54, 119, 84, 55, 48, 48, 108, 106, 116, 105, 122, 107, 67, 43, 112, 50, 105, 108, 57, 72, 97, 57, 48, 79, 114, 73, 110, 119, 77, 69, 101, 80, 110, 87, 106, 70, 113, 109, 118, 101, 105, 74, 100, 110, 120, 77, 97, 10, 122, 54, 101, 103, 54, 43, 79, 71, 67, 116, 80, 57, 53, 112, 97, 86, 49, 121, 80, 73, 78, 57, 51, 69, 102, 75, 111, 50, 114, 74, 103, 97, 69, 114, 72, 103, 84, 117, 105, 120, 79, 47, 88, 87, 98, 47, 69, 119, 49, 119, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 10, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 83, 56, 87, 48, 81, 71, 117, 116, 72, 76, 79, 108, 72, 71, 86, 117, 82, 106, 97, 74, 104, 119, 85, 77, 68, 114, 89, 119, 68, 81, 89, 74, 10, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 73, 66, 65, 72, 78, 88, 80, 121, 122, 86, 108, 84, 74, 43, 78, 57, 117, 87, 107, 117, 115, 90, 88, 110, 53, 84, 53, 48, 72, 115, 69, 98, 90, 72, 55, 55, 88, 101, 55, 88, 82, 99, 120, 102, 71, 79, 83, 101, 68, 56, 98, 112, 107, 84, 122, 90, 43, 75, 10, 50, 115, 48, 54, 67, 116, 103, 54, 87, 103, 107, 47, 88, 122, 84, 81, 76, 119, 80, 83, 90, 104, 48, 97, 118, 90, 121, 81, 78, 56, 103, 77, 106, 103, 100, 97, 108, 69, 86, 71, 75, 117, 97, 43, 101, 116, 113, 104, 113, 97, 82, 112, 69, 112, 75, 119, 102, 84, 98, 85, 82, 73, 102, 88, 85, 102, 69, 112, 89, 57, 90, 49, 122, 82, 98, 107, 10, 74, 52, 107, 100, 43, 77, 73, 121, 83, 80, 51, 98, 109, 100, 67, 80, 88, 49, 82, 48, 122, 75, 120, 110, 78, 66, 70, 105, 50, 81, 119, 75, 78, 52, 102, 82, 111, 120, 100, 73, 106, 116, 73, 88, 72, 102, 98, 88, 47, 100, 116, 108, 54, 47, 50, 111, 49, 80, 88, 87, 84, 54, 82, 98, 100, 101, 106, 70, 48, 109, 67, 121, 50, 119, 108, 43, 10, 74, 89, 116, 55, 117, 108, 75, 83, 110, 106, 55, 111, 120, 88, 101, 104, 80, 79, 66, 75, 99, 50, 116, 104, 122, 52, 98, 99, 81, 47, 47, 47, 73, 102, 52, 106, 88, 83, 82, 75, 57, 100, 78, 116, 68, 50, 73, 69, 66, 86, 101, 67, 50, 109, 54, 107, 77, 121, 86, 53, 83, 121, 53, 85, 71, 89, 118, 77, 76, 68, 48, 119, 54, 100, 69, 71, 10, 47, 43, 103, 121, 82, 114, 54, 49, 77, 51, 90, 51, 113, 65, 70, 100, 108, 115, 72, 66, 49, 98, 54, 117, 74, 99, 68, 74, 72, 103, 111, 74, 73, 73, 105, 104, 68, 115, 110, 122, 98, 48, 50, 67, 86, 65, 65, 103, 112, 57, 75, 80, 53, 68, 108, 85, 70, 121, 54, 78, 72, 114, 103, 98, 117, 120, 117, 57, 109, 107, 52, 55, 69, 68, 84, 99, 10, 110, 73, 104, 84, 55, 54, 73, 120, 87, 49, 104, 80, 107, 87, 76, 73, 119, 112, 113, 97, 122, 82, 86, 100, 79, 75, 110, 87, 118, 118, 103, 84, 116, 90, 56, 83, 97, 102, 74, 81, 89, 113, 122, 55, 70, 122, 102, 48, 55, 114, 104, 49, 90, 50, 65, 81, 43, 52, 78, 81, 43, 85, 83, 49, 100, 90, 120, 65, 70, 55, 76, 43, 47, 88, 108, 100, 10, 98, 108, 104, 89, 88, 122, 68, 56, 65, 75, 54, 118, 77, 56, 69, 79, 84, 109, 121, 54, 112, 54, 97, 104, 102, 122, 76, 98, 79, 79, 67, 120, 99, 104, 99, 75, 75, 53, 72, 115, 97, 109, 77, 109, 55, 89, 110, 85, 101, 77, 120, 48, 72, 103, 88, 52, 97, 47, 54, 77, 97, 110, 89, 53, 75, 97, 53, 108, 73, 120, 75, 86, 67, 67, 73, 99, 10, 108, 56, 53, 98, 66, 117, 52, 77, 52, 114, 117, 56, 72, 48, 83, 84, 57, 116, 103, 52, 82, 81, 85, 104, 55, 101, 83, 116, 113, 120, 75, 50, 65, 54, 82, 67, 76, 105, 51, 69, 67, 84, 111, 68, 90, 50, 109, 69, 109, 117, 70, 90, 107, 73, 111, 111, 104, 100, 86, 100, 100, 76, 72, 82, 68, 105, 66, 89, 109, 120, 79, 108, 115, 71, 79, 109, 10, 55, 88, 116, 72, 47, 85, 86, 86, 77, 75, 84, 117, 109, 116, 84, 109, 52, 111, 102, 118, 109, 77, 107, 121, 103, 104, 69, 112, 73, 114, 119, 65, 67, 106, 70, 101, 76, 81, 47, 65, 106, 117, 108, 114, 115, 111, 56, 117, 66, 116, 106, 82, 107, 99, 102, 71, 69, 118, 82, 77, 47, 84, 65, 88, 119, 56, 72, 97, 79, 70, 118, 106, 113, 101, 114, 109, 10, 111, 98, 112, 53, 55, 51, 80, 89, 116, 108, 78, 88, 76, 102, 98, 81, 52, 100, 100, 73, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 66, 117, 121, 112, 97, 115, 115, 32, 67, 108, 97, 115, 115, 32, 50, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 87, 84, 67, 67, 65, 48, 71, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 79, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 79, 84, 122, 69, 100, 77, 66, 115, 71, 65, 49, 85, 69, 67, 103, 119, 85, 10, 81, 110, 86, 53, 99, 71, 70, 122, 99, 121, 66, 66, 85, 121, 48, 53, 79, 68, 77, 120, 78, 106, 77, 122, 77, 106, 99, 120, 73, 68, 65, 101, 66, 103, 78, 86, 66, 65, 77, 77, 70, 48, 74, 49, 101, 88, 66, 104, 99, 51, 77, 103, 81, 50, 120, 104, 99, 51, 77, 103, 77, 105, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 66, 52, 88, 10, 68, 84, 69, 119, 77, 84, 65, 121, 78, 106, 65, 52, 77, 122, 103, 119, 77, 49, 111, 88, 68, 84, 81, 119, 77, 84, 65, 121, 78, 106, 65, 52, 77, 122, 103, 119, 77, 49, 111, 119, 84, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 84, 107, 56, 120, 72, 84, 65, 98, 66, 103, 78, 86, 66, 65, 111, 77, 70, 69, 74, 49, 10, 101, 88, 66, 104, 99, 51, 77, 103, 81, 86, 77, 116, 79, 84, 103, 122, 77, 84, 89, 122, 77, 122, 73, 51, 77, 83, 65, 119, 72, 103, 89, 68, 86, 81, 81, 68, 68, 66, 100, 67, 100, 88, 108, 119, 89, 88, 78, 122, 73, 69, 78, 115, 89, 88, 78, 122, 73, 68, 73, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 84, 67, 67, 65, 105, 73, 119, 10, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 78, 102, 72, 88, 118, 102, 66, 66, 57, 82, 51, 43, 48, 77, 104, 57, 80, 84, 49, 97, 101, 84, 117, 77, 103, 72, 98, 111, 52, 89, 102, 53, 70, 107, 78, 117, 117, 100, 49, 10, 103, 49, 76, 114, 54, 104, 120, 104, 70, 85, 105, 55, 72, 81, 102, 75, 106, 75, 54, 119, 51, 74, 97, 100, 54, 115, 78, 103, 107, 111, 97, 67, 75, 72, 79, 99, 86, 103, 98, 47, 83, 50, 84, 119, 68, 67, 111, 51, 83, 98, 88, 108, 122, 119, 120, 56, 55, 118, 70, 75, 117, 51, 77, 119, 90, 102, 80, 86, 76, 52, 79, 50, 102, 117, 80, 110, 10, 57, 90, 54, 114, 89, 80, 110, 84, 56, 90, 50, 83, 100, 73, 114, 107, 72, 74, 97, 115, 87, 52, 68, 112, 116, 102, 81, 120, 104, 54, 78, 82, 47, 77, 100, 43, 111, 87, 43, 79, 85, 51, 102, 85, 108, 56, 70, 86, 77, 53, 73, 43, 71, 67, 57, 49, 49, 75, 50, 71, 83, 99, 117, 86, 114, 49, 81, 71, 98, 78, 103, 71, 69, 52, 49, 98, 10, 47, 43, 69, 109, 71, 86, 110, 65, 74, 76, 113, 66, 99, 88, 109, 81, 82, 70, 66, 111, 74, 74, 82, 102, 117, 76, 77, 82, 56, 83, 108, 66, 89, 97, 78, 66, 121, 121, 77, 50, 49, 99, 72, 120, 77, 108, 65, 81, 84, 110, 47, 48, 104, 112, 80, 115, 104, 78, 79, 79, 118, 69, 117, 47, 88, 65, 70, 79, 66, 122, 51, 99, 70, 73, 113, 85, 10, 67, 113, 84, 113, 99, 47, 115, 76, 85, 101, 103, 84, 66, 120, 106, 54, 68, 118, 69, 114, 48, 86, 81, 86, 102, 84, 122, 104, 57, 55, 81, 90, 81, 109, 100, 105, 88, 110, 102, 103, 111, 108, 88, 115, 116, 116, 108, 112, 70, 57, 85, 54, 114, 48, 84, 116, 83, 115, 87, 101, 53, 72, 111, 110, 102, 79, 86, 49, 49, 54, 114, 76, 74, 101, 102, 102, 10, 97, 119, 114, 98, 68, 48, 50, 84, 84, 113, 105, 103, 122, 88, 115, 117, 56, 108, 107, 66, 97, 114, 99, 78, 117, 65, 101, 66, 102, 111, 115, 52, 71, 122, 106, 109, 67, 108, 101, 90, 80, 101, 52, 104, 54, 75, 80, 49, 68, 66, 98, 100, 105, 43, 119, 48, 106, 112, 119, 113, 72, 65, 65, 86, 70, 52, 49, 111, 103, 57, 74, 119, 110, 120, 103, 73, 10, 122, 82, 70, 111, 49, 99, 108, 114, 85, 115, 51, 69, 82, 111, 47, 99, 116, 102, 80, 89, 86, 51, 77, 101, 54, 90, 81, 53, 66, 76, 47, 84, 51, 106, 106, 101, 116, 70, 80, 115, 97, 82, 121, 105, 102, 115, 83, 80, 53, 66, 116, 119, 114, 102, 75, 105, 43, 102, 118, 51, 70, 109, 82, 109, 97, 90, 57, 74, 85, 97, 76, 105, 70, 82, 104, 110, 10, 66, 107, 112, 47, 49, 87, 121, 49, 84, 98, 77, 122, 52, 71, 72, 114, 88, 98, 55, 112, 109, 65, 56, 121, 49, 120, 49, 76, 80, 67, 53, 97, 65, 86, 75, 82, 67, 102, 76, 102, 54, 111, 51, 89, 66, 107, 66, 106, 113, 104, 72, 107, 47, 115, 77, 51, 110, 104, 82, 83, 80, 47, 84, 105, 122, 80, 74, 104, 107, 57, 72, 57, 90, 50, 118, 88, 10, 85, 113, 54, 47, 97, 75, 116, 65, 81, 54, 66, 88, 78, 86, 78, 52, 56, 70, 80, 52, 89, 85, 73, 72, 90, 77, 98, 88, 98, 53, 116, 77, 79, 65, 49, 106, 114, 71, 75, 118, 78, 111, 117, 105, 99, 119, 111, 78, 57, 83, 71, 57, 100, 75, 112, 78, 54, 110, 73, 68, 83, 100, 118, 72, 88, 120, 49, 105, 89, 56, 102, 57, 51, 90, 72, 115, 10, 77, 43, 55, 49, 98, 98, 82, 117, 77, 71, 106, 101, 121, 78, 89, 109, 115, 72, 86, 101, 101, 55, 81, 72, 73, 74, 105, 104, 100, 106, 75, 52, 84, 87, 120, 80, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 10, 86, 82, 48, 79, 66, 66, 89, 69, 70, 77, 109, 65, 100, 43, 66, 105, 107, 111, 76, 49, 82, 112, 122, 122, 117, 118, 100, 77, 119, 57, 54, 52, 111, 54, 48, 53, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 10, 65, 65, 79, 67, 65, 103, 69, 65, 85, 49, 56, 104, 57, 98, 113, 119, 79, 108, 73, 53, 76, 74, 75, 119, 98, 65, 68, 74, 55, 56, 52, 103, 55, 119, 98, 121, 108, 112, 55, 112, 112, 72, 82, 47, 101, 104, 98, 56, 116, 47, 87, 50, 43, 120, 85, 98, 80, 54, 117, 109, 119, 72, 74, 100, 69, 76, 70, 120, 55, 114, 120, 80, 52, 54, 50, 115, 10, 65, 50, 48, 117, 99, 83, 54, 118, 120, 79, 79, 116, 111, 55, 48, 77, 69, 97, 101, 48, 47, 48, 113, 121, 101, 120, 65, 81, 72, 54, 100, 88, 81, 98, 76, 65, 114, 118, 81, 115, 87, 100, 90, 72, 69, 73, 106, 122, 73, 86, 69, 112, 77, 77, 112, 103, 104, 113, 57, 71, 113, 120, 51, 116, 79, 108, 117, 119, 108, 78, 53, 69, 52, 48, 69, 73, 10, 111, 115, 72, 115, 72, 100, 98, 57, 84, 55, 98, 87, 82, 57, 65, 85, 67, 56, 114, 109, 121, 114, 86, 55, 100, 51, 53, 66, 72, 49, 54, 68, 120, 55, 97, 77, 79, 90, 97, 119, 80, 53, 97, 66, 81, 87, 57, 103, 107, 79, 76, 111, 43, 102, 115, 105, 99, 100, 108, 57, 115, 122, 49, 71, 118, 55, 83, 69, 114, 53, 65, 99, 68, 52, 56, 83, 10, 97, 113, 47, 118, 55, 104, 53, 54, 114, 103, 74, 75, 105, 104, 99, 114, 100, 118, 54, 115, 86, 73, 107, 107, 76, 69, 56, 47, 116, 114, 75, 110, 84, 111, 121, 111, 107, 90, 102, 55, 75, 99, 90, 55, 88, 67, 50, 53, 121, 50, 97, 50, 116, 54, 104, 98, 69, 108, 71, 70, 116, 81, 108, 43, 89, 110, 104, 119, 47, 113, 108, 113, 89, 76, 89, 100, 10, 68, 110, 107, 77, 47, 99, 114, 113, 74, 73, 66, 121, 119, 53, 99, 47, 56, 110, 101, 114, 81, 121, 73, 75, 120, 43, 117, 50, 68, 73, 83, 67, 76, 73, 66, 114, 81, 89, 111, 73, 119, 79, 117, 108, 97, 57, 43, 90, 69, 115, 117, 75, 49, 86, 54, 65, 68, 74, 72, 103, 74, 103, 103, 50, 83, 77, 88, 54, 79, 66, 69, 49, 47, 121, 87, 68, 10, 76, 102, 74, 54, 118, 57, 114, 57, 106, 118, 54, 108, 121, 48, 85, 115, 72, 56, 83, 73, 85, 54, 53, 51, 68, 116, 109, 97, 100, 115, 87, 79, 76, 66, 50, 106, 117, 116, 88, 115, 77, 113, 55, 65, 113, 113, 122, 51, 48, 88, 112, 78, 54, 57, 81, 72, 52, 107, 106, 51, 73, 111, 54, 119, 112, 74, 57, 113, 122, 111, 54, 121, 115, 109, 68, 48, 10, 111, 121, 76, 81, 73, 43, 117, 85, 87, 110, 112, 112, 51, 81, 43, 47, 81, 70, 101, 115, 97, 49, 108, 81, 50, 97, 79, 90, 52, 87, 55, 43, 106, 81, 70, 53, 74, 121, 77, 86, 51, 112, 75, 100, 101, 119, 108, 78, 87, 117, 100, 76, 83, 68, 66, 97, 71, 79, 89, 75, 98, 101, 97, 80, 52, 78, 75, 55, 53, 116, 57, 56, 98, 105, 71, 67, 10, 119, 87, 103, 53, 84, 98, 83, 89, 87, 71, 90, 105, 122, 69, 113, 81, 88, 115, 80, 54, 74, 119, 83, 120, 101, 82, 86, 48, 109, 99, 121, 43, 114, 83, 68, 101, 74, 109, 65, 99, 54, 49, 90, 82, 112, 113, 80, 113, 53, 75, 77, 47, 112, 47, 57, 104, 51, 80, 70, 97, 84, 87, 119, 121, 73, 48, 80, 117, 114, 75, 106, 117, 55, 107, 111, 83, 10, 67, 84, 120, 100, 99, 99, 75, 43, 101, 102, 114, 67, 104, 50, 103, 100, 67, 47, 49, 99, 97, 99, 119, 71, 48, 74, 112, 57, 86, 74, 107, 113, 121, 84, 107, 97, 71, 97, 57, 76, 75, 107, 80, 122, 89, 49, 49, 97, 87, 79, 73, 118, 52, 120, 51, 107, 113, 100, 98, 81, 67, 116, 67, 101, 118, 57, 101, 66, 67, 102, 72, 74, 120, 121, 89, 78, 10, 114, 74, 103, 87, 86, 113, 65, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 66, 117, 121, 112, 97, 115, 115, 32, 67, 108, 97, 115, 115, 32, 51, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 87, 84, 67, 67, 65, 48, 71, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 79, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 79, 84, 122, 69, 100, 77, 66, 115, 71, 65, 49, 85, 69, 67, 103, 119, 85, 10, 81, 110, 86, 53, 99, 71, 70, 122, 99, 121, 66, 66, 85, 121, 48, 53, 79, 68, 77, 120, 78, 106, 77, 122, 77, 106, 99, 120, 73, 68, 65, 101, 66, 103, 78, 86, 66, 65, 77, 77, 70, 48, 74, 49, 101, 88, 66, 104, 99, 51, 77, 103, 81, 50, 120, 104, 99, 51, 77, 103, 77, 121, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 66, 52, 88, 10, 68, 84, 69, 119, 77, 84, 65, 121, 78, 106, 65, 52, 77, 106, 103, 49, 79, 70, 111, 88, 68, 84, 81, 119, 77, 84, 65, 121, 78, 106, 65, 52, 77, 106, 103, 49, 79, 70, 111, 119, 84, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 84, 107, 56, 120, 72, 84, 65, 98, 66, 103, 78, 86, 66, 65, 111, 77, 70, 69, 74, 49, 10, 101, 88, 66, 104, 99, 51, 77, 103, 81, 86, 77, 116, 79, 84, 103, 122, 77, 84, 89, 122, 77, 122, 73, 51, 77, 83, 65, 119, 72, 103, 89, 68, 86, 81, 81, 68, 68, 66, 100, 67, 100, 88, 108, 119, 89, 88, 78, 122, 73, 69, 78, 115, 89, 88, 78, 122, 73, 68, 77, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 84, 67, 67, 65, 105, 73, 119, 10, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 75, 88, 97, 67, 112, 85, 87, 85, 79, 79, 86, 56, 108, 54, 100, 100, 106, 69, 71, 77, 110, 113, 98, 56, 82, 66, 50, 117, 65, 67, 97, 116, 86, 73, 50, 122, 83, 82, 72, 10, 115, 74, 56, 89, 90, 76, 121, 97, 57, 118, 114, 86, 101, 100, 105, 81, 89, 107, 119, 105, 76, 57, 52, 52, 80, 100, 98, 103, 113, 79, 107, 99, 76, 78, 116, 52, 69, 101, 109, 79, 97, 70, 69, 86, 99, 115, 102, 122, 77, 52, 102, 107, 111, 70, 48, 76, 88, 79, 66, 88, 66, 121, 111, 119, 57, 99, 51, 69, 78, 51, 99, 111, 84, 82, 105, 82, 10, 53, 114, 47, 86, 85, 118, 49, 120, 76, 88, 65, 43, 53, 56, 98, 69, 105, 117, 80, 119, 75, 65, 118, 48, 100, 112, 105, 104, 105, 52, 100, 86, 115, 106, 111, 84, 47, 76, 99, 43, 74, 122, 101, 79, 73, 117, 79, 111, 84, 121, 114, 118, 89, 76, 115, 57, 116, 122, 110, 68, 68, 103, 70, 72, 109, 86, 48, 83, 84, 57, 116, 68, 43, 108, 101, 104, 10, 55, 102, 109, 100, 118, 104, 70, 72, 74, 108, 115, 84, 109, 75, 116, 100, 70, 111, 113, 119, 78, 120, 120, 88, 110, 85, 88, 47, 105, 74, 89, 50, 118, 55, 118, 75, 66, 51, 116, 118, 104, 50, 80, 88, 48, 68, 74, 113, 49, 108, 49, 115, 68, 80, 71, 122, 98, 106, 110, 105, 97, 122, 69, 117, 79, 81, 65, 110, 70, 78, 52, 52, 119, 79, 119, 90, 10, 90, 111, 89, 83, 54, 74, 49, 121, 70, 104, 78, 107, 85, 115, 101, 112, 78, 120, 122, 57, 103, 106, 68, 116, 104, 66, 103, 100, 57, 75, 53, 99, 47, 51, 65, 84, 65, 79, 117, 120, 57, 84, 78, 54, 83, 57, 90, 86, 43, 65, 87, 78, 83, 50, 109, 119, 57, 98, 77, 111, 78, 108, 119, 85, 120, 70, 70, 122, 84, 87, 115, 76, 56, 84, 81, 72, 10, 50, 120, 99, 53, 49, 57, 119, 111, 101, 50, 118, 49, 110, 47, 77, 117, 119, 85, 56, 88, 75, 104, 68, 122, 122, 77, 114, 111, 54, 47, 49, 114, 113, 121, 54, 97, 110, 121, 50, 67, 98, 103, 84, 85, 85, 103, 71, 84, 76, 84, 50, 71, 47, 72, 55, 56, 51, 43, 57, 67, 72, 97, 90, 114, 55, 55, 107, 103, 120, 118, 101, 57, 111, 75, 101, 86, 10, 47, 97, 102, 109, 105, 83, 84, 89, 122, 73, 119, 48, 98, 79, 73, 106, 76, 57, 107, 83, 71, 105, 71, 53, 86, 90, 70, 118, 67, 53, 70, 53, 71, 81, 121, 116, 81, 73, 103, 76, 99, 79, 74, 54, 48, 103, 55, 89, 97, 69, 105, 55, 103, 104, 77, 53, 69, 70, 106, 112, 50, 67, 111, 72, 120, 104, 76, 98, 87, 78, 118, 83, 79, 49, 85, 81, 10, 82, 119, 85, 86, 90, 50, 74, 43, 71, 71, 79, 109, 82, 106, 56, 74, 68, 108, 81, 121, 88, 114, 56, 78, 89, 110, 111, 110, 55, 52, 68, 111, 50, 57, 108, 76, 66, 108, 111, 51, 87, 105, 88, 81, 67, 66, 74, 51, 49, 71, 56, 74, 85, 74, 99, 57, 121, 66, 51, 68, 51, 52, 120, 70, 77, 70, 98, 71, 48, 50, 83, 114, 90, 118, 80, 65, 10, 88, 112, 97, 99, 119, 56, 84, 118, 119, 51, 120, 114, 105, 122, 112, 53, 102, 55, 78, 74, 122, 122, 51, 105, 105, 90, 43, 103, 77, 69, 117, 70, 117, 90, 121, 85, 74, 72, 109, 80, 102, 87, 117, 112, 82, 87, 103, 80, 75, 57, 68, 120, 50, 104, 122, 76, 97, 98, 106, 75, 83, 87, 74, 116, 121, 78, 66, 106, 89, 116, 49, 103, 68, 49, 105, 113, 10, 106, 54, 71, 56, 66, 97, 86, 109, 111, 115, 56, 98, 100, 114, 75, 69, 90, 76, 70, 77, 79, 86, 76, 65, 77, 76, 114, 119, 106, 69, 115, 67, 115, 76, 97, 51, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 10, 86, 82, 48, 79, 66, 66, 89, 69, 70, 69, 101, 52, 122, 102, 47, 108, 98, 43, 55, 52, 115, 117, 119, 118, 84, 103, 55, 53, 74, 98, 67, 79, 80, 71, 118, 68, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 10, 65, 65, 79, 67, 65, 103, 69, 65, 65, 67, 65, 106, 81, 84, 85, 69, 107, 77, 74, 65, 89, 109, 68, 118, 52, 106, 86, 77, 49, 122, 43, 115, 52, 106, 83, 81, 117, 75, 70, 118, 100, 118, 111, 87, 70, 113, 82, 73, 78, 121, 122, 112, 107, 77, 76, 121, 80, 80, 103, 75, 110, 57, 105, 66, 53, 98, 116, 98, 50, 105, 85, 115, 112, 75, 100, 86, 10, 99, 83, 81, 121, 57, 115, 103, 76, 56, 114, 120, 113, 43, 74, 79, 115, 115, 103, 102, 67, 88, 53, 47, 98, 122, 77, 105, 75, 113, 114, 53, 113, 98, 43, 70, 74, 69, 77, 119, 120, 49, 52, 67, 55, 117, 56, 106, 89, 111, 103, 53, 107, 86, 43, 113, 105, 57, 99, 75, 112, 77, 82, 88, 83, 73, 71, 114, 115, 47, 67, 73, 66, 75, 77, 43, 71, 10, 117, 73, 65, 101, 113, 99, 119, 82, 112, 84, 122, 121, 70, 114, 78, 72, 110, 102, 122, 83, 103, 67, 72, 69, 121, 57, 66, 72, 99, 69, 71, 104, 121, 111, 77, 90, 67, 67, 120, 116, 56, 108, 49, 51, 110, 73, 111, 85, 69, 57, 81, 50, 72, 74, 76, 119, 53, 81, 89, 51, 51, 75, 98, 109, 107, 74, 115, 52, 106, 49, 120, 114, 71, 48, 97, 71, 10, 81, 48, 74, 102, 80, 103, 69, 72, 85, 49, 82, 100, 90, 88, 51, 51, 105, 110, 79, 104, 109, 108, 82, 97, 72, 121, 108, 68, 70, 67, 102, 67, 104, 81, 43, 49, 105, 72, 115, 97, 79, 53, 83, 51, 72, 87, 67, 110, 116, 90, 122, 110, 75, 87, 108, 88, 87, 112, 117, 84, 101, 107, 77, 119, 71, 119, 80, 88, 89, 115, 104, 65, 112, 113, 114, 56, 10, 90, 79, 82, 75, 49, 53, 70, 84, 65, 97, 103, 103, 105, 71, 54, 99, 88, 48, 83, 53, 121, 50, 67, 66, 78, 79, 120, 118, 48, 51, 51, 97, 83, 70, 47, 114, 116, 74, 67, 56, 76, 97, 107, 99, 67, 54, 119, 99, 49, 97, 74, 111, 73, 73, 65, 69, 49, 118, 121, 120, 106, 121, 43, 55, 83, 106, 69, 78, 83, 111, 89, 99, 54, 43, 73, 50, 10, 75, 83, 98, 49, 50, 116, 106, 69, 56, 110, 86, 104, 122, 51, 54, 117, 100, 109, 78, 75, 101, 107, 66, 108, 107, 52, 102, 52, 72, 111, 67, 77, 104, 117, 87, 71, 49, 111, 56, 79, 47, 70, 77, 115, 89, 79, 103, 87, 89, 82, 113, 105, 80, 107, 78, 55, 122, 84, 108, 103, 86, 71, 114, 49, 56, 111, 107, 109, 65, 87, 105, 68, 83, 75, 73, 122, 10, 54, 77, 107, 69, 107, 98, 73, 82, 78, 66, 69, 43, 54, 116, 66, 68, 71, 82, 56, 68, 107, 53, 65, 77, 47, 49, 69, 57, 86, 47, 82, 66, 98, 117, 72, 76, 111, 76, 55, 114, 121, 87, 80, 78, 98, 99, 122, 107, 43, 68, 97, 113, 97, 74, 51, 116, 118, 86, 50, 88, 99, 69, 81, 78, 116, 103, 52, 49, 51, 79, 69, 77, 88, 98, 117, 103, 10, 85, 90, 84, 76, 102, 104, 98, 114, 69, 83, 43, 106, 107, 107, 88, 73, 84, 72, 72, 90, 118, 77, 109, 90, 85, 108, 100, 71, 76, 49, 68, 80, 118, 84, 86, 112, 57, 68, 48, 86, 122, 103, 97, 108, 76, 65, 56, 43, 57, 111, 71, 54, 108, 76, 118, 68, 117, 55, 57, 108, 101, 78, 75, 71, 101, 102, 57, 74, 79, 120, 113, 68, 68, 80, 68, 101, 10, 101, 79, 122, 73, 56, 107, 49, 77, 71, 116, 54, 67, 75, 102, 106, 66, 87, 116, 114, 116, 55, 117, 89, 110, 88, 117, 104, 70, 48, 74, 48, 99, 85, 97, 104, 111, 113, 48, 84, 106, 48, 73, 116, 113, 52, 47, 103, 55, 117, 57, 120, 78, 49, 50, 84, 121, 85, 98, 55, 109, 113, 113, 116, 97, 54, 84, 72, 117, 66, 114, 120, 122, 118, 120, 78, 105, 10, 67, 112, 47, 72, 117, 90, 99, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 84, 45, 84, 101, 108, 101, 83, 101, 99, 32, 71, 108, 111, 98, 97, 108, 82, 111, 111, 116, 32, 67, 108, 97, 115, 115, 32, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 119, 122, 67, 67, 65, 113, 117, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 66, 103, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 69, 85, 120, 75, 122, 65, 112, 66, 103, 78, 86, 66, 65, 111, 77, 10, 73, 108, 81, 116, 85, 51, 108, 122, 100, 71, 86, 116, 99, 121, 66, 70, 98, 110, 82, 108, 99, 110, 66, 121, 97, 88, 78, 108, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 86, 122, 73, 69, 100, 116, 89, 107, 103, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 115, 77, 70, 108, 81, 116, 85, 51, 108, 122, 100, 71, 86, 116, 99, 121, 66, 85, 10, 99, 110, 86, 122, 100, 67, 66, 68, 90, 87, 53, 48, 90, 88, 73, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 77, 77, 72, 70, 81, 116, 86, 71, 86, 115, 90, 86, 78, 108, 89, 121, 66, 72, 98, 71, 57, 105, 89, 87, 120, 83, 98, 50, 57, 48, 73, 69, 78, 115, 89, 88, 78, 122, 73, 68, 77, 119, 72, 104, 99, 78, 77, 68, 103, 120, 10, 77, 68, 65, 120, 77, 84, 65, 121, 79, 84, 85, 50, 87, 104, 99, 78, 77, 122, 77, 120, 77, 68, 65, 120, 77, 106, 77, 49, 79, 84, 85, 53, 87, 106, 67, 66, 103, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 69, 85, 120, 75, 122, 65, 112, 66, 103, 78, 86, 66, 65, 111, 77, 73, 108, 81, 116, 85, 51, 108, 122, 10, 100, 71, 86, 116, 99, 121, 66, 70, 98, 110, 82, 108, 99, 110, 66, 121, 97, 88, 78, 108, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 86, 122, 73, 69, 100, 116, 89, 107, 103, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 115, 77, 70, 108, 81, 116, 85, 51, 108, 122, 100, 71, 86, 116, 99, 121, 66, 85, 99, 110, 86, 122, 100, 67, 66, 68, 10, 90, 87, 53, 48, 90, 88, 73, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 77, 77, 72, 70, 81, 116, 86, 71, 86, 115, 90, 86, 78, 108, 89, 121, 66, 72, 98, 71, 57, 105, 89, 87, 120, 83, 98, 50, 57, 48, 73, 69, 78, 115, 89, 88, 78, 122, 73, 68, 77, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 10, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 57, 100, 90, 80, 119, 89, 105, 74, 118, 74, 75, 55, 103, 101, 110, 97, 115, 102, 98, 51, 90, 74, 78, 87, 52, 116, 47, 122, 78, 56, 69, 76, 103, 54, 51, 105, 73, 86, 108, 54, 98, 109, 108, 81, 100, 84, 81, 121, 75, 10, 57, 116, 80, 80, 99, 80, 82, 83, 116, 100, 105, 84, 66, 79, 78, 71, 104, 110, 70, 66, 83, 105, 118, 119, 75, 105, 120, 86, 65, 57, 90, 73, 119, 43, 65, 53, 79, 79, 51, 121, 88, 68, 119, 47, 82, 76, 121, 84, 80, 87, 71, 114, 84, 115, 48, 78, 118, 118, 65, 103, 74, 49, 103, 79, 82, 72, 56, 69, 71, 111, 101, 108, 49, 53, 89, 85, 10, 78, 112, 68, 81, 83, 88, 117, 104, 100, 102, 115, 97, 97, 51, 79, 120, 43, 77, 54, 112, 67, 83, 122, 121, 85, 57, 88, 68, 70, 69, 83, 52, 104, 113, 88, 50, 105, 121, 115, 53, 50, 113, 77, 122, 86, 78, 110, 54, 99, 104, 114, 51, 73, 104, 85, 99, 105, 74, 70, 114, 102, 50, 98, 108, 119, 50, 113, 65, 115, 67, 84, 122, 51, 52, 90, 70, 10, 105, 80, 48, 90, 102, 51, 87, 72, 72, 120, 43, 120, 71, 119, 112, 122, 74, 70, 117, 53, 90, 101, 65, 115, 86, 77, 104, 103, 48, 50, 89, 88, 80, 43, 72, 77, 86, 68, 78, 122, 107, 81, 73, 54, 112, 110, 57, 55, 100, 106, 109, 105, 72, 53, 97, 50, 79, 75, 54, 49, 121, 74, 78, 48, 72, 90, 54, 53, 116, 79, 86, 103, 110, 83, 57, 87, 10, 48, 101, 68, 114, 88, 108, 116, 77, 69, 110, 65, 77, 98, 69, 81, 103, 113, 120, 72, 89, 57, 66, 110, 50, 48, 112, 120, 83, 78, 43, 102, 54, 116, 115, 73, 120, 79, 48, 114, 85, 70, 74, 109, 116, 120, 120, 114, 49, 88, 86, 47, 54, 66, 55, 104, 56, 68, 82, 47, 87, 103, 120, 54, 122, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 10, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 83, 49, 65, 47, 100, 50, 79, 50, 71, 67, 97, 104, 75, 113, 71, 70, 80, 114, 10, 65, 121, 71, 85, 118, 47, 55, 79, 121, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, 67, 65, 81, 69, 65, 86, 106, 51, 118, 108, 78, 87, 57, 50, 110, 79, 121, 87, 76, 54, 117, 107, 75, 50, 89, 74, 53, 102, 43, 65, 98, 71, 119, 85, 103, 67, 52, 84, 101, 81, 98, 73, 88, 81, 98, 10, 102, 115, 68, 117, 88, 109, 107, 113, 74, 97, 57, 99, 49, 104, 51, 97, 48, 110, 110, 74, 56, 53, 99, 112, 52, 73, 97, 72, 51, 103, 82, 90, 68, 47, 70, 90, 49, 71, 83, 70, 83, 53, 109, 118, 74, 81, 81, 101, 121, 85, 97, 112, 108, 57, 54, 67, 115, 104, 116, 119, 110, 53, 122, 50, 114, 51, 69, 120, 51, 88, 115, 70, 112, 83, 122, 84, 10, 117, 99, 112, 72, 57, 115, 114, 121, 57, 117, 101, 116, 117, 85, 103, 47, 118, 66, 97, 51, 119, 87, 51, 48, 54, 103, 109, 118, 55, 80, 79, 49, 53, 119, 87, 101, 112, 104, 54, 75, 85, 49, 72, 87, 107, 52, 72, 77, 100, 74, 80, 50, 117, 100, 113, 109, 74, 81, 86, 48, 101, 86, 112, 43, 81, 68, 54, 67, 83, 121, 89, 82, 77, 71, 55, 104, 10, 80, 48, 72, 72, 82, 119, 65, 49, 49, 102, 88, 84, 57, 49, 81, 43, 103, 84, 51, 97, 83, 87, 113, 97, 115, 43, 56, 81, 80, 101, 98, 114, 98, 57, 72, 73, 73, 107, 102, 76, 122, 77, 56, 66, 77, 90, 76, 90, 71, 79, 77, 105, 118, 103, 107, 101, 71, 106, 53, 97, 115, 117, 82, 114, 68, 70, 82, 54, 102, 85, 78, 79, 117, 73, 109, 108, 10, 101, 57, 101, 105, 80, 90, 97, 71, 122, 80, 73, 109, 78, 67, 49, 113, 107, 112, 50, 97, 71, 116, 65, 119, 52, 108, 49, 79, 66, 76, 66, 102, 105, 121, 66, 43, 100, 56, 69, 57, 108, 89, 76, 82, 82, 112, 111, 55, 80, 72, 105, 52, 98, 54, 72, 81, 68, 87, 83, 105, 101, 66, 52, 112, 84, 112, 80, 68, 112, 70, 81, 85, 87, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 69, 69, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 67, 101, 110, 116, 114, 101, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 65, 122, 67, 67, 65, 117, 117, 103, 65, 119, 73, 66, 65, 103, 73, 81, 86, 73, 68, 53, 111, 72, 80, 116, 80, 119, 66, 77, 121, 111, 110, 89, 52, 51, 72, 109, 83, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 49, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 70, 82, 84, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 67, 103, 119, 90, 81, 86, 77, 103, 85, 50, 86, 121, 100, 71, 108, 109, 97, 88, 82, 122, 90, 87, 86, 121, 97, 87, 49, 112, 99, 50, 116, 108, 99, 50, 116, 49, 99, 122, 69, 111, 77, 67, 89, 71, 65, 49, 85, 69, 65, 119, 119, 102, 82, 85, 85, 103, 81, 50, 86, 121, 10, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 68, 90, 87, 53, 48, 99, 109, 85, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 84, 69, 89, 77, 66, 89, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 74, 65, 82, 89, 74, 99, 71, 116, 112, 81, 72, 78, 114, 76, 109, 86, 108, 77, 67, 73, 89, 68, 122, 73, 119, 10, 77, 84, 65, 120, 77, 68, 77, 119, 77, 84, 65, 120, 77, 68, 77, 119, 87, 104, 103, 80, 77, 106, 65, 122, 77, 68, 69, 121, 77, 84, 99, 121, 77, 122, 85, 53, 78, 84, 108, 97, 77, 72, 85, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 86, 70, 77, 83, 73, 119, 73, 65, 89, 68, 86, 81, 81, 75, 68, 66, 108, 66, 10, 85, 121, 66, 84, 90, 88, 74, 48, 97, 87, 90, 112, 100, 72, 78, 108, 90, 88, 74, 112, 98, 87, 108, 122, 97, 50, 86, 122, 97, 51, 86, 122, 77, 83, 103, 119, 74, 103, 89, 68, 86, 81, 81, 68, 68, 66, 57, 70, 82, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 78, 108, 98, 110, 82, 121, 10, 90, 83, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 82, 103, 119, 70, 103, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 107, 66, 70, 103, 108, 119, 97, 50, 108, 65, 99, 50, 115, 117, 90, 87, 85, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 10, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 68, 73, 73, 77, 68, 115, 52, 77, 86, 76, 113, 119, 100, 52, 108, 102, 78, 69, 55, 118, 115, 76, 68, 80, 57, 48, 106, 109, 71, 55, 115, 87, 76, 113, 73, 57, 105, 114, 111, 87, 85, 121, 101, 117, 117, 79, 70, 48, 43, 87, 50, 65, 112, 55, 107, 97, 74, 106, 98, 77, 101, 77, 10, 84, 67, 53, 53, 118, 54, 107, 70, 47, 71, 108, 99, 108, 89, 49, 105, 43, 98, 108, 119, 55, 99, 78, 82, 102, 100, 67, 84, 53, 109, 122, 114, 77, 69, 118, 104, 118, 72, 50, 47, 85, 112, 118, 79, 98, 110, 116, 108, 56, 106, 105, 120, 119, 75, 73, 121, 55, 50, 75, 121, 97, 79, 66, 104, 85, 56, 69, 50, 108, 102, 47, 115, 108, 76, 111, 50, 10, 114, 112, 119, 99, 112, 122, 73, 80, 53, 88, 121, 48, 120, 109, 57, 48, 47, 88, 115, 89, 54, 75, 120, 88, 55, 81, 89, 103, 83, 122, 73, 119, 87, 70, 118, 57, 122, 97, 106, 109, 111, 102, 120, 119, 118, 73, 54, 83, 99, 57, 117, 88, 112, 51, 119, 104, 114, 106, 51, 66, 57, 85, 105, 72, 98, 67, 101, 57, 110, 121, 86, 48, 103, 86, 87, 119, 10, 57, 51, 88, 50, 80, 97, 82, 107, 97, 57, 90, 80, 53, 56, 53, 65, 114, 81, 47, 100, 77, 116, 79, 56, 105, 104, 74, 84, 109, 77, 109, 74, 43, 120, 65, 100, 84, 88, 55, 78, 102, 104, 57, 87, 68, 83, 70, 119, 104, 102, 89, 103, 103, 120, 47, 50, 117, 104, 56, 69, 106, 43, 112, 51, 105, 68, 88, 69, 47, 43, 112, 79, 111, 89, 116, 78, 10, 80, 50, 77, 98, 82, 77, 78, 69, 49, 67, 86, 50, 121, 114, 101, 78, 49, 120, 53, 75, 90, 109, 84, 78, 88, 77, 87, 99, 103, 43, 72, 67, 67, 73, 105, 97, 55, 69, 54, 106, 56, 84, 52, 99, 76, 78, 108, 115, 72, 97, 70, 76, 65, 103, 77, 66, 65, 65, 71, 106, 103, 89, 111, 119, 103, 89, 99, 119, 68, 119, 89, 68, 86, 82, 48, 84, 10, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 66, 76, 121, 87, 106, 55, 113, 86, 104, 121, 47, 122, 81, 97, 115, 56, 102, 69, 108, 121, 97, 108, 76, 49, 66, 83, 90, 10, 77, 69, 85, 71, 65, 49, 85, 100, 74, 81, 81, 43, 77, 68, 119, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 77, 67, 66, 103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 68, 65, 81, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 119, 77, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 77, 69, 66, 103, 103, 114, 66, 103, 69, 70, 10, 66, 81, 99, 68, 67, 65, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 119, 107, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 72, 118, 50, 53, 77, 65, 78, 113, 104, 108, 72, 116, 48, 49, 88, 111, 47, 54, 116, 117, 55, 70, 113, 49, 81, 43, 101, 50, 43, 82, 106, 10, 120, 89, 54, 104, 85, 70, 97, 84, 108, 114, 103, 52, 119, 67, 81, 105, 90, 114, 120, 84, 70, 71, 71, 86, 118, 57, 68, 72, 75, 112, 89, 53, 80, 51, 48, 111, 115, 120, 66, 65, 73, 87, 114, 69, 114, 55, 66, 83, 100, 120, 106, 104, 108, 116, 104, 87, 88, 101, 80, 100, 78, 108, 52, 100, 112, 49, 66, 85, 111, 77, 85, 113, 53, 75, 113, 77, 10, 108, 73, 112, 80, 110, 84, 88, 47, 100, 113, 81, 71, 69, 53, 71, 105, 111, 110, 48, 65, 82, 68, 57, 86, 48, 52, 73, 56, 71, 116, 86, 98, 118, 70, 90, 77, 73, 105, 53, 71, 81, 52, 111, 107, 81, 67, 51, 122, 69, 114, 103, 55, 99, 66, 113, 107, 108, 114, 107, 97, 114, 52, 100, 66, 71, 109, 111, 89, 68, 81, 90, 80, 120, 122, 53, 117, 10, 117, 83, 108, 78, 68, 85, 109, 74, 69, 89, 99, 121, 87, 43, 90, 76, 66, 77, 106, 107, 88, 79, 90, 48, 99, 53, 82, 100, 70, 112, 103, 84, 108, 102, 55, 55, 50, 55, 70, 69, 53, 84, 112, 119, 114, 68, 100, 114, 53, 114, 77, 122, 99, 105, 106, 74, 115, 49, 101, 103, 57, 103, 73, 87, 105, 65, 89, 76, 116, 113, 90, 76, 73, 67, 106, 85, 10, 51, 106, 50, 76, 114, 84, 99, 70, 85, 51, 84, 43, 98, 115, 121, 56, 81, 120, 100, 120, 88, 118, 110, 70, 122, 66, 113, 112, 89, 101, 55, 51, 100, 103, 122, 122, 99, 118, 82, 121, 114, 99, 57, 121, 65, 106, 89, 72, 82, 56, 47, 118, 71, 86, 67, 74, 89, 77, 122, 112, 74, 74, 85, 80, 119, 115, 115, 100, 56, 109, 57, 50, 107, 77, 102, 77, 10, 100, 99, 71, 87, 120, 90, 48, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 84, 85, 82, 75, 84, 82, 85, 83, 84, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 32, 83, 101, 114, 118, 105, 99, 101, 115, 32, 80, 114, 111, 118, 105, 100, 101, 114, 32, 82, 111, 111, 116, 32, 50, 48, 48, 55, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 80, 84, 67, 67, 65, 121, 87, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 66, 118, 122, 69, 47, 77, 68, 48, 71, 65, 49, 85, 69, 65, 119, 119, 50, 86, 77, 79, 99, 85, 107, 116, 85, 85, 108, 86, 84, 86, 67, 66, 70, 10, 98, 71, 86, 114, 100, 72, 74, 118, 98, 109, 108, 114, 73, 70, 78, 108, 99, 110, 82, 112, 90, 109, 108, 114, 89, 83, 66, 73, 97, 88, 112, 116, 90, 88, 81, 103, 85, 50, 72, 69, 110, 50, 120, 104, 101, 99, 83, 120, 89, 56, 83, 120, 99, 56, 83, 120, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 85, 85, 106, 69, 80, 10, 77, 65, 48, 71, 65, 49, 85, 69, 66, 119, 119, 71, 81, 87, 53, 114, 89, 88, 74, 104, 77, 86, 52, 119, 88, 65, 89, 68, 86, 81, 81, 75, 68, 70, 86, 85, 119, 53, 120, 83, 83, 49, 82, 83, 86, 86, 78, 85, 73, 69, 74, 112, 98, 71, 100, 112, 73, 77, 83, 119, 98, 71, 86, 48, 97, 99, 87, 102, 97, 87, 48, 103, 100, 109, 85, 103, 10, 81, 109, 108, 115, 97, 99, 87, 102, 97, 87, 48, 103, 82, 56, 79, 56, 100, 109, 86, 117, 98, 71, 110, 69, 110, 50, 107, 103, 83, 71, 108, 54, 98, 87, 86, 48, 98, 71, 86, 121, 97, 83, 66, 66, 76, 115, 87, 101, 76, 105, 65, 111, 89, 121, 107, 103, 81, 88, 74, 104, 98, 77, 83, 120, 97, 121, 65, 121, 77, 68, 65, 51, 77, 66, 52, 88, 10, 68, 84, 65, 51, 77, 84, 73, 121, 78, 84, 69, 52, 77, 122, 99, 120, 79, 86, 111, 88, 68, 84, 69, 51, 77, 84, 73, 121, 77, 106, 69, 52, 77, 122, 99, 120, 79, 86, 111, 119, 103, 98, 56, 120, 80, 122, 65, 57, 66, 103, 78, 86, 66, 65, 77, 77, 78, 108, 84, 68, 110, 70, 74, 76, 86, 70, 74, 86, 85, 49, 81, 103, 82, 87, 120, 108, 10, 97, 51, 82, 121, 98, 50, 53, 112, 97, 121, 66, 84, 90, 88, 74, 48, 97, 87, 90, 112, 97, 50, 69, 103, 83, 71, 108, 54, 98, 87, 86, 48, 73, 70, 78, 104, 120, 74, 57, 115, 89, 88, 110, 69, 115, 87, 80, 69, 115, 88, 80, 69, 115, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 70, 73, 120, 68, 122, 65, 78, 10, 66, 103, 78, 86, 66, 65, 99, 77, 66, 107, 70, 117, 97, 50, 70, 121, 89, 84, 70, 101, 77, 70, 119, 71, 65, 49, 85, 69, 67, 103, 120, 86, 86, 77, 79, 99, 85, 107, 116, 85, 85, 108, 86, 84, 86, 67, 66, 67, 97, 87, 120, 110, 97, 83, 68, 69, 115, 71, 120, 108, 100, 71, 110, 70, 110, 50, 108, 116, 73, 72, 90, 108, 73, 69, 74, 112, 10, 98, 71, 110, 70, 110, 50, 108, 116, 73, 69, 102, 68, 118, 72, 90, 108, 98, 109, 120, 112, 120, 74, 57, 112, 73, 69, 104, 112, 101, 109, 49, 108, 100, 71, 120, 108, 99, 109, 107, 103, 81, 83, 55, 70, 110, 105, 52, 103, 75, 71, 77, 112, 73, 69, 70, 121, 89, 87, 122, 69, 115, 87, 115, 103, 77, 106, 65, 119, 78, 122, 67, 67, 65, 83, 73, 119, 10, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 75, 117, 51, 80, 103, 113, 77, 121, 75, 86, 89, 70, 101, 97, 75, 55, 121, 99, 57, 83, 114, 84, 111, 74, 100, 80, 78, 77, 56, 73, 103, 51, 66, 110, 117, 105, 68, 57, 78, 10, 89, 118, 68, 100, 69, 51, 101, 80, 89, 97, 107, 113, 116, 100, 84, 121, 117, 84, 70, 89, 75, 84, 115, 118, 80, 50, 113, 99, 98, 51, 78, 50, 74, 101, 52, 48, 73, 73, 68, 117, 54, 114, 102, 119, 120, 65, 114, 78, 75, 52, 97, 85, 121, 101, 78, 103, 115, 85, 82, 83, 115, 108, 111, 112, 116, 74, 71, 88, 103, 57, 105, 51, 112, 104, 81, 118, 10, 75, 85, 109, 105, 56, 119, 85, 71, 43, 55, 82, 80, 50, 113, 70, 115, 109, 109, 97, 102, 56, 69, 77, 74, 121, 117, 112, 121, 106, 43, 115, 65, 49, 122, 85, 53, 49, 49, 89, 88, 82, 120, 99, 119, 57, 76, 54, 47, 80, 56, 74, 111, 114, 122, 90, 65, 119, 97, 110, 48, 113, 97, 102, 111, 69, 71, 115, 73, 105, 118, 101, 71, 72, 116, 121, 97, 10, 75, 104, 85, 71, 57, 113, 80, 119, 57, 79, 68, 72, 70, 78, 82, 82, 102, 56, 43, 48, 50, 50, 50, 118, 82, 53, 89, 88, 109, 51, 100, 120, 50, 75, 100, 120, 110, 83, 81, 77, 57, 112, 81, 47, 104, 84, 69, 83, 84, 55, 114, 117, 84, 111, 75, 52, 117, 84, 54, 80, 73, 122, 100, 101, 122, 75, 75, 113, 100, 102, 99, 89, 98, 119, 110, 84, 10, 114, 113, 100, 85, 75, 68, 84, 55, 52, 101, 65, 55, 89, 72, 50, 103, 118, 110, 109, 74, 104, 115, 105, 102, 76, 102, 107, 75, 83, 56, 82, 81, 111, 117, 102, 57, 101, 82, 98, 72, 101, 103, 115, 89, 122, 56, 53, 77, 55, 51, 51, 87, 66, 50, 43, 89, 56, 97, 43, 120, 119, 88, 114, 88, 103, 84, 87, 52, 113, 104, 101, 48, 52, 77, 115, 67, 10, 65, 119, 69, 65, 65, 97, 78, 67, 77, 69, 65, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 67, 110, 70, 107, 75, 115, 108, 114, 120, 72, 107, 89, 98, 43, 106, 47, 52, 104, 104, 107, 101, 89, 79, 47, 112, 121, 66, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 80, 10, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 66, 65, 81, 65, 81, 68, 100, 114, 52, 79, 117, 119, 111, 48, 82, 83, 86, 103, 114, 69, 83, 76, 70, 70, 54, 81, 83, 85, 50, 84, 74, 47, 115, 10, 80, 120, 43, 69, 110, 87, 86, 85, 88, 75, 103, 87, 65, 107, 68, 54, 98, 104, 111, 51, 104, 79, 57, 121, 110, 89, 89, 75, 86, 90, 49, 87, 75, 75, 120, 109, 76, 78, 65, 54, 86, 112, 77, 48, 66, 121, 87, 116, 67, 76, 67, 80, 121, 65, 56, 74, 87, 99, 113, 100, 109, 66, 122, 108, 86, 80, 105, 53, 82, 88, 57, 113, 108, 50, 43, 73, 10, 97, 69, 49, 75, 66, 105, 89, 51, 105, 65, 73, 79, 116, 115, 98, 87, 99, 112, 110, 79, 97, 51, 102, 97, 89, 106, 71, 107, 86, 104, 43, 117, 88, 52, 49, 51, 50, 108, 51, 50, 105, 80, 119, 97, 50, 90, 54, 49, 103, 102, 65, 121, 117, 79, 79, 73, 48, 74, 122, 122, 97, 113, 67, 53, 109, 120, 82, 90, 78, 84, 90, 80, 122, 47, 79, 79, 10, 88, 108, 48, 88, 114, 82, 87, 86, 50, 78, 50, 121, 49, 82, 86, 117, 65, 69, 54, 122, 83, 56, 57, 109, 108, 79, 84, 103, 122, 98, 85, 70, 50, 109, 78, 88, 105, 43, 87, 122, 113, 116, 118, 65, 76, 104, 121, 81, 82, 78, 115, 97, 88, 82, 105, 107, 55, 114, 52, 69, 87, 53, 110, 86, 99, 86, 57, 86, 90, 87, 82, 105, 49, 97, 75, 98, 10, 66, 70, 109, 71, 121, 71, 74, 51, 53, 51, 121, 67, 82, 87, 111, 57, 70, 55, 47, 115, 110, 88, 85, 77, 114, 113, 78, 118, 87, 116, 77, 118, 109, 68, 98, 48, 56, 80, 85, 90, 113, 120, 70, 100, 121, 75, 98, 106, 75, 108, 104, 113, 81, 103, 110, 68, 118, 90, 73, 109, 90, 106, 73, 78, 88, 81, 104, 86, 100, 80, 43, 77, 109, 78, 65, 75, 10, 112, 111, 82, 113, 48, 84, 108, 57, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 45, 84, 82, 85, 83, 84, 32, 82, 111, 111, 116, 32, 67, 108, 97, 115, 115, 32, 51, 32, 67, 65, 32, 50, 32, 50, 48, 48, 57, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 77, 122, 67, 67, 65, 120, 117, 103, 65, 119, 73, 66, 65, 103, 73, 68, 67, 89, 80, 122, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 77, 69, 48, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 82, 70, 77, 82, 85, 119, 69, 119, 89, 68, 86, 81, 81, 75, 10, 68, 65, 120, 69, 76, 86, 82, 121, 100, 88, 78, 48, 73, 69, 100, 116, 89, 107, 103, 120, 74, 122, 65, 108, 66, 103, 78, 86, 66, 65, 77, 77, 72, 107, 81, 116, 86, 70, 74, 86, 85, 49, 81, 103, 85, 109, 57, 118, 100, 67, 66, 68, 98, 71, 70, 122, 99, 121, 65, 122, 73, 69, 78, 66, 73, 68, 73, 103, 77, 106, 65, 119, 79, 84, 65, 101, 10, 70, 119, 48, 119, 79, 84, 69, 120, 77, 68, 85, 119, 79, 68, 77, 49, 78, 84, 104, 97, 70, 119, 48, 121, 79, 84, 69, 120, 77, 68, 85, 119, 79, 68, 77, 49, 78, 84, 104, 97, 77, 69, 48, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 82, 70, 77, 82, 85, 119, 69, 119, 89, 68, 86, 81, 81, 75, 68, 65, 120, 69, 10, 76, 86, 82, 121, 100, 88, 78, 48, 73, 69, 100, 116, 89, 107, 103, 120, 74, 122, 65, 108, 66, 103, 78, 86, 66, 65, 77, 77, 72, 107, 81, 116, 86, 70, 74, 86, 85, 49, 81, 103, 85, 109, 57, 118, 100, 67, 66, 68, 98, 71, 70, 122, 99, 121, 65, 122, 73, 69, 78, 66, 73, 68, 73, 103, 77, 106, 65, 119, 79, 84, 67, 67, 65, 83, 73, 119, 10, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 78, 79, 121, 83, 115, 57, 54, 82, 43, 57, 49, 109, 121, 80, 54, 79, 105, 47, 87, 85, 69, 87, 74, 78, 84, 114, 71, 97, 57, 118, 43, 50, 119, 66, 111, 113, 79, 65, 68, 10, 69, 82, 48, 51, 85, 65, 105, 102, 84, 85, 112, 111, 108, 68, 87, 122, 85, 57, 71, 85, 89, 54, 99, 103, 86, 113, 47, 101, 85, 88, 106, 115, 75, 106, 51, 122, 83, 69, 104, 81, 80, 103, 114, 102, 82, 108, 87, 76, 74, 50, 51, 68, 69, 69, 48, 78, 107, 86, 74, 68, 50, 73, 102, 103, 88, 85, 52, 50, 116, 83, 72, 75, 88, 122, 108, 65, 10, 66, 70, 57, 98, 102, 115, 121, 106, 120, 105, 117, 112, 81, 66, 55, 90, 78, 111, 84, 87, 83, 80, 79, 83, 72, 106, 82, 71, 73, 67, 84, 66, 112, 70, 71, 79, 83, 104, 114, 118, 85, 68, 57, 112, 88, 82, 108, 47, 82, 99, 80, 72, 65, 89, 57, 82, 121, 83, 80, 111, 99, 113, 54, 48, 118, 70, 89, 74, 102, 120, 76, 76, 72, 76, 71, 118, 10, 75, 90, 65, 75, 121, 86, 88, 77, 68, 57, 79, 48, 71, 117, 49, 72, 78, 86, 112, 75, 55, 90, 120, 122, 66, 67, 72, 81, 113, 114, 48, 77, 69, 55, 85, 65, 121, 105, 90, 115, 120, 71, 115, 77, 108, 70, 113, 86, 108, 78, 112, 81, 109, 118, 72, 47, 112, 83, 116, 109, 77, 97, 84, 74, 79, 75, 68, 102, 72, 82, 43, 52, 67, 83, 55, 122, 10, 112, 43, 104, 110, 85, 113, 117, 86, 72, 43, 66, 71, 80, 116, 105, 107, 119, 56, 112, 97, 120, 84, 71, 65, 54, 69, 105, 97, 110, 53, 82, 112, 47, 104, 110, 100, 50, 72, 78, 56, 103, 99, 113, 87, 51, 111, 55, 116, 115, 122, 73, 70, 90, 89, 81, 48, 53, 117, 98, 57, 86, 120, 67, 49, 88, 51, 97, 47, 76, 55, 65, 81, 68, 99, 85, 67, 10, 65, 119, 69, 65, 65, 97, 79, 67, 65, 82, 111, 119, 103, 103, 69, 87, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 80, 51, 97, 70, 77, 83, 102, 77, 78, 52, 104, 118, 82, 53, 67, 79, 102, 121, 114, 89, 121, 78, 74, 10, 52, 80, 71, 69, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 67, 66, 48, 119, 89, 68, 86, 82, 48, 102, 66, 73, 72, 76, 77, 73, 72, 73, 77, 73, 71, 65, 111, 72, 54, 103, 102, 73, 90, 54, 98, 71, 82, 104, 99, 68, 111, 118, 76, 50, 82, 112, 99, 109, 86, 106, 100, 71, 57, 121, 10, 101, 83, 53, 107, 76, 88, 82, 121, 100, 88, 78, 48, 76, 109, 53, 108, 100, 67, 57, 68, 84, 106, 49, 69, 76, 86, 82, 83, 86, 86, 78, 85, 74, 84, 73, 119, 85, 109, 57, 118, 100, 67, 85, 121, 77, 69, 78, 115, 89, 88, 78, 122, 74, 84, 73, 119, 77, 121, 85, 121, 77, 69, 78, 66, 74, 84, 73, 119, 77, 105, 85, 121, 77, 68, 73, 119, 10, 77, 68, 107, 115, 84, 122, 49, 69, 76, 86, 82, 121, 100, 88, 78, 48, 74, 84, 73, 119, 82, 50, 49, 105, 83, 67, 120, 68, 80, 85, 82, 70, 80, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 109, 86, 50, 98, 50, 78, 104, 100, 71, 108, 118, 98, 109, 120, 112, 99, 51, 81, 119, 81, 54, 66, 66, 111, 68, 43, 71, 10, 80, 87, 104, 48, 100, 72, 65, 54, 76, 121, 57, 51, 100, 51, 99, 117, 90, 67, 49, 48, 99, 110, 86, 122, 100, 67, 53, 117, 90, 88, 81, 118, 89, 51, 74, 115, 76, 50, 81, 116, 100, 72, 74, 49, 99, 51, 82, 102, 99, 109, 57, 118, 100, 70, 57, 106, 98, 71, 70, 122, 99, 49, 56, 122, 88, 50, 78, 104, 88, 122, 74, 102, 77, 106, 65, 119, 10, 79, 83, 53, 106, 99, 109, 119, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 69, 66, 65, 72, 43, 88, 50, 122, 68, 73, 51, 54, 83, 99, 102, 83, 70, 54, 103, 72, 68, 79, 70, 66, 74, 112, 105, 66, 83, 86, 89, 69, 81, 66, 114, 76, 76, 112, 77, 69, 43, 98, 85, 77, 74, 109, 10, 50, 72, 54, 78, 77, 76, 86, 119, 77, 101, 110, 105, 97, 99, 102, 122, 99, 78, 115, 103, 70, 89, 98, 81, 68, 102, 67, 43, 114, 65, 70, 49, 104, 77, 53, 43, 110, 48, 50, 47, 116, 50, 65, 55, 110, 80, 80, 75, 72, 101, 74, 101, 97, 78, 105, 106, 110, 90, 102, 108, 81, 71, 68, 83, 78, 105, 72, 43, 48, 76, 83, 52, 70, 57, 112, 48, 10, 111, 51, 47, 85, 51, 55, 67, 89, 65, 113, 120, 118, 97, 50, 115, 115, 74, 83, 82, 121, 111, 87, 88, 117, 74, 86, 114, 108, 53, 106, 76, 110, 56, 116, 43, 114, 83, 102, 114, 122, 107, 71, 107, 106, 50, 119, 84, 90, 53, 49, 120, 89, 47, 71, 88, 85, 108, 55, 55, 77, 47, 67, 52, 75, 122, 67, 85, 113, 78, 81, 84, 52, 89, 74, 69, 86, 10, 100, 84, 49, 66, 47, 121, 77, 102, 71, 99, 104, 115, 54, 52, 74, 84, 66, 75, 98, 107, 84, 67, 74, 78, 106, 89, 121, 54, 122, 108, 116, 122, 55, 71, 82, 85, 85, 71, 51, 82, 110, 70, 88, 55, 97, 99, 77, 50, 119, 52, 121, 56, 80, 73, 87, 109, 97, 119, 111, 109, 68, 101, 67, 84, 109, 71, 67, 117, 102, 115, 89, 107, 108, 52, 112, 104, 10, 88, 53, 71, 79, 90, 112, 73, 74, 104, 122, 98, 78, 105, 53, 115, 116, 80, 118, 90, 82, 49, 70, 68, 85, 87, 83, 105, 57, 103, 47, 76, 77, 75, 72, 116, 84, 104, 109, 51, 89, 74, 111, 104, 119, 49, 43, 113, 82, 122, 84, 54, 53, 121, 115, 67, 81, 98, 108, 114, 71, 88, 110, 82, 108, 49, 49, 122, 43, 111, 43, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 45, 84, 82, 85, 83, 84, 32, 82, 111, 111, 116, 32, 67, 108, 97, 115, 115, 32, 51, 32, 67, 65, 32, 50, 32, 69, 86, 32, 50, 48, 48, 57, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 81, 122, 67, 67, 65, 121, 117, 103, 65, 119, 73, 66, 65, 103, 73, 68, 67, 89, 80, 48, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 77, 70, 65, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 82, 70, 77, 82, 85, 119, 69, 119, 89, 68, 86, 81, 81, 75, 10, 68, 65, 120, 69, 76, 86, 82, 121, 100, 88, 78, 48, 73, 69, 100, 116, 89, 107, 103, 120, 75, 106, 65, 111, 66, 103, 78, 86, 66, 65, 77, 77, 73, 85, 81, 116, 86, 70, 74, 86, 85, 49, 81, 103, 85, 109, 57, 118, 100, 67, 66, 68, 98, 71, 70, 122, 99, 121, 65, 122, 73, 69, 78, 66, 73, 68, 73, 103, 82, 86, 89, 103, 77, 106, 65, 119, 10, 79, 84, 65, 101, 70, 119, 48, 119, 79, 84, 69, 120, 77, 68, 85, 119, 79, 68, 85, 119, 78, 68, 90, 97, 70, 119, 48, 121, 79, 84, 69, 120, 77, 68, 85, 119, 79, 68, 85, 119, 78, 68, 90, 97, 77, 70, 65, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 82, 70, 77, 82, 85, 119, 69, 119, 89, 68, 86, 81, 81, 75, 10, 68, 65, 120, 69, 76, 86, 82, 121, 100, 88, 78, 48, 73, 69, 100, 116, 89, 107, 103, 120, 75, 106, 65, 111, 66, 103, 78, 86, 66, 65, 77, 77, 73, 85, 81, 116, 86, 70, 74, 86, 85, 49, 81, 103, 85, 109, 57, 118, 100, 67, 66, 68, 98, 71, 70, 122, 99, 121, 65, 122, 73, 69, 78, 66, 73, 68, 73, 103, 82, 86, 89, 103, 77, 106, 65, 119, 10, 79, 84, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 103, 103, 69, 66, 65, 74, 110, 120, 104, 68, 82, 119, 117, 105, 43, 51, 77, 75, 67, 79, 118, 88, 119, 69, 122, 55, 53, 105, 118, 74, 110, 57, 103, 112, 102, 83, 10, 101, 103, 112, 110, 108, 106, 103, 74, 57, 104, 66, 79, 108, 83, 74, 122, 109, 89, 51, 97, 70, 83, 51, 110, 66, 102, 119, 90, 99, 121, 75, 51, 106, 112, 103, 65, 118, 68, 119, 57, 114, 75, 70, 115, 43, 57, 90, 53, 74, 85, 117, 116, 56, 77, 120, 107, 50, 111, 103, 43, 75, 98, 103, 80, 67, 100, 77, 48, 51, 84, 80, 49, 89, 116, 72, 104, 10, 122, 82, 110, 112, 55, 104, 104, 80, 84, 70, 105, 117, 52, 104, 55, 87, 68, 70, 115, 86, 87, 116, 103, 54, 117, 77, 81, 89, 90, 66, 55, 106, 77, 55, 75, 49, 105, 88, 100, 79, 68, 76, 47, 90, 108, 71, 115, 84, 108, 50, 56, 83, 111, 47, 54, 90, 113, 81, 84, 77, 70, 101, 120, 103, 97, 68, 98, 116, 67, 72, 117, 51, 57, 98, 43, 84, 10, 55, 87, 89, 120, 103, 52, 122, 71, 99, 84, 83, 72, 84, 104, 102, 113, 114, 52, 117, 82, 106, 82, 120, 87, 81, 97, 52, 105, 78, 49, 52, 51, 56, 104, 51, 90, 48, 83, 48, 78, 76, 50, 108, 82, 112, 55, 53, 109, 112, 111, 111, 54, 75, 114, 51, 72, 71, 114, 72, 104, 70, 80, 67, 43, 79, 104, 50, 53, 122, 49, 117, 120, 97, 118, 54, 48, 10, 115, 85, 89, 103, 111, 118, 115, 101, 79, 51, 68, 118, 107, 53, 104, 57, 106, 72, 79, 87, 56, 115, 88, 118, 104, 88, 67, 116, 75, 83, 98, 56, 72, 103, 81, 43, 72, 75, 68, 89, 68, 56, 116, 83, 103, 50, 74, 56, 55, 111, 116, 84, 108, 90, 67, 112, 86, 54, 76, 113, 89, 81, 88, 89, 43, 85, 51, 69, 74, 47, 112, 117, 114, 101, 51, 53, 10, 49, 49, 72, 51, 97, 54, 85, 67, 65, 119, 69, 65, 65, 97, 79, 67, 65, 83, 81, 119, 103, 103, 69, 103, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 78, 79, 85, 105, 107, 120, 105, 69, 121, 111, 90, 76, 115, 121, 118, 10, 99, 111, 112, 57, 78, 116, 101, 97, 72, 78, 120, 110, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 67, 66, 51, 81, 89, 68, 86, 82, 48, 102, 66, 73, 72, 86, 77, 73, 72, 83, 77, 73, 71, 72, 111, 73, 71, 69, 111, 73, 71, 66, 104, 110, 57, 115, 90, 71, 70, 119, 79, 105, 56, 118, 10, 90, 71, 108, 121, 90, 87, 78, 48, 98, 51, 74, 53, 76, 109, 81, 116, 100, 72, 74, 49, 99, 51, 81, 117, 98, 109, 86, 48, 76, 48, 78, 79, 80, 85, 81, 116, 86, 70, 74, 86, 85, 49, 81, 108, 77, 106, 66, 83, 98, 50, 57, 48, 74, 84, 73, 119, 81, 50, 120, 104, 99, 51, 77, 108, 77, 106, 65, 122, 74, 84, 73, 119, 81, 48, 69, 108, 10, 77, 106, 65, 121, 74, 84, 73, 119, 82, 86, 89, 108, 77, 106, 65, 121, 77, 68, 65, 53, 76, 69, 56, 57, 82, 67, 49, 85, 99, 110, 86, 122, 100, 67, 85, 121, 77, 69, 100, 116, 89, 107, 103, 115, 81, 122, 49, 69, 82, 84, 57, 106, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 88, 74, 108, 100, 109, 57, 106, 89, 88, 82, 112, 10, 98, 50, 53, 115, 97, 88, 78, 48, 77, 69, 97, 103, 82, 75, 66, 67, 104, 107, 66, 111, 100, 72, 82, 119, 79, 105, 56, 118, 100, 51, 100, 51, 76, 109, 81, 116, 100, 72, 74, 49, 99, 51, 81, 117, 98, 109, 86, 48, 76, 50, 78, 121, 98, 67, 57, 107, 76, 88, 82, 121, 100, 88, 78, 48, 88, 51, 74, 118, 98, 51, 82, 102, 89, 50, 120, 104, 10, 99, 51, 78, 102, 77, 49, 57, 106, 89, 86, 56, 121, 88, 50, 86, 50, 88, 122, 73, 119, 77, 68, 107, 117, 89, 51, 74, 115, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 66, 65, 81, 65, 48, 55, 88, 116, 97, 80, 75, 83, 85, 105, 79, 56, 97, 69, 88, 85, 72, 76, 55, 80, 43, 10, 80, 80, 111, 101, 85, 83, 98, 114, 104, 47, 89, 112, 51, 117, 68, 120, 49, 77, 89, 107, 67, 101, 110, 66, 122, 49, 85, 98, 116, 68, 68, 90, 122, 104, 114, 43, 66, 108, 71, 109, 70, 97, 81, 116, 55, 55, 74, 76, 118, 121, 65, 111, 74, 85, 110, 82, 112, 106, 90, 51, 78, 79, 104, 107, 51, 49, 75, 120, 69, 99, 100, 122, 101, 115, 48, 53, 10, 110, 115, 75, 116, 106, 72, 69, 104, 56, 108, 112, 114, 114, 57, 56, 56, 84, 108, 87, 118, 115, 111, 82, 108, 70, 73, 109, 53, 100, 56, 115, 113, 77, 98, 55, 80, 111, 50, 51, 80, 98, 48, 105, 85, 77, 107, 90, 118, 53, 51, 71, 77, 111, 75, 97, 69, 71, 84, 99, 72, 56, 103, 78, 70, 67, 83, 117, 71, 100, 88, 122, 102, 88, 50, 108, 88, 10, 65, 78, 116, 117, 50, 75, 90, 121, 73, 107, 116, 81, 49, 72, 87, 89, 86, 116, 43, 51, 71, 80, 57, 68, 81, 49, 67, 117, 101, 107, 82, 55, 56, 72, 108, 82, 49, 48, 77, 57, 112, 57, 79, 66, 48, 47, 68, 74, 84, 55, 110, 97, 120, 112, 101, 71, 48, 73, 76, 68, 53, 69, 74, 116, 47, 114, 68, 105, 90, 69, 52, 79, 74, 117, 100, 65, 10, 78, 67, 97, 49, 67, 73, 110, 88, 67, 71, 78, 106, 79, 67, 100, 49, 72, 106, 80, 113, 98, 113, 106, 100, 110, 53, 108, 80, 100, 69, 50, 66, 105, 89, 66, 76, 51, 90, 113, 88, 75, 86, 119, 118, 118, 111, 70, 66, 117, 89, 122, 47, 54, 110, 49, 103, 66, 112, 55, 78, 49, 122, 51, 84, 76, 113, 77, 86, 118, 75, 106, 109, 74, 117, 86, 118, 10, 119, 57, 121, 52, 65, 121, 72, 113, 110, 120, 98, 120, 76, 70, 83, 49, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 80, 83, 67, 80, 114, 111, 99, 101, 114, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 74, 104, 106, 67, 67, 66, 50, 54, 103, 65, 119, 73, 66, 65, 103, 73, 66, 67, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 67, 65, 82, 52, 120, 80, 106, 65, 56, 66, 103, 78, 86, 66, 65, 77, 84, 78, 85, 70, 49, 100, 71, 57, 121, 97, 87, 82, 104, 90, 67, 66, 107, 10, 90, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 106, 97, 87, 57, 117, 73, 70, 74, 104, 97, 88, 111, 103, 90, 71, 86, 115, 73, 69, 86, 122, 100, 71, 70, 107, 98, 121, 66, 87, 90, 87, 53, 108, 101, 109, 57, 115, 89, 87, 53, 118, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 87, 82, 84, 69, 81, 10, 77, 65, 52, 71, 65, 49, 85, 69, 66, 120, 77, 72, 81, 50, 70, 121, 89, 87, 78, 104, 99, 122, 69, 90, 77, 66, 99, 71, 65, 49, 85, 69, 67, 66, 77, 81, 82, 71, 108, 122, 100, 72, 74, 112, 100, 71, 56, 103, 81, 50, 70, 119, 97, 88, 82, 104, 98, 68, 69, 50, 77, 68, 81, 71, 65, 49, 85, 69, 67, 104, 77, 116, 85, 50, 108, 122, 10, 100, 71, 86, 116, 89, 83, 66, 79, 89, 87, 78, 112, 98, 50, 53, 104, 98, 67, 66, 107, 90, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 106, 97, 87, 57, 117, 73, 69, 86, 115, 90, 87, 78, 48, 99, 109, 57, 117, 97, 87, 78, 104, 77, 85, 77, 119, 81, 81, 89, 68, 86, 81, 81, 76, 69, 122, 112, 84, 100, 88, 66, 108, 10, 99, 109, 108, 117, 100, 71, 86, 117, 90, 71, 86, 117, 89, 50, 108, 104, 73, 71, 82, 108, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 108, 118, 99, 121, 66, 107, 90, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 106, 97, 87, 57, 117, 73, 69, 86, 115, 90, 87, 78, 48, 99, 109, 57, 117, 97, 87, 78, 104, 77, 83, 85, 119, 10, 73, 119, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 107, 66, 70, 104, 90, 104, 89, 51, 74, 104, 97, 88, 112, 65, 99, 51, 86, 122, 89, 50, 86, 121, 100, 71, 85, 117, 90, 50, 57, 105, 76, 110, 90, 108, 77, 66, 52, 88, 68, 84, 69, 119, 77, 84, 73, 121, 79, 68, 69, 50, 78, 84, 69, 119, 77, 70, 111, 88, 68, 84, 73, 119, 10, 77, 84, 73, 121, 78, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 103, 100, 69, 120, 74, 106, 65, 107, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 67, 81, 69, 87, 70, 50, 78, 118, 98, 110, 82, 104, 89, 51, 82, 118, 81, 72, 66, 121, 98, 50, 78, 108, 99, 110, 81, 117, 98, 109, 86, 48, 76, 110, 90, 108, 77, 81, 56, 119, 10, 68, 81, 89, 68, 86, 81, 81, 72, 69, 119, 90, 68, 97, 71, 70, 106, 89, 87, 56, 120, 69, 68, 65, 79, 66, 103, 78, 86, 66, 65, 103, 84, 66, 48, 49, 112, 99, 109, 70, 117, 90, 71, 69, 120, 75, 106, 65, 111, 66, 103, 78, 86, 66, 65, 115, 84, 73, 86, 66, 121, 98, 51, 90, 108, 90, 87, 82, 118, 99, 105, 66, 107, 90, 83, 66, 68, 10, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 107, 98, 51, 77, 103, 85, 70, 74, 80, 81, 48, 86, 83, 86, 68, 69, 50, 77, 68, 81, 71, 65, 49, 85, 69, 67, 104, 77, 116, 85, 50, 108, 122, 100, 71, 86, 116, 89, 83, 66, 79, 89, 87, 78, 112, 98, 50, 53, 104, 98, 67, 66, 107, 90, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 10, 89, 50, 70, 106, 97, 87, 57, 117, 73, 69, 86, 115, 90, 87, 78, 48, 99, 109, 57, 117, 97, 87, 78, 104, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 87, 82, 84, 69, 84, 77, 66, 69, 71, 65, 49, 85, 69, 65, 120, 77, 75, 85, 70, 78, 68, 85, 72, 74, 118, 89, 50, 86, 121, 100, 68, 67, 67, 65, 105, 73, 119, 10, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 78, 87, 51, 57, 75, 79, 85, 77, 54, 70, 71, 113, 86, 86, 104, 83, 81, 50, 111, 104, 51, 78, 101, 107, 83, 49, 119, 119, 81, 89, 97, 108, 78, 111, 57, 55, 66, 86, 67, 10, 119, 102, 87, 77, 114, 109, 111, 88, 56, 89, 113, 116, 47, 73, 67, 86, 54, 111, 78, 69, 111, 108, 116, 54, 86, 99, 53, 80, 112, 54, 88, 86, 117, 114, 103, 102, 111, 67, 102, 65, 85, 70, 77, 43, 106, 98, 110, 65, 68, 114, 103, 86, 51, 78, 90, 115, 43, 74, 55, 52, 66, 67, 88, 102, 103, 73, 56, 81, 104, 100, 49, 57, 76, 51, 117, 65, 10, 51, 86, 99, 65, 90, 67, 80, 52, 98, 115, 109, 43, 108, 85, 47, 104, 100, 101, 122, 103, 102, 108, 54, 86, 122, 98, 72, 118, 118, 110, 112, 67, 50, 77, 107, 115, 48, 43, 115, 97, 71, 105, 75, 76, 116, 51, 56, 71, 105, 101, 85, 56, 57, 82, 76, 65, 117, 57, 77, 76, 109, 86, 43, 81, 102, 73, 52, 116, 76, 51, 99, 122, 107, 107, 111, 104, 10, 82, 113, 105, 112, 67, 75, 122, 120, 57, 104, 69, 67, 50, 90, 85, 87, 110, 111, 48, 118, 108, 117, 89, 67, 51, 88, 88, 67, 70, 67, 112, 97, 49, 115, 108, 57, 74, 99, 76, 66, 47, 75, 112, 110, 104, 101, 76, 115, 118, 116, 70, 56, 80, 80, 113, 118, 49, 87, 55, 47, 85, 48, 72, 85, 57, 84, 73, 52, 115, 101, 74, 102, 120, 80, 109, 79, 10, 69, 79, 56, 71, 113, 81, 75, 74, 47, 43, 77, 77, 98, 112, 102, 103, 51, 53, 51, 98, 73, 100, 68, 48, 80, 103, 104, 112, 98, 78, 106, 85, 53, 68, 98, 52, 103, 55, 97, 121, 78, 111, 43, 99, 55, 122, 111, 51, 70, 110, 50, 47, 111, 109, 110, 88, 79, 49, 116, 121, 48, 75, 43, 113, 80, 49, 120, 109, 107, 54, 119, 75, 73, 109, 71, 50, 10, 48, 113, 67, 90, 121, 70, 83, 84, 88, 97, 105, 50, 48, 98, 49, 100, 67, 108, 53, 51, 108, 75, 73, 116, 119, 73, 75, 79, 118, 77, 111, 68, 75, 106, 83, 117, 99, 47, 72, 85, 116, 81, 121, 57, 118, 109, 101, 98, 86, 79, 118, 104, 43, 113, 66, 97, 55, 68, 104, 43, 80, 115, 72, 77, 111, 115, 100, 69, 77, 88, 88, 113, 80, 43, 85, 72, 10, 48, 113, 117, 104, 74, 90, 98, 50, 53, 117, 83, 103, 88, 84, 99, 89, 79, 87, 69, 65, 77, 49, 49, 71, 49, 65, 68, 69, 116, 77, 111, 56, 56, 97, 75, 106, 80, 118, 77, 54, 47, 50, 107, 119, 76, 107, 68, 100, 57, 112, 43, 99, 74, 115, 109, 87, 78, 54, 51, 110, 79, 97, 75, 47, 54, 109, 110, 98, 86, 83, 75, 86, 85, 121, 113, 85, 10, 116, 100, 43, 116, 70, 106, 105, 66, 100, 87, 98, 106, 120, 121, 119, 98, 107, 53, 121, 113, 106, 75, 80, 75, 50, 87, 119, 56, 70, 50, 50, 99, 51, 72, 120, 84, 52, 67, 65, 110, 81, 122, 98, 53, 69, 117, 69, 56, 88, 76, 49, 109, 118, 54, 74, 112, 73, 122, 105, 52, 109, 87, 67, 90, 68, 108, 90, 84, 79, 112, 120, 43, 70, 73, 121, 119, 10, 66, 109, 47, 120, 104, 110, 97, 81, 114, 47, 50, 118, 47, 112, 68, 71, 106, 53, 57, 47, 105, 53, 73, 106, 110, 79, 99, 86, 100, 111, 47, 86, 105, 53, 81, 84, 99, 109, 110, 55, 75, 50, 70, 106, 105, 79, 47, 109, 112, 70, 55, 109, 111, 120, 100, 113, 87, 69, 102, 76, 99, 85, 56, 85, 67, 49, 55, 73, 65, 103, 103, 109, 111, 115, 118, 112, 10, 114, 50, 117, 75, 71, 99, 102, 76, 70, 70, 98, 49, 52, 100, 113, 49, 50, 102, 121, 47, 99, 122, 106, 97, 43, 101, 101, 118, 98, 113, 81, 51, 52, 103, 99, 110, 65, 103, 77, 66, 65, 65, 71, 106, 103, 103, 77, 88, 77, 73, 73, 68, 69, 122, 65, 83, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 67, 68, 65, 71, 65, 81, 72, 47, 10, 65, 103, 69, 66, 77, 68, 99, 71, 65, 49, 85, 100, 69, 103, 81, 119, 77, 67, 54, 67, 68, 51, 78, 49, 99, 50, 78, 108, 99, 110, 82, 108, 76, 109, 100, 118, 89, 105, 53, 50, 90, 97, 65, 98, 66, 103, 86, 103, 104, 108, 52, 67, 65, 113, 65, 83, 68, 66, 66, 83, 83, 85, 89, 116, 82, 121, 48, 121, 77, 68, 65, 119, 78, 68, 65, 122, 10, 78, 105, 48, 119, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 66, 68, 120, 107, 52, 113, 112, 108, 47, 81, 103, 117, 107, 49, 121, 101, 89, 86, 75, 73, 88, 84, 67, 49, 82, 86, 68, 67, 67, 65, 86, 65, 71, 65, 49, 85, 100, 73, 119, 83, 67, 65, 85, 99, 119, 103, 103, 70, 68, 103, 66, 83, 116, 117, 121, 73, 100, 10, 120, 117, 68, 83, 65, 97, 106, 57, 100, 108, 66, 83, 107, 43, 50, 89, 119, 85, 50, 117, 48, 54, 71, 67, 65, 83, 97, 107, 103, 103, 69, 105, 77, 73, 73, 66, 72, 106, 69, 43, 77, 68, 119, 71, 65, 49, 85, 69, 65, 120, 77, 49, 81, 88, 86, 48, 98, 51, 74, 112, 90, 71, 70, 107, 73, 71, 82, 108, 73, 69, 78, 108, 99, 110, 82, 112, 10, 90, 109, 108, 106, 89, 87, 78, 112, 98, 50, 52, 103, 85, 109, 70, 112, 101, 105, 66, 107, 90, 87, 119, 103, 82, 88, 78, 48, 89, 87, 82, 118, 73, 70, 90, 108, 98, 109, 86, 54, 98, 50, 120, 104, 98, 109, 56, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 90, 70, 77, 82, 65, 119, 68, 103, 89, 68, 86, 81, 81, 72, 10, 69, 119, 100, 68, 89, 88, 74, 104, 89, 50, 70, 122, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 73, 69, 120, 66, 69, 97, 88, 78, 48, 99, 109, 108, 48, 98, 121, 66, 68, 89, 88, 66, 112, 100, 71, 70, 115, 77, 84, 89, 119, 78, 65, 89, 68, 86, 81, 81, 75, 69, 121, 49, 84, 97, 88, 78, 48, 90, 87, 49, 104, 73, 69, 53, 104, 10, 89, 50, 108, 118, 98, 109, 70, 115, 73, 71, 82, 108, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 87, 78, 112, 98, 50, 52, 103, 82, 87, 120, 108, 89, 51, 82, 121, 98, 50, 53, 112, 89, 50, 69, 120, 81, 122, 66, 66, 66, 103, 78, 86, 66, 65, 115, 84, 79, 108, 78, 49, 99, 71, 86, 121, 97, 87, 53, 48, 90, 87, 53, 107, 10, 90, 87, 53, 106, 97, 87, 69, 103, 90, 71, 85, 103, 85, 50, 86, 121, 100, 109, 108, 106, 97, 87, 57, 122, 73, 71, 82, 108, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 87, 78, 112, 98, 50, 52, 103, 82, 87, 120, 108, 89, 51, 82, 121, 98, 50, 53, 112, 89, 50, 69, 120, 74, 84, 65, 106, 66, 103, 107, 113, 104, 107, 105, 71, 10, 57, 119, 48, 66, 67, 81, 69, 87, 70, 109, 70, 106, 99, 109, 70, 112, 101, 107, 66, 122, 100, 88, 78, 106, 90, 88, 74, 48, 90, 83, 53, 110, 98, 50, 73, 117, 100, 109, 87, 67, 65, 81, 111, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 69, 48, 71, 65, 49, 85, 100, 69, 81, 82, 71, 10, 77, 69, 83, 67, 68, 110, 66, 121, 98, 50, 78, 108, 99, 110, 81, 117, 98, 109, 86, 48, 76, 110, 90, 108, 111, 66, 85, 71, 66, 87, 67, 71, 88, 103, 73, 66, 111, 65, 119, 77, 67, 108, 66, 84, 81, 121, 48, 119, 77, 68, 65, 119, 77, 68, 75, 103, 71, 119, 89, 70, 89, 73, 90, 101, 65, 103, 75, 103, 69, 103, 119, 81, 85, 107, 108, 71, 10, 76, 85, 111, 116, 77, 122, 69, 50, 77, 122, 85, 122, 78, 122, 77, 116, 78, 122, 66, 50, 66, 103, 78, 86, 72, 82, 56, 69, 98, 122, 66, 116, 77, 69, 97, 103, 82, 75, 66, 67, 104, 107, 66, 111, 100, 72, 82, 119, 79, 105, 56, 118, 100, 51, 100, 51, 76, 110, 78, 49, 99, 50, 78, 108, 99, 110, 82, 108, 76, 109, 100, 118, 89, 105, 53, 50, 10, 90, 83, 57, 115, 89, 51, 73, 118, 81, 48, 86, 83, 86, 69, 108, 71, 83, 85, 78, 66, 82, 69, 56, 116, 85, 107, 70, 74, 87, 105, 49, 84, 83, 69, 69, 122, 79, 68, 82, 68, 85, 107, 120, 69, 82, 86, 73, 117, 89, 51, 74, 115, 77, 67, 79, 103, 73, 97, 65, 102, 104, 104, 49, 115, 90, 71, 70, 119, 79, 105, 56, 118, 89, 87, 78, 121, 10, 89, 87, 108, 54, 76, 110, 78, 49, 99, 50, 78, 108, 99, 110, 82, 108, 76, 109, 100, 118, 89, 105, 53, 50, 90, 84, 65, 51, 66, 103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 66, 65, 81, 81, 114, 77, 67, 107, 119, 74, 119, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 77, 65, 71, 71, 71, 50, 104, 48, 100, 72, 65, 54, 76, 121, 57, 118, 10, 89, 51, 78, 119, 76, 110, 78, 49, 99, 50, 78, 108, 99, 110, 82, 108, 76, 109, 100, 118, 89, 105, 53, 50, 90, 84, 66, 66, 66, 103, 78, 86, 72, 83, 65, 69, 79, 106, 65, 52, 77, 68, 89, 71, 66, 109, 67, 71, 88, 103, 77, 66, 65, 106, 65, 115, 77, 67, 111, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 73, 66, 70, 104, 53, 111, 10, 100, 72, 82, 119, 79, 105, 56, 118, 100, 51, 100, 51, 76, 110, 78, 49, 99, 50, 78, 108, 99, 110, 82, 108, 76, 109, 100, 118, 89, 105, 53, 50, 90, 83, 57, 107, 99, 71, 77, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 73, 66, 65, 67, 116, 90, 54, 121, 75, 90, 117, 52, 83, 113, 10, 84, 57, 54, 81, 120, 116, 71, 71, 99, 83, 79, 101, 83, 119, 79, 82, 82, 51, 67, 55, 119, 74, 74, 103, 55, 79, 68, 85, 53, 50, 51, 71, 48, 43, 49, 110, 103, 51, 100, 83, 49, 102, 76, 108, 100, 54, 99, 50, 115, 117, 78, 85, 118, 116, 109, 55, 67, 112, 115, 82, 55, 50, 72, 48, 120, 112, 107, 122, 109, 102, 87, 118, 65, 68, 109, 78, 10, 103, 55, 43, 109, 118, 84, 86, 43, 76, 70, 119, 120, 78, 71, 57, 115, 50, 47, 78, 107, 65, 90, 105, 113, 108, 67, 120, 66, 51, 82, 87, 71, 121, 109, 115, 112, 84, 104, 98, 65, 83, 102, 122, 88, 103, 48, 103, 84, 66, 49, 71, 69, 77, 86, 75, 73, 117, 52, 89, 88, 120, 50, 115, 118, 105, 105, 67, 116, 120, 81, 117, 80, 99, 68, 52, 113, 10, 117, 120, 116, 120, 106, 55, 109, 107, 111, 80, 51, 89, 108, 100, 109, 118, 87, 98, 56, 108, 75, 53, 106, 112, 89, 53, 77, 118, 89, 66, 55, 69, 113, 118, 104, 51, 57, 89, 116, 115, 76, 43, 49, 43, 76, 114, 86, 80, 81, 65, 51, 117, 118, 70, 100, 51, 53, 57, 109, 50, 49, 68, 43, 86, 74, 122, 111, 103, 49, 101, 87, 117, 113, 50, 119, 49, 10, 110, 56, 71, 104, 72, 86, 110, 99, 104, 73, 72, 117, 84, 81, 102, 105, 83, 76, 97, 101, 83, 53, 85, 116, 81, 98, 72, 104, 54, 78, 53, 43, 76, 119, 85, 101, 97, 79, 54, 47, 117, 53, 66, 108, 79, 115, 106, 117, 54, 114, 69, 89, 78, 120, 120, 105, 107, 54, 83, 103, 77, 101, 120, 120, 98, 74, 72, 109, 112, 72, 109, 74, 87, 104, 83, 110, 10, 70, 70, 65, 70, 84, 75, 81, 65, 86, 122, 65, 115, 119, 98, 86, 104, 108, 116, 119, 43, 72, 111, 83, 118, 79, 85, 76, 80, 53, 100, 65, 115, 115, 83, 83, 56, 51, 48, 68, 68, 55, 88, 57, 106, 83, 114, 51, 104, 84, 120, 74, 107, 104, 112, 88, 122, 115, 79, 102, 73, 116, 43, 70, 84, 118, 90, 76, 109, 56, 119, 121, 87, 117, 101, 118, 111, 10, 53, 112, 76, 116, 112, 52, 69, 74, 70, 65, 118, 56, 108, 88, 114, 80, 106, 57, 89, 48, 84, 122, 89, 83, 51, 70, 55, 82, 78, 72, 88, 71, 82, 111, 65, 118, 108, 81, 83, 77, 120, 52, 98, 69, 113, 67, 97, 74, 113, 68, 56, 90, 109, 52, 71, 55, 85, 97, 82, 75, 104, 113, 115, 76, 69, 81, 43, 120, 114, 109, 78, 84, 98, 83, 106, 113, 10, 51, 84, 78, 87, 79, 66, 121, 121, 114, 89, 68, 84, 49, 51, 75, 57, 109, 109, 121, 90, 89, 43, 103, 65, 117, 48, 70, 50, 66, 98, 100, 98, 109, 82, 105, 75, 119, 55, 103, 83, 88, 70, 98, 80, 86, 103, 120, 57, 54, 79, 76, 80, 55, 98, 120, 48, 82, 47, 118, 117, 48, 120, 100, 79, 73, 107, 57, 87, 47, 49, 68, 122, 76, 117, 89, 53, 10, 112, 111, 76, 87, 99, 99, 114, 101, 116, 57, 87, 54, 97, 65, 106, 116, 109, 99, 122, 57, 111, 112, 76, 76, 97, 98, 105, 100, 43, 81, 113, 107, 112, 106, 53, 80, 107, 121, 103, 113, 89, 87, 119, 72, 74, 103, 68, 47, 108, 108, 57, 111, 104, 114, 105, 52, 122, 115, 112, 86, 52, 75, 117, 120, 80, 88, 43, 89, 49, 122, 77, 79, 87, 106, 51, 89, 10, 101, 77, 76, 69, 89, 67, 47, 72, 89, 118, 66, 104, 107, 100, 73, 52, 115, 80, 97, 101, 86, 100, 116, 65, 103, 65, 85, 83, 77, 56, 52, 100, 107, 112, 118, 82, 97, 98, 80, 47, 118, 47, 71, 83, 67, 109, 69, 49, 80, 57, 51, 43, 104, 118, 83, 56, 52, 66, 112, 120, 115, 50, 75, 109, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 104, 105, 110, 97, 32, 73, 110, 116, 101, 114, 110, 101, 116, 32, 78, 101, 116, 119, 111, 114, 107, 32, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 32, 67, 101, 110, 116, 101, 114, 32, 69, 86, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 57, 122, 67, 67, 65, 116, 43, 103, 65, 119, 73, 66, 65, 103, 73, 69, 83, 74, 56, 65, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 67, 66, 105, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 81, 48, 52, 120, 77, 106, 65, 119, 66, 103, 78, 86, 10, 66, 65, 111, 77, 75, 85, 78, 111, 97, 87, 53, 104, 73, 69, 108, 117, 100, 71, 86, 121, 98, 109, 86, 48, 73, 69, 53, 108, 100, 72, 100, 118, 99, 109, 115, 103, 83, 87, 53, 109, 98, 51, 74, 116, 89, 88, 82, 112, 98, 50, 52, 103, 81, 50, 86, 117, 100, 71, 86, 121, 77, 85, 99, 119, 82, 81, 89, 68, 86, 81, 81, 68, 68, 68, 53, 68, 10, 97, 71, 108, 117, 89, 83, 66, 74, 98, 110, 82, 108, 99, 109, 53, 108, 100, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 73, 69, 108, 117, 90, 109, 57, 121, 98, 87, 70, 48, 97, 87, 57, 117, 73, 69, 78, 108, 98, 110, 82, 108, 99, 105, 66, 70, 86, 105, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 88, 77, 103, 10, 85, 109, 57, 118, 100, 68, 65, 101, 70, 119, 48, 120, 77, 68, 65, 52, 77, 122, 69, 119, 78, 122, 69, 120, 77, 106, 86, 97, 70, 119, 48, 122, 77, 68, 65, 52, 77, 122, 69, 119, 78, 122, 69, 120, 77, 106, 86, 97, 77, 73, 71, 75, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 68, 84, 106, 69, 121, 77, 68, 65, 71, 10, 65, 49, 85, 69, 67, 103, 119, 112, 81, 50, 104, 112, 98, 109, 69, 103, 83, 87, 53, 48, 90, 88, 74, 117, 90, 88, 81, 103, 84, 109, 86, 48, 100, 50, 57, 121, 97, 121, 66, 74, 98, 109, 90, 118, 99, 109, 49, 104, 100, 71, 108, 118, 98, 105, 66, 68, 90, 87, 53, 48, 90, 88, 73, 120, 82, 122, 66, 70, 66, 103, 78, 86, 66, 65, 77, 77, 10, 80, 107, 78, 111, 97, 87, 53, 104, 73, 69, 108, 117, 100, 71, 86, 121, 98, 109, 86, 48, 73, 69, 53, 108, 100, 72, 100, 118, 99, 109, 115, 103, 83, 87, 53, 109, 98, 51, 74, 116, 89, 88, 82, 112, 98, 50, 52, 103, 81, 50, 86, 117, 100, 71, 86, 121, 73, 69, 86, 87, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 10, 99, 121, 66, 83, 98, 50, 57, 48, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 109, 51, 53, 122, 55, 114, 48, 55, 101, 75, 112, 107, 81, 48, 72, 49, 85, 78, 43, 85, 56, 105, 54, 121, 10, 106, 85, 113, 79, 82, 108, 84, 83, 73, 82, 76, 73, 79, 84, 74, 67, 66, 117, 109, 68, 49, 90, 57, 83, 55, 101, 86, 110, 65, 122, 116, 85, 119, 89, 121, 90, 109, 99, 122, 112, 119, 65, 47, 47, 68, 100, 109, 69, 69, 98, 75, 52, 48, 99, 116, 98, 51, 66, 55, 53, 97, 68, 70, 107, 52, 90, 118, 54, 100, 79, 116, 111, 117, 83, 67, 86, 10, 57, 56, 89, 80, 106, 85, 101, 115, 87, 103, 98, 100, 89, 97, 118, 105, 55, 78, 105, 102, 70, 121, 50, 99, 121, 106, 119, 49, 108, 49, 86, 120, 122, 85, 79, 70, 115, 85, 99, 87, 57, 83, 120, 84, 103, 72, 98, 80, 48, 119, 66, 107, 118, 85, 67, 90, 51, 99, 122, 89, 50, 56, 83, 102, 49, 104, 78, 102, 81, 89, 79, 76, 43, 81, 50, 72, 10, 107, 108, 89, 48, 98, 66, 111, 81, 67, 120, 102, 86, 87, 104, 121, 88, 87, 73, 81, 56, 104, 66, 111, 117, 88, 74, 69, 48, 98, 104, 108, 102, 102, 120, 100, 112, 120, 87, 88, 118, 97, 121, 72, 71, 49, 86, 65, 54, 118, 50, 71, 53, 66, 89, 51, 118, 98, 122, 81, 54, 115, 109, 56, 85, 89, 55, 56, 87, 79, 53, 117, 112, 75, 118, 50, 51, 10, 75, 122, 104, 109, 66, 115, 85, 115, 52, 113, 112, 110, 72, 107, 87, 110, 106, 81, 82, 109, 81, 118, 97, 80, 75, 43, 43, 73, 73, 71, 109, 80, 77, 111, 119, 85, 99, 57, 111, 114, 104, 112, 70, 106, 73, 112, 114, 121, 112, 57, 118, 79, 105, 89, 117, 114, 88, 99, 99, 85, 119, 86, 115, 119, 97, 104, 43, 120, 116, 53, 52, 117, 103, 81, 69, 67, 10, 55, 99, 43, 87, 88, 109, 80, 98, 113, 79, 89, 52, 116, 119, 73, 68, 65, 81, 65, 66, 111, 50, 77, 119, 89, 84, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 82, 56, 99, 107, 115, 53, 120, 56, 68, 98, 89, 113, 86, 80, 109, 54, 111, 89, 78, 74, 75, 105, 121, 111, 79, 67, 87, 84, 65, 80, 66, 103, 78, 86, 10, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 102, 72, 74, 76, 79, 99, 102, 65, 50, 50, 75, 108, 84, 53, 117, 113, 71, 68, 83, 83, 111, 115, 113, 68, 10, 103, 108, 107, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 69, 66, 65, 67, 114, 68, 120, 48, 77, 51, 106, 57, 50, 116, 112, 76, 73, 77, 55, 116, 119, 85, 98, 89, 56, 111, 112, 74, 104, 74, 121, 119, 121, 65, 54, 118, 80, 116, 73, 50, 90, 49, 102, 99, 88, 84, 73, 87, 100, 53, 10, 48, 88, 80, 70, 116, 81, 79, 51, 87, 75, 119, 77, 86, 67, 47, 71, 86, 104, 77, 80, 77, 100, 111, 71, 53, 50, 85, 55, 72, 87, 56, 50, 50, 56, 103, 100, 43, 102, 50, 65, 66, 115, 113, 106, 80, 87, 89, 87, 113, 74, 49, 77, 70, 110, 51, 65, 108, 85, 97, 49, 85, 101, 84, 105, 72, 57, 102, 113, 66, 107, 49, 106, 106, 90, 97, 77, 10, 55, 43, 99, 122, 86, 48, 73, 54, 54, 52, 122, 66, 101, 99, 104, 78, 100, 110, 51, 101, 57, 114, 71, 51, 103, 101, 67, 103, 43, 97, 70, 52, 82, 104, 99, 97, 86, 112, 106, 119, 84, 106, 50, 114, 72, 79, 51, 115, 79, 100, 119, 72, 83, 80, 100, 106, 47, 103, 97, 117, 119, 113, 82, 99, 97, 108, 115, 121, 105, 77, 88, 72, 77, 52, 87, 115, 10, 90, 107, 74, 72, 119, 108, 103, 107, 109, 101, 72, 108, 80, 117, 86, 49, 76, 73, 53, 68, 49, 108, 48, 56, 101, 66, 54, 111, 108, 89, 73, 112, 85, 78, 72, 82, 70, 114, 114, 118, 119, 98, 53, 54, 50, 98, 84, 89, 122, 66, 53, 77, 82, 117, 70, 51, 115, 84, 71, 114, 118, 83, 114, 73, 122, 111, 57, 117, 111, 86, 49, 47, 65, 51, 85, 48, 10, 53, 75, 50, 74, 82, 86, 82, 101, 118, 113, 52, 111, 112, 98, 115, 47, 101, 72, 110, 114, 99, 55, 77, 75, 68, 102, 50, 43, 121, 102, 100, 87, 114, 80, 97, 51, 55, 83, 43, 98, 73, 83, 110, 72, 79, 76, 97, 86, 120, 65, 84, 121, 119, 121, 51, 57, 70, 67, 113, 81, 109, 98, 107, 72, 122, 74, 56, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 119, 105, 115, 115, 99, 111, 109, 32, 82, 111, 111, 116, 32, 67, 65, 32, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 50, 84, 67, 67, 65, 56, 71, 103, 65, 119, 73, 66, 65, 103, 73, 81, 72, 112, 52, 111, 54, 69, 106, 121, 53, 101, 47, 68, 102, 69, 111, 101, 87, 104, 104, 110, 116, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 107, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 106, 97, 68, 69, 82, 77, 65, 56, 71, 65, 49, 85, 69, 67, 104, 77, 73, 85, 51, 100, 112, 99, 51, 78, 106, 98, 50, 48, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 115, 84, 72, 69, 82, 112, 90, 50, 108, 48, 89, 87, 119, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 85, 103, 85, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 77, 84, 69, 108, 78, 51, 97, 88, 78, 122, 89, 50, 57, 116, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 77, 106, 65, 101, 70, 119, 48, 120, 77, 84, 65, 50, 77, 106, 81, 119, 79, 68, 77, 52, 77, 84, 82, 97, 70, 119, 48, 122, 77, 84, 65, 50, 10, 77, 106, 85, 119, 78, 122, 77, 52, 77, 84, 82, 97, 77, 71, 81, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 109, 78, 111, 77, 82, 69, 119, 68, 119, 89, 68, 86, 81, 81, 75, 69, 119, 104, 84, 100, 50, 108, 122, 99, 50, 78, 118, 98, 84, 69, 108, 77, 67, 77, 71, 65, 49, 85, 69, 67, 120, 77, 99, 82, 71, 108, 110, 10, 97, 88, 82, 104, 98, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 83, 66, 84, 90, 88, 74, 50, 97, 87, 78, 108, 99, 122, 69, 98, 77, 66, 107, 71, 65, 49, 85, 69, 65, 120, 77, 83, 85, 51, 100, 112, 99, 51, 78, 106, 98, 50, 48, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 121, 77, 73, 73, 67, 10, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 103, 56, 65, 77, 73, 73, 67, 67, 103, 75, 67, 65, 103, 69, 65, 108, 85, 74, 79, 104, 74, 49, 82, 53, 116, 77, 74, 54, 72, 74, 97, 73, 50, 110, 98, 101, 72, 67, 79, 70, 118, 69, 114, 106, 119, 48, 68, 122, 112, 80, 77, 10, 76, 103, 65, 73, 101, 54, 115, 122, 106, 80, 84, 112, 81, 79, 89, 88, 84, 75, 117, 101, 117, 69, 99, 85, 77, 110, 99, 121, 51, 83, 103, 77, 51, 104, 104, 76, 88, 51, 97, 102, 43, 68, 107, 55, 47, 69, 54, 74, 50, 72, 122, 70, 90, 43, 43, 114, 48, 114, 107, 48, 88, 50, 115, 54, 56, 50, 81, 50, 122, 115, 75, 119, 122, 120, 78, 111, 10, 121, 115, 106, 76, 54, 55, 88, 105, 80, 83, 52, 104, 51, 43, 111, 115, 49, 79, 68, 53, 99, 74, 90, 77, 47, 50, 112, 89, 109, 76, 99, 88, 53, 66, 116, 83, 53, 88, 52, 72, 65, 66, 49, 102, 50, 117, 89, 43, 108, 81, 83, 51, 97, 89, 103, 53, 111, 85, 70, 103, 74, 87, 70, 76, 108, 84, 108, 111, 89, 104, 121, 120, 67, 119, 87, 74, 10, 119, 68, 97, 67, 70, 67, 69, 47, 114, 116, 117, 104, 47, 98, 120, 118, 72, 71, 67, 71, 116, 108, 79, 85, 83, 98, 107, 114, 82, 115, 86, 80, 65, 67, 117, 47, 111, 98, 118, 76, 80, 43, 68, 72, 86, 120, 120, 88, 54, 78, 90, 112, 43, 77, 69, 107, 85, 112, 50, 73, 86, 100, 51, 67, 104, 121, 53, 48, 73, 57, 65, 85, 47, 83, 112, 72, 10, 87, 114, 117, 109, 110, 102, 50, 85, 53, 78, 71, 75, 112, 86, 43, 71, 89, 51, 97, 70, 121, 54, 47, 47, 83, 83, 106, 56, 103, 79, 49, 77, 101, 100, 75, 55, 53, 77, 68, 118, 65, 101, 53, 81, 81, 81, 103, 49, 73, 51, 65, 114, 113, 82, 97, 48, 106, 71, 54, 70, 54, 98, 89, 82, 122, 122, 72, 100, 85, 121, 89, 98, 51, 121, 49, 97, 10, 83, 103, 74, 65, 47, 77, 84, 65, 116, 117, 107, 120, 71, 103, 103, 111, 53, 87, 68, 68, 72, 56, 83, 81, 106, 104, 66, 105, 89, 69, 81, 78, 55, 65, 113, 43, 86, 82, 104, 120, 76, 75, 88, 48, 115, 114, 119, 86, 89, 118, 56, 99, 52, 55, 52, 100, 50, 104, 53, 88, 115, 122, 120, 43, 122, 89, 73, 100, 107, 101, 78, 76, 54, 121, 120, 83, 10, 78, 76, 67, 75, 47, 82, 74, 79, 108, 114, 68, 114, 99, 72, 43, 101, 79, 102, 100, 109, 81, 114, 71, 114, 114, 70, 76, 97, 100, 107, 66, 88, 101, 121, 113, 57, 54, 71, 52, 68, 115, 103, 117, 65, 104, 89, 105, 100, 68, 77, 102, 67, 100, 55, 67, 97, 109, 108, 102, 48, 117, 80, 111, 84, 88, 71, 105, 84, 79, 109, 101, 107, 108, 57, 65, 98, 10, 109, 98, 101, 71, 77, 107, 116, 103, 50, 77, 55, 118, 48, 65, 120, 47, 108, 90, 57, 118, 104, 48, 43, 72, 105, 111, 53, 102, 67, 72, 121, 113, 87, 47, 120, 97, 118, 113, 71, 82, 110, 49, 86, 57, 84, 114, 65, 76, 97, 99, 121, 119, 108, 75, 105, 110, 104, 47, 76, 84, 83, 108, 68, 99, 88, 51, 75, 119, 70, 110, 85, 101, 121, 55, 81, 89, 10, 89, 112, 113, 119, 112, 122, 109, 113, 109, 53, 57, 109, 50, 73, 50, 109, 98, 74, 89, 86, 52, 43, 98, 121, 43, 80, 71, 68, 89, 109, 121, 55, 86, 101, 108, 104, 107, 54, 77, 57, 57, 98, 70, 88, 105, 48, 56, 106, 115, 74, 118, 108, 108, 71, 111, 118, 51, 52, 122, 102, 108, 86, 69, 112, 89, 75, 69, 76, 75, 101, 82, 99, 86, 86, 105, 51, 10, 113, 80, 121, 90, 55, 105, 86, 78, 84, 65, 54, 122, 48, 48, 121, 80, 104, 79, 103, 112, 68, 47, 48, 81, 86, 65, 75, 70, 121, 80, 110, 108, 119, 52, 118, 80, 53, 119, 56, 67, 65, 119, 69, 65, 65, 97, 79, 66, 104, 106, 67, 66, 103, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 89, 89, 119, 10, 72, 81, 89, 68, 86, 82, 48, 104, 66, 66, 89, 119, 70, 68, 65, 83, 66, 103, 100, 103, 104, 88, 81, 66, 85, 119, 73, 66, 66, 103, 100, 103, 104, 88, 81, 66, 85, 119, 73, 66, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 99, 119, 72, 81, 89, 68, 86, 82, 48, 79, 10, 66, 66, 89, 69, 70, 69, 48, 109, 73, 67, 75, 74, 83, 57, 80, 86, 112, 65, 113, 104, 98, 57, 55, 105, 69, 111, 72, 70, 56, 84, 119, 117, 77, 66, 56, 71, 65, 49, 85, 100, 73, 119, 81, 89, 77, 66, 97, 65, 70, 69, 48, 109, 73, 67, 75, 74, 83, 57, 80, 86, 112, 65, 113, 104, 98, 57, 55, 105, 69, 111, 72, 70, 56, 84, 119, 117, 10, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 67, 65, 81, 65, 121, 67, 114, 75, 107, 71, 56, 116, 57, 118, 111, 74, 88, 105, 98, 108, 113, 102, 47, 80, 48, 119, 83, 52, 82, 102, 98, 103, 90, 80, 110, 109, 51, 113, 75, 104, 121, 78, 50, 97, 98, 71, 117, 50, 115, 69, 122, 115, 79, 10, 118, 50, 76, 119, 110, 78, 43, 101, 101, 54, 70, 84, 83, 65, 53, 66, 101, 115, 111, 103, 112, 120, 99, 98, 116, 110, 106, 115, 81, 74, 72, 122, 81, 113, 48, 81, 119, 49, 122, 118, 47, 50, 66, 90, 102, 56, 50, 70, 111, 52, 115, 57, 83, 66, 119, 108, 65, 106, 120, 110, 102, 102, 85, 121, 54, 83, 56, 119, 53, 88, 50, 108, 101, 106, 106, 81, 10, 56, 50, 89, 113, 90, 104, 54, 78, 77, 52, 79, 75, 98, 51, 120, 117, 113, 70, 112, 49, 109, 114, 106, 88, 50, 108, 104, 73, 82, 69, 101, 111, 84, 80, 112, 77, 83, 81, 112, 75, 119, 104, 73, 51, 113, 69, 65, 77, 119, 56, 106, 104, 48, 70, 99, 78, 108, 122, 75, 86, 120, 122, 113, 102, 108, 57, 78, 88, 43, 65, 118, 101, 53, 88, 76, 122, 10, 111, 57, 118, 47, 116, 100, 104, 90, 115, 110, 80, 100, 84, 83, 112, 120, 115, 114, 112, 74, 57, 99, 115, 99, 49, 102, 86, 53, 121, 74, 109, 122, 47, 77, 70, 77, 100, 79, 79, 48, 118, 83, 107, 51, 70, 81, 81, 111, 72, 116, 53, 70, 82, 110, 68, 115, 114, 55, 112, 52, 68, 111, 111, 113, 122, 103, 66, 53, 51, 77, 66, 102, 71, 87, 99, 115, 10, 97, 48, 118, 118, 97, 71, 103, 76, 81, 43, 79, 115, 119, 87, 73, 74, 55, 54, 98, 100, 90, 87, 71, 103, 114, 52, 82, 86, 83, 74, 70, 83, 72, 77, 89, 108, 107, 83, 114, 81, 119, 83, 73, 106, 89, 86, 109, 118, 82, 82, 71, 70, 72, 81, 69, 107, 78, 73, 47, 80, 115, 47, 56, 88, 99, 105, 65, 84, 119, 111, 67, 113, 73, 83, 120, 120, 10, 79, 81, 55, 81, 106, 49, 122, 66, 48, 57, 71, 79, 73, 110, 74, 71, 84, 66, 50, 87, 114, 107, 57, 120, 115, 101, 69, 70, 75, 90, 90, 90, 57, 76, 117, 101, 100, 84, 51, 80, 68, 84, 99, 78, 89, 116, 115, 109, 106, 71, 79, 112, 73, 57, 57, 110, 66, 106, 120, 56, 79, 116, 111, 48, 81, 117, 70, 109, 116, 69, 89, 69, 51, 115, 97, 87, 10, 109, 65, 57, 76, 83, 72, 111, 107, 77, 110, 87, 82, 110, 54, 122, 51, 97, 79, 107, 113, 117, 86, 86, 108, 122, 108, 49, 104, 48, 121, 100, 119, 50, 68, 102, 43, 110, 55, 109, 118, 111, 67, 53, 87, 116, 54, 78, 108, 85, 101, 48, 55, 113, 120, 83, 47, 84, 70, 69, 68, 54, 70, 43, 75, 66, 90, 118, 117, 105, 109, 54, 99, 55, 55, 57, 111, 10, 43, 115, 106, 97, 67, 43, 78, 67, 121, 100, 65, 88, 70, 74, 121, 51, 83, 117, 67, 118, 107, 121, 99, 104, 86, 83, 97, 49, 90, 67, 43, 78, 56, 102, 43, 109, 81, 65, 87, 70, 66, 86, 122, 75, 66, 120, 108, 99, 67, 120, 77, 111, 84, 70, 104, 47, 119, 113, 88, 118, 82, 100, 112, 103, 48, 54, 53, 108, 89, 90, 49, 84, 103, 51, 84, 67, 10, 114, 118, 74, 99, 119, 104, 98, 116, 107, 106, 54, 69, 80, 110, 78, 103, 105, 76, 120, 50, 57, 67, 122, 80, 48, 72, 49, 57, 48, 55, 104, 101, 48, 90, 69, 83, 69, 79, 110, 78, 51, 99, 111, 108, 52, 57, 88, 116, 109, 83, 43, 43, 100, 89, 70, 76, 74, 80, 108, 70, 82, 112, 84, 74, 75, 83, 70, 84, 110, 67, 90, 70, 113, 104, 77, 88, 10, 53, 79, 102, 78, 101, 79, 73, 53, 119, 83, 115, 83, 110, 113, 97, 101, 71, 56, 88, 109, 68, 116, 107, 120, 50, 81, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 119, 105, 115, 115, 99, 111, 109, 32, 82, 111, 111, 116, 32, 69, 86, 32, 67, 65, 32, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 52, 68, 67, 67, 65, 56, 105, 103, 65, 119, 73, 66, 65, 103, 73, 82, 65, 80, 76, 54, 90, 79, 74, 48, 89, 57, 79, 78, 47, 82, 65, 100, 66, 66, 57, 50, 121, 108, 103, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 90, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 89, 50, 103, 120, 69, 84, 65, 80, 66, 103, 78, 86, 66, 65, 111, 84, 67, 70, 78, 51, 97, 88, 78, 122, 89, 50, 57, 116, 77, 83, 85, 119, 73, 119, 89, 68, 86, 81, 81, 76, 69, 120, 120, 69, 97, 87, 100, 112, 100, 71, 70, 115, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 73, 70, 78, 108, 10, 99, 110, 90, 112, 89, 50, 86, 122, 77, 82, 52, 119, 72, 65, 89, 68, 86, 81, 81, 68, 69, 120, 86, 84, 100, 50, 108, 122, 99, 50, 78, 118, 98, 83, 66, 83, 98, 50, 57, 48, 73, 69, 86, 87, 73, 69, 78, 66, 73, 68, 73, 119, 72, 104, 99, 78, 77, 84, 69, 119, 78, 106, 73, 48, 77, 68, 107, 48, 78, 84, 65, 52, 87, 104, 99, 78, 10, 77, 122, 69, 119, 78, 106, 73, 49, 77, 68, 103, 48, 78, 84, 65, 52, 87, 106, 66, 110, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 106, 97, 68, 69, 82, 77, 65, 56, 71, 65, 49, 85, 69, 67, 104, 77, 73, 85, 51, 100, 112, 99, 51, 78, 106, 98, 50, 48, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 115, 84, 10, 72, 69, 82, 112, 90, 50, 108, 48, 89, 87, 119, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 85, 103, 85, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 120, 72, 106, 65, 99, 66, 103, 78, 86, 66, 65, 77, 84, 70, 86, 78, 51, 97, 88, 78, 122, 89, 50, 57, 116, 73, 70, 74, 118, 98, 51, 81, 103, 82, 86, 89, 103, 10, 81, 48, 69, 103, 77, 106, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 77, 84, 51, 72, 83, 57, 88, 54, 108, 100, 115, 57, 51, 66, 100, 89, 55, 66, 120, 85, 103, 108, 103, 82, 67, 103, 122, 10, 111, 51, 112, 79, 67, 118, 114, 89, 54, 109, 121, 76, 85, 82, 89, 97, 86, 97, 53, 85, 74, 115, 84, 77, 82, 81, 100, 66, 84, 120, 66, 53, 102, 51, 72, 83, 101, 107, 52, 47, 79, 69, 54, 122, 65, 77, 97, 86, 121, 108, 118, 78, 119, 83, 113, 68, 49, 121, 99, 102, 77, 81, 52, 106, 70, 114, 99, 108, 121, 120, 121, 48, 117, 89, 65, 121, 10, 88, 104, 113, 100, 107, 47, 72, 111, 80, 71, 65, 115, 112, 49, 53, 88, 71, 86, 104, 82, 88, 114, 119, 115, 86, 103, 117, 52, 50, 79, 43, 76, 103, 114, 81, 56, 117, 77, 73, 107, 113, 66, 80, 72, 111, 67, 69, 50, 71, 51, 112, 88, 75, 83, 105, 110, 76, 114, 57, 120, 74, 90, 68, 122, 82, 73, 78, 112, 85, 75, 84, 107, 52, 82, 116, 105, 10, 71, 90, 81, 74, 111, 47, 80, 68, 118, 79, 47, 48, 118, 101, 122, 98, 69, 53, 51, 80, 110, 85, 103, 74, 85, 109, 102, 65, 78, 121, 107, 82, 72, 118, 118, 83, 69, 97, 101, 70, 71, 72, 82, 53, 53, 69, 43, 70, 70, 79, 116, 83, 78, 43, 75, 120, 82, 100, 106, 77, 68, 85, 78, 47, 114, 104, 80, 83, 97, 121, 115, 47, 112, 56, 76, 105, 10, 113, 71, 49, 50, 87, 48, 79, 102, 118, 114, 83, 100, 115, 121, 97, 71, 79, 120, 57, 47, 53, 102, 76, 111, 90, 105, 103, 87, 74, 100, 66, 76, 108, 122, 105, 110, 53, 77, 56, 74, 48, 84, 98, 68, 67, 55, 55, 97, 79, 48, 82, 89, 106, 98, 55, 120, 110, 103, 108, 114, 80, 118, 77, 121, 120, 121, 117, 72, 120, 117, 120, 101, 110, 80, 97, 72, 10, 90, 97, 48, 122, 75, 99, 81, 118, 105, 100, 109, 53, 121, 56, 107, 68, 110, 102, 116, 115, 108, 70, 71, 88, 69, 66, 117, 71, 67, 120, 111, 98, 80, 47, 89, 67, 102, 110, 118, 85, 120, 86, 70, 107, 75, 74, 51, 49, 48, 54, 121, 68, 103, 89, 106, 84, 100, 76, 82, 90, 110, 99, 72, 114, 89, 84, 78, 97, 82, 100, 72, 76, 79, 100, 65, 71, 10, 97, 108, 78, 103, 72, 97, 47, 50, 43, 50, 109, 56, 97, 116, 119, 66, 122, 55, 51, 53, 106, 57, 109, 57, 87, 56, 69, 54, 88, 52, 55, 97, 68, 48, 117, 112, 109, 53, 48, 113, 75, 71, 115, 97, 67, 110, 119, 56, 113, 121, 73, 76, 53, 88, 99, 116, 99, 102, 97, 67, 78, 89, 71, 117, 43, 72, 117, 66, 53, 117, 114, 43, 114, 80, 81, 97, 10, 109, 51, 82, 99, 54, 73, 56, 107, 57, 108, 50, 100, 82, 115, 81, 115, 48, 104, 52, 114, 73, 87, 113, 68, 74, 50, 100, 86, 83, 113, 84, 106, 121, 68, 75, 88, 90, 112, 66, 121, 50, 117, 80, 85, 90, 67, 53, 102, 52, 54, 70, 113, 57, 109, 68, 85, 53, 122, 88, 78, 121, 115, 82, 111, 106, 100, 100, 120, 121, 78, 77, 107, 77, 51, 79, 120, 10, 98, 80, 108, 113, 52, 83, 106, 98, 88, 56, 89, 57, 54, 76, 53, 86, 53, 106, 99, 98, 55, 83, 84, 90, 68, 120, 109, 80, 88, 50, 77, 89, 87, 70, 67, 66, 85, 87, 86, 118, 56, 112, 57, 43, 97, 103, 84, 110, 78, 67, 82, 120, 117, 110, 90, 76, 87, 66, 52, 90, 118, 82, 86, 103, 82, 97, 111, 77, 69, 107, 65, 66, 110, 82, 68, 105, 10, 120, 122, 103, 72, 99, 103, 112, 108, 119, 76, 97, 55, 74, 83, 110, 97, 70, 112, 54, 76, 78, 89, 116, 104, 55, 101, 86, 120, 86, 52, 79, 49, 80, 72, 71, 102, 52, 48, 43, 47, 102, 104, 54, 66, 110, 48, 71, 88, 65, 103, 77, 66, 65, 65, 71, 106, 103, 89, 89, 119, 103, 89, 77, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 10, 66, 65, 81, 68, 65, 103, 71, 71, 77, 66, 48, 71, 65, 49, 85, 100, 73, 81, 81, 87, 77, 66, 81, 119, 69, 103, 89, 72, 89, 73, 86, 48, 65, 86, 77, 67, 65, 103, 89, 72, 89, 73, 86, 48, 65, 86, 77, 67, 65, 106, 65, 83, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 67, 68, 65, 71, 65, 81, 72, 47, 65, 103, 69, 68, 10, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 70, 50, 97, 87, 66, 98, 106, 50, 73, 84, 89, 49, 120, 48, 107, 98, 66, 98, 107, 85, 101, 56, 56, 83, 65, 110, 84, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 82, 70, 50, 97, 87, 66, 98, 106, 50, 73, 84, 89, 49, 120, 48, 107, 98, 66, 10, 98, 107, 85, 101, 56, 56, 83, 65, 110, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, 67, 65, 103, 69, 65, 108, 68, 112, 122, 66, 112, 57, 83, 83, 122, 66, 99, 49, 80, 54, 120, 88, 67, 88, 53, 49, 52, 53, 118, 57, 89, 100, 107, 110, 43, 48, 85, 106, 114, 103, 69, 106, 105, 104, 76, 10, 106, 54, 112, 55, 106, 106, 109, 48, 50, 86, 106, 50, 101, 54, 69, 49, 67, 113, 71, 100, 105, 118, 100, 106, 53, 101, 117, 57, 79, 89, 76, 85, 52, 51, 111, 116, 98, 57, 56, 84, 80, 76, 114, 43, 102, 108, 97, 89, 67, 47, 78, 85, 110, 56, 49, 69, 84, 109, 52, 56, 52, 84, 52, 86, 118, 119, 89, 109, 110, 101, 84, 119, 107, 76, 98, 85, 10, 119, 112, 52, 119, 76, 104, 47, 118, 120, 51, 114, 69, 85, 77, 102, 113, 101, 57, 112, 81, 121, 51, 111, 109, 121, 119, 67, 48, 87, 113, 117, 49, 107, 120, 43, 65, 105, 89, 81, 69, 108, 89, 50, 78, 102, 119, 109, 84, 118, 57, 83, 111, 113, 79, 82, 106, 98, 100, 108, 107, 53, 76, 103, 112, 87, 103, 105, 47, 85, 79, 71, 69, 68, 49, 86, 55, 10, 88, 119, 103, 105, 71, 47, 87, 57, 109, 82, 52, 85, 57, 115, 55, 48, 87, 66, 67, 67, 115, 119, 111, 57, 71, 99, 71, 47, 87, 54, 117, 113, 109, 100, 106, 121, 77, 98, 51, 108, 79, 71, 98, 99, 87, 65, 88, 72, 55, 87, 77, 97, 76, 103, 113, 88, 102, 73, 101, 84, 75, 55, 75, 75, 52, 47, 72, 115, 71, 79, 86, 49, 116, 105, 109, 72, 10, 53, 57, 121, 76, 71, 110, 54, 48, 50, 77, 110, 84, 105, 104, 100, 115, 102, 83, 108, 69, 118, 111, 113, 113, 57, 88, 52, 54, 76, 109, 103, 120, 107, 55, 108, 113, 50, 112, 114, 103, 50, 43, 107, 117, 112, 89, 84, 78, 72, 65, 113, 52, 83, 103, 106, 53, 110, 80, 70, 104, 74, 112, 105, 84, 116, 51, 116, 109, 55, 74, 70, 101, 51, 86, 69, 47, 10, 50, 51, 77, 80, 114, 81, 82, 89, 67, 100, 48, 69, 65, 112, 85, 75, 80, 116, 78, 50, 51, 54, 89, 81, 72, 111, 65, 57, 54, 77, 50, 107, 90, 78, 69, 122, 120, 53, 76, 72, 52, 107, 53, 69, 52, 119, 110, 74, 84, 115, 74, 100, 104, 119, 52, 83, 110, 114, 56, 80, 121, 81, 85, 81, 51, 110, 113, 106, 115, 84, 122, 121, 80, 54, 87, 113, 10, 74, 51, 109, 116, 77, 88, 48, 102, 47, 102, 119, 90, 97, 99, 88, 100, 117, 84, 57, 56, 122, 99, 97, 48, 119, 106, 65, 101, 102, 109, 54, 83, 49, 51, 57, 104, 100, 108, 113, 80, 54, 53, 86, 78, 118, 66, 70, 117, 73, 88, 120, 90, 78, 53, 110, 81, 66, 114, 122, 53, 66, 109, 48, 121, 70, 113, 88, 90, 97, 97, 106, 104, 51, 68, 121, 65, 10, 72, 109, 66, 82, 51, 78, 100, 85, 73, 82, 55, 75, 89, 110, 100, 80, 43, 116, 105, 80, 115, 121, 115, 54, 68, 88, 104, 121, 121, 87, 104, 66, 87, 107, 100, 75, 119, 113, 80, 114, 71, 116, 99, 75, 113, 122, 119, 121, 86, 99, 103, 75, 69, 90, 122, 102, 100, 78, 98, 119, 81, 66, 85, 100, 121, 76, 109, 80, 116, 84, 98, 70, 114, 47, 103, 105, 10, 117, 77, 111, 100, 56, 57, 97, 50, 71, 81, 43, 102, 89, 87, 86, 113, 54, 110, 84, 73, 102, 73, 47, 68, 84, 49, 49, 108, 103, 104, 47, 90, 68, 89, 110, 97, 100, 88, 76, 55, 55, 47, 70, 72, 90, 120, 79, 122, 121, 78, 69, 90, 105, 67, 99, 109, 109, 112, 108, 53, 102, 120, 55, 107, 76, 68, 57, 55, 55, 118, 72, 101, 84, 89, 117, 87, 10, 108, 56, 80, 86, 80, 51, 119, 98, 73, 43, 50, 107, 115, 120, 48, 87, 99, 107, 78, 76, 73, 79, 70, 90, 102, 115, 76, 111, 114, 83, 97, 47, 111, 118, 99, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 65, 32, 68, 105, 115, 105, 103, 32, 82, 111, 111, 116, 32, 82, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 97, 84, 67, 67, 65, 49, 71, 103, 65, 119, 73, 66, 65, 103, 73, 74, 65, 77, 77, 68, 109, 117, 53, 81, 107, 71, 52, 111, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 77, 70, 73, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 78, 76, 77, 82, 77, 119, 10, 69, 81, 89, 68, 86, 81, 81, 72, 69, 119, 112, 67, 99, 109, 70, 48, 97, 88, 78, 115, 89, 88, 90, 104, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 75, 69, 119, 112, 69, 97, 88, 78, 112, 90, 121, 66, 104, 76, 110, 77, 117, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 68, 69, 120, 66, 68, 81, 83, 66, 69, 97, 88, 78, 112, 10, 90, 121, 66, 83, 98, 50, 57, 48, 73, 70, 73, 120, 77, 66, 52, 88, 68, 84, 69, 121, 77, 68, 99, 120, 79, 84, 65, 53, 77, 68, 89, 49, 78, 108, 111, 88, 68, 84, 81, 121, 77, 68, 99, 120, 79, 84, 65, 53, 77, 68, 89, 49, 78, 108, 111, 119, 85, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 85, 48, 115, 120, 10, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 99, 84, 67, 107, 74, 121, 89, 88, 82, 112, 99, 50, 120, 104, 100, 109, 69, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 111, 84, 67, 107, 82, 112, 99, 50, 108, 110, 73, 71, 69, 117, 99, 121, 52, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 77, 84, 69, 69, 78, 66, 73, 69, 82, 112, 10, 99, 50, 108, 110, 73, 70, 74, 118, 98, 51, 81, 103, 85, 106, 69, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 113, 119, 51, 106, 51, 51, 74, 105, 106, 112, 49, 112, 101, 100, 120, 105, 121, 10, 51, 81, 82, 107, 68, 50, 80, 57, 109, 53, 89, 74, 103, 78, 88, 111, 113, 113, 88, 105, 110, 67, 97, 85, 79, 117, 105, 90, 99, 52, 121, 100, 51, 57, 102, 102, 103, 47, 78, 52, 84, 48, 68, 104, 102, 57, 75, 110, 48, 117, 88, 75, 69, 53, 80, 110, 55, 99, 90, 51, 88, 122, 97, 49, 108, 75, 47, 111, 79, 73, 55, 98, 109, 43, 86, 56, 10, 117, 56, 121, 78, 54, 51, 86, 122, 52, 83, 84, 78, 53, 113, 99, 116, 71, 83, 55, 89, 49, 111, 112, 114, 70, 79, 115, 73, 89, 103, 114, 89, 51, 76, 77, 65, 84, 99, 77, 106, 102, 70, 57, 68, 67, 67, 77, 121, 69, 116, 122, 116, 68, 75, 51, 65, 102, 81, 43, 108, 101, 107, 76, 90, 87, 110, 68, 90, 118, 54, 102, 88, 65, 82, 122, 50, 10, 109, 54, 117, 79, 116, 48, 113, 71, 101, 75, 65, 101, 86, 106, 71, 117, 55, 52, 73, 75, 103, 69, 72, 51, 71, 56, 109, 117, 113, 122, 73, 109, 49, 67, 120, 114, 55, 88, 49, 114, 53, 79, 74, 101, 73, 103, 112, 70, 121, 52, 81, 120, 84, 97, 122, 43, 50, 57, 70, 72, 117, 118, 108, 103, 108, 122, 109, 120, 90, 99, 102, 101, 43, 53, 110, 107, 10, 67, 105, 75, 120, 76, 85, 51, 108, 83, 67, 90, 112, 113, 43, 75, 113, 56, 47, 118, 56, 107, 105, 107, 121, 54, 98, 77, 43, 84, 82, 56, 110, 111, 99, 50, 79, 117, 82, 102, 55, 74, 84, 55, 74, 98, 118, 78, 51, 50, 103, 48, 83, 57, 108, 51, 72, 117, 122, 89, 81, 49, 86, 84, 87, 56, 43, 68, 105, 82, 48, 106, 109, 51, 104, 84, 97, 10, 89, 86, 75, 118, 74, 114, 84, 49, 99, 85, 47, 74, 49, 57, 73, 71, 51, 50, 80, 75, 47, 121, 72, 111, 87, 81, 98, 103, 67, 78, 87, 69, 70, 86, 80, 51, 81, 43, 86, 56, 120, 97, 67, 74, 109, 71, 116, 122, 120, 109, 106, 79, 90, 100, 54, 57, 102, 119, 88, 51, 115, 101, 55, 50, 86, 54, 70, 103, 108, 99, 88, 77, 54, 112, 77, 54, 10, 118, 112, 109, 117, 109, 119, 75, 106, 114, 99, 107, 87, 116, 99, 55, 100, 88, 112, 108, 52, 102, 104, 111, 53, 102, 114, 76, 65, 66, 97, 84, 65, 103, 113, 87, 106, 82, 53, 54, 77, 54, 108, 121, 50, 118, 71, 102, 98, 53, 105, 112, 78, 48, 103, 84, 99, 111, 54, 53, 70, 57, 55, 121, 76, 110, 66, 121, 110, 49, 116, 85, 68, 51, 65, 106, 76, 10, 76, 104, 98, 75, 88, 69, 65, 122, 54, 71, 102, 68, 76, 117, 101, 109, 82, 79, 111, 82, 82, 82, 119, 49, 90, 83, 48, 101, 82, 87, 69, 107, 71, 52, 73, 117, 112, 90, 48, 122, 88, 87, 88, 52, 81, 102, 107, 117, 121, 53, 81, 47, 72, 54, 77, 77, 77, 83, 82, 69, 55, 99, 100, 101, 114, 86, 67, 54, 120, 107, 71, 98, 114, 80, 65, 88, 10, 90, 99, 68, 52, 88, 87, 57, 98, 111, 65, 111, 48, 80, 79, 55, 88, 54, 111, 105, 102, 109, 80, 109, 118, 84, 105, 84, 54, 108, 55, 74, 107, 100, 116, 113, 114, 57, 79, 51, 106, 119, 50, 68, 118, 49, 102, 107, 67, 121, 67, 50, 102, 103, 54, 57, 110, 97, 81, 97, 110, 77, 86, 88, 86, 122, 48, 116, 118, 47, 119, 81, 70, 120, 49, 105, 115, 10, 88, 120, 89, 98, 53, 100, 75, 106, 54, 122, 72, 98, 72, 122, 77, 86, 84, 100, 68, 121, 112, 86, 80, 49, 121, 43, 69, 57, 84, 109, 103, 116, 50, 66, 76, 100, 113, 118, 76, 109, 84, 90, 116, 74, 53, 99, 85, 111, 111, 98, 113, 119, 87, 115, 97, 103, 116, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 10, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 105, 81, 113, 48, 79, 74, 77, 97, 53, 113, 118, 117, 109, 53, 69, 89, 43, 102, 85, 56, 80, 106, 88, 81, 10, 48, 52, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 73, 66, 65, 68, 75, 76, 57, 112, 49, 75, 121, 98, 52, 85, 53, 89, 121, 115, 79, 77, 111, 54, 67, 100, 81, 98, 122, 111, 97, 122, 51, 101, 118, 85, 117, 105, 105, 43, 69, 113, 53, 70, 76, 65, 82, 48, 114, 66, 78, 82, 10, 120, 86, 103, 89, 90, 107, 50, 67, 50, 116, 88, 99, 107, 56, 65, 110, 52, 98, 53, 56, 110, 49, 75, 101, 69, 108, 98, 50, 49, 90, 121, 112, 57, 72, 87, 99, 43, 106, 99, 83, 106, 120, 121, 84, 55, 70, 102, 43, 66, 119, 43, 114, 49, 82, 76, 51, 68, 54, 53, 104, 88, 108, 97, 65, 83, 102, 88, 56, 77, 80, 87, 98, 84, 120, 57, 66, 10, 76, 120, 121, 69, 48, 52, 110, 72, 52, 116, 111, 67, 100, 117, 48, 74, 122, 50, 122, 66, 117, 66, 121, 68, 72, 66, 98, 54, 108, 77, 49, 57, 111, 77, 103, 89, 48, 115, 105, 100, 98, 118, 87, 57, 97, 100, 82, 116, 80, 84, 88, 111, 72, 113, 74, 80, 89, 78, 99, 72, 75, 102, 121, 121, 111, 54, 83, 100, 98, 104, 87, 83, 86, 104, 108, 77, 10, 67, 114, 68, 112, 102, 78, 73, 90, 84, 85, 74, 71, 55, 76, 51, 57, 57, 108, 100, 98, 51, 90, 104, 43, 112, 69, 51, 77, 99, 103, 79, 68, 87, 70, 51, 118, 107, 122, 112, 66, 101, 109, 79, 113, 102, 68, 113, 111, 57, 97, 121, 107, 48, 100, 50, 105, 76, 98, 89, 113, 47, 74, 56, 66, 106, 117, 73, 81, 115, 99, 84, 75, 53, 71, 102, 98, 10, 86, 83, 85, 90, 80, 47, 51, 111, 78, 110, 54, 122, 52, 101, 71, 66, 114, 120, 69, 87, 105, 49, 67, 88, 89, 66, 109, 67, 65, 77, 66, 114, 84, 88, 79, 52, 48, 82, 77, 72, 80, 117, 113, 50, 77, 85, 47, 119, 81, 112, 112, 116, 52, 104, 70, 48, 53, 90, 83, 115, 106, 89, 83, 86, 80, 67, 71, 118, 120, 100, 112, 72, 121, 78, 56, 53, 10, 89, 109, 76, 76, 87, 49, 65, 76, 49, 52, 70, 65, 66, 90, 121, 98, 55, 98, 113, 50, 105, 120, 52, 69, 98, 53, 89, 103, 79, 101, 50, 107, 102, 83, 110, 98, 83, 77, 54, 67, 51, 78, 81, 67, 106, 82, 48, 69, 77, 86, 114, 72, 83, 47, 66, 115, 89, 86, 76, 88, 116, 70, 72, 67, 103, 87, 122, 78, 52, 102, 117, 110, 111, 100, 75, 83, 10, 100, 115, 43, 120, 68, 122, 100, 89, 112, 80, 74, 83, 99, 87, 99, 47, 68, 73, 104, 52, 103, 73, 110, 66, 121, 76, 85, 102, 107, 109, 79, 43, 112, 51, 113, 75, 86, 105, 119, 97, 113, 75, 97, 99, 116, 86, 50, 122, 89, 57, 65, 84, 73, 75, 72, 114, 107, 87, 122, 81, 106, 88, 50, 118, 51, 119, 118, 107, 70, 55, 109, 71, 110, 106, 105, 120, 10, 108, 65, 120, 89, 106, 79, 66, 86, 113, 106, 116, 106, 98, 90, 113, 74, 89, 76, 104, 107, 75, 112, 76, 71, 78, 47, 82, 43, 81, 48, 79, 51, 99, 43, 103, 66, 53, 51, 43, 88, 68, 57, 102, 121, 101, 120, 110, 57, 71, 116, 101, 80, 121, 102, 113, 70, 97, 51, 113, 100, 110, 111, 109, 50, 112, 105, 105, 90, 107, 52, 104, 65, 57, 122, 55, 78, 10, 85, 97, 80, 75, 54, 117, 57, 53, 82, 121, 71, 49, 47, 106, 76, 105, 120, 56, 78, 82, 98, 55, 54, 65, 100, 80, 67, 107, 119, 122, 114, 121, 84, 43, 108, 102, 51, 120, 107, 75, 56, 106, 115, 84, 81, 54, 119, 120, 112, 76, 80, 110, 54, 47, 119, 89, 49, 103, 71, 112, 56, 121, 113, 80, 78, 103, 55, 114, 116, 76, 71, 56, 116, 48, 122, 74, 10, 97, 55, 43, 104, 56, 57, 110, 48, 55, 101, 76, 119, 52, 43, 49, 107, 110, 106, 48, 118, 108, 108, 74, 80, 103, 70, 79, 76, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 65, 32, 68, 105, 115, 105, 103, 32, 82, 111, 111, 116, 32, 82, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 97, 84, 67, 67, 65, 49, 71, 103, 65, 119, 73, 66, 65, 103, 73, 74, 65, 74, 75, 52, 105, 78, 117, 119, 105, 115, 70, 106, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 77, 70, 73, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 78, 76, 77, 82, 77, 119, 10, 69, 81, 89, 68, 86, 81, 81, 72, 69, 119, 112, 67, 99, 109, 70, 48, 97, 88, 78, 115, 89, 88, 90, 104, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 75, 69, 119, 112, 69, 97, 88, 78, 112, 90, 121, 66, 104, 76, 110, 77, 117, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 68, 69, 120, 66, 68, 81, 83, 66, 69, 97, 88, 78, 112, 10, 90, 121, 66, 83, 98, 50, 57, 48, 73, 70, 73, 121, 77, 66, 52, 88, 68, 84, 69, 121, 77, 68, 99, 120, 79, 84, 65, 53, 77, 84, 85, 122, 77, 70, 111, 88, 68, 84, 81, 121, 77, 68, 99, 120, 79, 84, 65, 53, 77, 84, 85, 122, 77, 70, 111, 119, 85, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 85, 48, 115, 120, 10, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 99, 84, 67, 107, 74, 121, 89, 88, 82, 112, 99, 50, 120, 104, 100, 109, 69, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 111, 84, 67, 107, 82, 112, 99, 50, 108, 110, 73, 71, 69, 117, 99, 121, 52, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 77, 84, 69, 69, 78, 66, 73, 69, 82, 112, 10, 99, 50, 108, 110, 73, 70, 74, 118, 98, 51, 81, 103, 85, 106, 73, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 105, 111, 56, 81, 65, 67, 100, 97, 70, 88, 83, 49, 116, 70, 80, 98, 67, 10, 119, 51, 79, 101, 78, 99, 74, 120, 86, 88, 54, 66, 43, 54, 116, 71, 85, 79, 68, 66, 102, 69, 108, 52, 53, 113, 116, 53, 87, 68, 122, 97, 47, 51, 119, 99, 110, 57, 105, 88, 65, 110, 103, 43, 97, 48, 69, 69, 54, 85, 71, 57, 118, 103, 77, 115, 82, 102, 89, 118, 90, 78, 83, 114, 88, 97, 78, 72, 80, 87, 83, 98, 54, 87, 105, 97, 10, 120, 115, 119, 98, 80, 55, 113, 43, 115, 111, 115, 48, 65, 105, 54, 89, 86, 82, 110, 56, 106, 71, 43, 113, 88, 57, 112, 77, 122, 107, 48, 68, 73, 97, 80, 89, 48, 106, 83, 84, 86, 112, 98, 76, 84, 65, 119, 65, 70, 106, 120, 102, 71, 115, 51, 73, 120, 50, 121, 109, 114, 100, 77, 120, 112, 55, 122, 111, 53, 101, 70, 109, 49, 116, 76, 55, 10, 65, 55, 82, 66, 90, 99, 107, 81, 114, 103, 52, 70, 89, 56, 97, 65, 97, 109, 107, 119, 47, 100, 76, 117, 107, 79, 56, 78, 74, 57, 43, 102, 108, 88, 80, 48, 52, 83, 88, 97, 98, 66, 98, 101, 81, 84, 103, 48, 54, 111, 118, 56, 48, 101, 103, 69, 70, 71, 69, 116, 81, 88, 54, 115, 120, 51, 100, 79, 121, 49, 70, 85, 43, 49, 54, 83, 10, 71, 66, 115, 69, 87, 109, 106, 71, 121, 99, 84, 54, 116, 120, 79, 103, 109, 76, 99, 82, 75, 55, 102, 87, 86, 56, 120, 56, 110, 104, 102, 82, 121, 121, 88, 43, 104, 107, 52, 107, 76, 108, 89, 77, 101, 69, 50, 101, 65, 82, 75, 109, 75, 54, 99, 66, 90, 87, 53, 56, 89, 104, 50, 69, 104, 78, 47, 113, 119, 71, 117, 49, 112, 83, 113, 86, 10, 103, 56, 78, 84, 69, 81, 120, 122, 72, 81, 117, 121, 82, 112, 68, 82, 81, 106, 114, 79, 81, 71, 54, 86, 114, 102, 47, 71, 108, 75, 49, 117, 108, 52, 83, 79, 102, 87, 43, 101, 105, 111, 65, 78, 83, 87, 49, 122, 52, 110, 117, 83, 72, 115, 80, 122, 119, 102, 80, 114, 76, 103, 86, 118, 50, 82, 118, 80, 78, 51, 89, 69, 121, 76, 82, 97, 10, 53, 66, 101, 110, 121, 57, 49, 50, 72, 57, 65, 90, 100, 117, 103, 115, 66, 98, 80, 87, 110, 68, 84, 89, 108, 116, 120, 104, 104, 53, 69, 70, 53, 69, 81, 73, 77, 56, 72, 97, 117, 81, 104, 108, 49, 75, 54, 121, 78, 103, 51, 114, 117, 106, 105, 54, 68, 79, 87, 98, 110, 117, 117, 78, 90, 116, 50, 90, 122, 57, 97, 74, 81, 102, 89, 69, 10, 107, 111, 111, 112, 75, 87, 49, 114, 79, 104, 122, 110, 100, 88, 48, 67, 99, 81, 55, 122, 119, 79, 101, 57, 121, 120, 110, 100, 110, 87, 67, 121, 119, 109, 90, 103, 116, 114, 69, 69, 55, 115, 110, 109, 104, 114, 109, 97, 90, 107, 67, 111, 53, 120, 72, 116, 103, 85, 85, 68, 105, 47, 90, 110, 87, 101, 106, 66, 66, 104, 71, 57, 51, 99, 43, 65, 10, 65, 107, 57, 108, 81, 72, 104, 99, 82, 49, 68, 73, 109, 43, 89, 102, 103, 88, 118, 107, 82, 75, 104, 98, 104, 90, 114, 105, 51, 108, 114, 86, 120, 47, 107, 54, 82, 71, 90, 76, 53, 68, 74, 85, 102, 79, 82, 115, 110, 76, 77, 79, 80, 82, 101, 105, 115, 106, 81, 83, 49, 110, 54, 121, 113, 69, 109, 55, 48, 88, 111, 111, 81, 76, 54, 105, 10, 70, 104, 47, 102, 53, 68, 99, 102, 69, 88, 80, 55, 107, 65, 112, 108, 81, 54, 73, 78, 102, 80, 103, 71, 65, 86, 85, 122, 102, 98, 65, 78, 117, 80, 84, 49, 114, 113, 86, 67, 86, 51, 119, 50, 69, 89, 120, 55, 88, 115, 81, 68, 110, 89, 120, 53, 110, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 10, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 116, 90, 110, 52, 114, 55, 67, 85, 57, 101, 77, 103, 49, 103, 113, 116, 122, 107, 53, 87, 112, 67, 53, 117, 10, 81, 117, 48, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 73, 66, 65, 67, 89, 71, 88, 110, 68, 110, 90, 84, 80, 73, 103, 109, 55, 90, 110, 66, 99, 54, 71, 51, 112, 109, 115, 103, 72, 50, 101, 68, 116, 112, 88, 105, 47, 113, 47, 48, 55, 53, 75, 77, 79, 89, 75, 109, 70, 77, 10, 116, 67, 81, 83, 105, 110, 49, 116, 69, 82, 84, 51, 110, 76, 88, 75, 53, 114, 121, 101, 74, 52, 53, 77, 71, 99, 105, 112, 118, 88, 114, 65, 49, 122, 89, 79, 98, 89, 86, 121, 98, 113, 106, 71, 111, 109, 51, 50, 43, 110, 78, 106, 102, 55, 120, 117, 101, 81, 103, 99, 110, 89, 113, 102, 71, 111, 112, 84, 112, 116, 105, 55, 50, 84, 86, 86, 10, 115, 82, 72, 70, 113, 81, 79, 122, 86, 106, 117, 53, 104, 74, 77, 105, 88, 110, 55, 66, 57, 104, 74, 83, 105, 43, 111, 115, 90, 55, 122, 43, 78, 107, 122, 49, 117, 77, 47, 82, 115, 48, 109, 83, 79, 57, 77, 112, 68, 112, 107, 98, 108, 118, 100, 104, 117, 68, 118, 69, 75, 55, 90, 52, 98, 76, 81, 106, 98, 47, 68, 57, 48, 55, 74, 101, 10, 100, 82, 43, 90, 108, 97, 105, 115, 57, 116, 114, 104, 120, 84, 70, 55, 43, 57, 70, 71, 115, 57, 75, 56, 90, 55, 82, 105, 86, 76, 111, 74, 57, 50, 79, 119, 107, 54, 75, 97, 43, 101, 108, 83, 76, 111, 116, 103, 69, 113, 118, 56, 57, 87, 66, 87, 55, 120, 66, 99, 105, 56, 81, 97, 81, 116, 121, 68, 87, 50, 81, 79, 121, 55, 87, 56, 10, 49, 107, 47, 66, 102, 68, 120, 117, 106, 82, 78, 116, 43, 51, 118, 114, 77, 78, 68, 99, 84, 97, 47, 70, 49, 98, 97, 108, 84, 70, 116, 120, 121, 101, 103, 120, 118, 117, 103, 52, 66, 107, 105, 104, 71, 117, 76, 113, 48, 116, 52, 83, 79, 86, 103, 97, 47, 52, 65, 79, 103, 110, 88, 109, 116, 56, 107, 72, 98, 65, 55, 118, 47, 122, 106, 120, 10, 109, 72, 72, 69, 116, 51, 56, 79, 70, 100, 65, 108, 97, 98, 48, 105, 110, 83, 118, 116, 66, 102, 90, 71, 82, 54, 122, 116, 119, 80, 68, 85, 79, 43, 76, 115, 55, 112, 90, 98, 107, 66, 78, 79, 72, 108, 89, 54, 54, 55, 68, 118, 108, 114, 117, 87, 73, 120, 71, 54, 56, 107, 79, 71, 100, 71, 83, 86, 121, 67, 104, 49, 51, 120, 48, 49, 10, 117, 116, 73, 51, 103, 122, 104, 84, 79, 68, 89, 55, 122, 50, 122, 112, 43, 87, 115, 79, 48, 80, 115, 69, 54, 69, 57, 51, 49, 50, 85, 66, 101, 73, 89, 77, 101, 106, 52, 104, 89, 118, 70, 47, 89, 51, 69, 77, 121, 90, 57, 69, 50, 54, 103, 110, 111, 110, 87, 43, 98, 111, 69, 43, 49, 56, 68, 114, 71, 53, 103, 80, 99, 70, 119, 48, 10, 115, 111, 114, 77, 119, 73, 85, 89, 54, 50, 53, 54, 115, 47, 100, 97, 111, 81, 101, 47, 113, 85, 75, 83, 56, 50, 65, 105, 108, 43, 81, 85, 111, 81, 101, 98, 84, 110, 98, 65, 106, 110, 51, 57, 112, 67, 88, 72, 82, 43, 51, 47, 72, 51, 79, 115, 122, 77, 79, 108, 54, 87, 56, 75, 106, 112, 116, 108, 119, 108, 67, 70, 116, 97, 79, 103, 10, 85, 120, 76, 77, 86, 89, 100, 104, 56, 52, 71, 117, 69, 69, 90, 104, 118, 85, 81, 104, 117, 77, 73, 57, 100, 77, 57, 43, 74, 68, 88, 54, 72, 65, 99, 79, 109, 122, 48, 105, 121, 117, 56, 120, 76, 52, 121, 115, 69, 114, 51, 118, 81, 67, 106, 56, 75, 87, 101, 102, 115, 104, 78, 80, 90, 105, 84, 69, 85, 120, 110, 112, 72, 105, 107, 86, 10, 55, 43, 90, 116, 115, 72, 56, 116, 90, 47, 51, 122, 98, 66, 116, 49, 82, 113, 80, 108, 83, 104, 102, 112, 112, 78, 99, 76, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 67, 67, 86, 82, 65, 73, 90, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 72, 48, 122, 67, 67, 66, 98, 117, 103, 65, 119, 73, 66, 65, 103, 73, 73, 88, 115, 79, 51, 112, 107, 78, 47, 112, 79, 65, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 81, 106, 69, 83, 77, 66, 65, 71, 65, 49, 85, 69, 65, 119, 119, 74, 81, 85, 78, 68, 86, 108, 74, 66, 10, 83, 86, 111, 120, 77, 82, 65, 119, 68, 103, 89, 68, 86, 81, 81, 76, 68, 65, 100, 81, 83, 48, 108, 66, 81, 48, 78, 87, 77, 81, 48, 119, 67, 119, 89, 68, 86, 81, 81, 75, 68, 65, 82, 66, 81, 48, 78, 87, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 70, 85, 122, 65, 101, 70, 119, 48, 120, 77, 84, 65, 49, 10, 77, 68, 85, 119, 79, 84, 77, 51, 77, 122, 100, 97, 70, 119, 48, 122, 77, 68, 69, 121, 77, 122, 69, 119, 79, 84, 77, 51, 77, 122, 100, 97, 77, 69, 73, 120, 69, 106, 65, 81, 66, 103, 78, 86, 66, 65, 77, 77, 67, 85, 70, 68, 81, 49, 90, 83, 81, 85, 108, 97, 77, 84, 69, 81, 77, 65, 52, 71, 65, 49, 85, 69, 67, 119, 119, 72, 10, 85, 69, 116, 74, 81, 85, 78, 68, 86, 106, 69, 78, 77, 65, 115, 71, 65, 49, 85, 69, 67, 103, 119, 69, 81, 85, 78, 68, 86, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 86, 77, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 10, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 98, 113, 97, 117, 47, 89, 85, 113, 88, 114, 121, 43, 88, 90, 112, 112, 48, 88, 57, 68, 90, 108, 118, 51, 80, 52, 117, 82, 109, 55, 120, 56, 102, 82, 122, 80, 67, 82, 75, 80, 102, 109, 116, 52, 102, 116, 86, 84, 100, 70, 88, 120, 112, 78, 82, 70, 118, 117, 56, 103, 77, 10, 106, 109, 111, 89, 72, 116, 105, 80, 50, 82, 97, 56, 69, 69, 103, 50, 88, 80, 66, 106, 115, 53, 66, 97, 88, 67, 81, 51, 49, 54, 80, 87, 121, 119, 108, 120, 117, 102, 69, 66, 99, 111, 83, 119, 102, 100, 116, 78, 103, 77, 51, 56, 48, 50, 47, 74, 43, 78, 113, 50, 68, 111, 76, 83, 82, 89, 87, 111, 71, 50, 105, 111, 80, 101, 106, 48, 10, 82, 71, 121, 57, 111, 99, 76, 76, 65, 55, 54, 77, 80, 104, 77, 65, 104, 78, 57, 75, 83, 77, 68, 106, 73, 103, 114, 111, 54, 84, 101, 110, 71, 69, 121, 120, 67, 81, 48, 106, 86, 110, 56, 69, 84, 100, 107, 88, 104, 66, 105, 108, 121, 78, 112, 65, 108, 72, 80, 114, 122, 103, 53, 88, 80, 65, 79, 66, 79, 112, 48, 75, 111, 86, 100, 68, 10, 97, 97, 120, 88, 98, 88, 109, 81, 101, 79, 87, 49, 116, 68, 118, 89, 118, 69, 121, 78, 75, 75, 71, 110, 111, 54, 101, 54, 65, 107, 52, 108, 48, 83, 113, 117, 55, 97, 52, 68, 73, 114, 104, 114, 73, 65, 56, 119, 75, 70, 83, 86, 102, 43, 68, 117, 122, 103, 112, 109, 110, 100, 70, 65, 76, 87, 52, 105, 114, 53, 48, 97, 119, 81, 85, 90, 10, 48, 109, 47, 65, 56, 112, 47, 52, 101, 55, 77, 67, 81, 118, 116, 81, 113, 82, 48, 116, 107, 119, 56, 106, 113, 56, 98, 66, 68, 53, 76, 47, 48, 75, 73, 86, 57, 86, 77, 74, 99, 82, 122, 47, 82, 82, 79, 69, 53, 105, 90, 101, 43, 79, 67, 73, 72, 65, 114, 56, 70, 114, 97, 111, 99, 119, 97, 52, 56, 71, 79, 69, 65, 113, 68, 71, 10, 87, 117, 122, 110, 100, 78, 57, 119, 114, 113, 79, 68, 74, 101, 114, 87, 120, 53, 101, 72, 107, 54, 102, 71, 105, 111, 111, 122, 108, 50, 65, 51, 69, 68, 54, 88, 80, 109, 52, 112, 70, 100, 97, 104, 68, 57, 71, 73, 76, 66, 75, 102, 98, 54, 113, 107, 120, 107, 76, 114, 81, 97, 76, 106, 108, 85, 80, 84, 65, 89, 86, 116, 106, 114, 115, 55, 10, 56, 121, 77, 50, 120, 47, 52, 55, 52, 75, 69, 108, 66, 48, 105, 114, 121, 89, 108, 48, 47, 119, 105, 80, 103, 76, 47, 65, 108, 109, 88, 122, 55, 117, 120, 76, 97, 76, 50, 100, 105, 77, 77, 120, 115, 48, 68, 120, 54, 77, 47, 50, 79, 76, 117, 99, 53, 78, 70, 47, 49, 79, 86, 89, 109, 51, 122, 54, 49, 80, 77, 79, 109, 51, 87, 82, 10, 53, 76, 112, 83, 76, 104, 108, 43, 48, 102, 88, 78, 87, 104, 110, 56, 117, 103, 98, 50, 43, 49, 75, 111, 83, 53, 107, 69, 51, 102, 106, 53, 116, 73, 116, 81, 111, 48, 53, 105, 105, 102, 67, 72, 74, 80, 113, 68, 81, 115, 71, 72, 43, 116, 85, 116, 75, 83, 112, 97, 99, 88, 112, 107, 97, 116, 99, 110, 89, 71, 77, 78, 50, 56, 53, 74, 10, 57, 89, 48, 102, 107, 73, 107, 121, 70, 47, 104, 122, 81, 55, 106, 83, 87, 112, 79, 71, 89, 100, 98, 104, 100, 81, 114, 113, 101, 87, 90, 50, 105, 69, 57, 120, 54, 119, 81, 108, 49, 103, 112, 97, 101, 112, 80, 108, 117, 85, 115, 88, 81, 65, 43, 120, 116, 114, 110, 49, 51, 107, 47, 99, 52, 76, 79, 115, 79, 120, 70, 119, 89, 73, 82, 75, 10, 81, 50, 54, 90, 73, 77, 65, 112, 99, 81, 114, 65, 90, 81, 73, 68, 65, 81, 65, 66, 111, 52, 73, 67, 121, 122, 67, 67, 65, 115, 99, 119, 102, 81, 89, 73, 75, 119, 89, 66, 66, 81, 85, 72, 65, 81, 69, 69, 99, 84, 66, 118, 77, 69, 119, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 122, 65, 67, 104, 107, 66, 111, 100, 72, 82, 119, 10, 79, 105, 56, 118, 100, 51, 100, 51, 76, 109, 70, 106, 89, 51, 89, 117, 90, 88, 77, 118, 90, 109, 108, 115, 90, 87, 70, 107, 98, 87, 108, 117, 76, 48, 70, 121, 89, 50, 104, 112, 100, 109, 57, 122, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 87, 82, 118, 99, 121, 57, 121, 89, 87, 108, 54, 89, 87, 78, 106, 100, 106, 69, 117, 10, 89, 51, 74, 48, 77, 66, 56, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 122, 65, 66, 104, 104, 78, 111, 100, 72, 82, 119, 79, 105, 56, 118, 98, 50, 78, 122, 99, 67, 53, 104, 89, 50, 78, 50, 76, 109, 86, 122, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 84, 83, 104, 55, 84, 106, 51, 122, 99, 110, 107, 49, 88, 50, 10, 86, 117, 113, 66, 53, 84, 98, 77, 106, 66, 52, 47, 118, 84, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 56, 71, 65, 49, 85, 100, 73, 119, 81, 89, 77, 66, 97, 65, 70, 78, 75, 72, 116, 79, 80, 102, 78, 121, 101, 84, 86, 102, 90, 87, 54, 111, 72, 108, 78, 115, 121, 77, 10, 72, 106, 43, 57, 77, 73, 73, 66, 99, 119, 89, 68, 86, 82, 48, 103, 66, 73, 73, 66, 97, 106, 67, 67, 65, 87, 89, 119, 103, 103, 70, 105, 66, 103, 82, 86, 72, 83, 65, 65, 77, 73, 73, 66, 87, 68, 67, 67, 65, 83, 73, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 73, 67, 77, 73, 73, 66, 70, 66, 54, 67, 65, 82, 65, 65, 10, 81, 81, 66, 49, 65, 72, 81, 65, 98, 119, 66, 121, 65, 71, 107, 65, 90, 65, 66, 104, 65, 71, 81, 65, 73, 65, 66, 107, 65, 71, 85, 65, 73, 65, 66, 68, 65, 71, 85, 65, 99, 103, 66, 48, 65, 71, 107, 65, 90, 103, 66, 112, 65, 71, 77, 65, 89, 81, 66, 106, 65, 71, 107, 65, 56, 119, 66, 117, 65, 67, 65, 65, 85, 103, 66, 104, 10, 65, 79, 48, 65, 101, 103, 65, 103, 65, 71, 81, 65, 90, 81, 65, 103, 65, 71, 119, 65, 89, 81, 65, 103, 65, 69, 69, 65, 81, 119, 66, 68, 65, 70, 89, 65, 73, 65, 65, 111, 65, 69, 69, 65, 90, 119, 66, 108, 65, 71, 52, 65, 89, 119, 66, 112, 65, 71, 69, 65, 73, 65, 66, 107, 65, 71, 85, 65, 73, 65, 66, 85, 65, 71, 85, 65, 10, 89, 119, 66, 117, 65, 71, 56, 65, 98, 65, 66, 118, 65, 71, 99, 65, 55, 81, 66, 104, 65, 67, 65, 65, 101, 81, 65, 103, 65, 69, 77, 65, 90, 81, 66, 121, 65, 72, 81, 65, 97, 81, 66, 109, 65, 71, 107, 65, 89, 119, 66, 104, 65, 71, 77, 65, 97, 81, 68, 122, 65, 71, 52, 65, 73, 65, 66, 70, 65, 71, 119, 65, 90, 81, 66, 106, 10, 65, 72, 81, 65, 99, 103, 68, 122, 65, 71, 52, 65, 97, 81, 66, 106, 65, 71, 69, 65, 76, 65, 65, 103, 65, 69, 77, 65, 83, 81, 66, 71, 65, 67, 65, 65, 85, 81, 65, 48, 65, 68, 89, 65, 77, 65, 65, 120, 65, 68, 69, 65, 78, 81, 65, 50, 65, 69, 85, 65, 75, 81, 65, 117, 65, 67, 65, 65, 81, 119, 66, 81, 65, 70, 77, 65, 10, 73, 65, 66, 108, 65, 71, 52, 65, 73, 65, 66, 111, 65, 72, 81, 65, 100, 65, 66, 119, 65, 68, 111, 65, 76, 119, 65, 118, 65, 72, 99, 65, 100, 119, 66, 51, 65, 67, 52, 65, 89, 81, 66, 106, 65, 71, 77, 65, 100, 103, 65, 117, 65, 71, 85, 65, 99, 122, 65, 119, 66, 103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 67, 65, 82, 89, 107, 10, 97, 72, 82, 48, 99, 68, 111, 118, 76, 51, 100, 51, 100, 121, 53, 104, 89, 50, 78, 50, 76, 109, 86, 122, 76, 50, 120, 108, 90, 50, 108, 122, 98, 71, 70, 106, 97, 87, 57, 117, 88, 50, 77, 117, 97, 72, 82, 116, 77, 70, 85, 71, 65, 49, 85, 100, 72, 119, 82, 79, 77, 69, 119, 119, 83, 113, 66, 73, 111, 69, 97, 71, 82, 71, 104, 48, 10, 100, 72, 65, 54, 76, 121, 57, 51, 100, 51, 99, 117, 89, 87, 78, 106, 100, 105, 53, 108, 99, 121, 57, 109, 97, 87, 120, 108, 89, 87, 82, 116, 97, 87, 52, 118, 81, 88, 74, 106, 97, 71, 108, 50, 98, 51, 77, 118, 89, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 90, 71, 57, 122, 76, 51, 74, 104, 97, 88, 112, 104, 89, 50, 78, 50, 10, 77, 86, 57, 107, 90, 88, 73, 117, 89, 51, 74, 115, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 88, 66, 103, 78, 86, 72, 82, 69, 69, 69, 68, 65, 79, 103, 81, 120, 104, 89, 50, 78, 50, 81, 71, 70, 106, 89, 51, 89, 117, 90, 88, 77, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 68, 103, 103, 73, 66, 65, 74, 99, 120, 65, 112, 47, 110, 47, 85, 78, 110, 83, 69, 81, 85, 53, 67, 109, 72, 55, 85, 119, 111, 90, 116, 67, 80, 78, 100, 112, 78, 89, 98, 100, 75, 108, 48, 50, 49, 50, 53, 68, 103, 66, 83, 52, 79, 120, 110, 110, 81, 56, 112, 100, 112, 68, 55, 48, 69, 10, 82, 57, 109, 43, 50, 55, 85, 112, 50, 112, 118, 90, 114, 113, 109, 90, 49, 100, 77, 56, 77, 74, 80, 49, 106, 97, 71, 111, 47, 65, 97, 78, 82, 80, 84, 75, 70, 112, 86, 56, 77, 57, 120, 105, 105, 54, 103, 51, 43, 67, 102, 89, 67, 83, 48, 98, 55, 56, 103, 85, 74, 121, 67, 112, 90, 69, 84, 47, 76, 116, 90, 49, 113, 109, 120, 78, 10, 89, 69, 65, 90, 83, 85, 78, 85, 89, 57, 114, 105, 122, 76, 112, 109, 53, 85, 57, 69, 101, 108, 118, 90, 97, 111, 69, 114, 81, 78, 86, 47, 43, 81, 69, 110, 87, 67, 122, 73, 55, 85, 105, 82, 102, 68, 43, 109, 65, 77, 47, 69, 75, 88, 77, 82, 78, 116, 54, 71, 71, 84, 54, 100, 55, 104, 109, 75, 71, 57, 87, 119, 55, 89, 52, 57, 10, 110, 67, 114, 65, 68, 100, 103, 57, 90, 117, 77, 56, 68, 98, 51, 86, 108, 70, 122, 105, 52, 113, 99, 49, 71, 119, 81, 65, 57, 106, 57, 97, 106, 101, 112, 68, 118, 86, 43, 74, 72, 97, 110, 66, 115, 77, 121, 90, 52, 107, 48, 65, 67, 116, 114, 74, 74, 49, 118, 110, 69, 53, 66, 99, 53, 80, 85, 122, 111, 108, 86, 116, 51, 79, 65, 74, 10, 84, 83, 43, 120, 74, 108, 115, 110, 100, 81, 65, 74, 120, 71, 74, 51, 75, 81, 104, 102, 110, 108, 109, 115, 116, 110, 54, 116, 110, 49, 81, 119, 73, 103, 80, 66, 72, 110, 70, 107, 47, 118, 107, 52, 67, 112, 89, 89, 51, 81, 73, 85, 114, 67, 80, 76, 66, 104, 119, 101, 112, 72, 50, 78, 68, 100, 52, 110, 81, 101, 105, 116, 50, 104, 87, 51, 10, 115, 67, 80, 100, 75, 54, 106, 84, 50, 105, 87, 72, 55, 101, 104, 86, 82, 69, 50, 73, 57, 68, 90, 43, 104, 74, 112, 52, 114, 80, 99, 79, 86, 107, 107, 79, 49, 106, 77, 108, 49, 111, 82, 81, 81, 109, 119, 103, 69, 104, 48, 113, 49, 98, 54, 56, 56, 110, 67, 66, 112, 72, 66, 103, 118, 103, 87, 49, 109, 53, 52, 69, 82, 76, 53, 104, 10, 73, 54, 122, 112, 112, 83, 83, 77, 69, 89, 67, 85, 87, 113, 75, 105, 117, 85, 110, 83, 119, 100, 122, 82, 112, 43, 48, 120, 69, 83, 121, 101, 71, 97, 98, 117, 52, 86, 88, 104, 119, 79, 114, 80, 68, 89, 84, 107, 70, 55, 101, 105, 102, 75, 88, 101, 86, 83, 85, 71, 55, 115, 122, 65, 104, 49, 120, 65, 50, 115, 121, 86, 80, 49, 88, 103, 10, 78, 99, 101, 52, 104, 76, 54, 48, 88, 99, 49, 54, 103, 119, 70, 121, 55, 111, 102, 109, 88, 120, 50, 117, 116, 89, 88, 71, 74, 116, 47, 109, 119, 90, 114, 112, 72, 103, 74, 72, 110, 121, 113, 111, 98, 97, 108, 98, 122, 43, 120, 70, 100, 51, 43, 89, 74, 53, 111, 121, 88, 83, 114, 106, 104, 79, 55, 70, 109, 71, 89, 118, 108, 105, 65, 100, 10, 51, 100, 106, 68, 74, 57, 101, 119, 43, 102, 55, 90, 102, 99, 51, 81, 110, 52, 56, 76, 70, 70, 104, 82, 110, 121, 43, 76, 119, 122, 103, 116, 51, 117, 105, 80, 49, 111, 50, 72, 112, 80, 86, 87, 81, 120, 97, 90, 76, 80, 83, 107, 86, 114, 81, 48, 117, 71, 69, 51, 121, 99, 74, 89, 103, 66, 117, 103, 108, 54, 72, 56, 87, 89, 51, 112, 10, 69, 102, 98, 82, 68, 48, 116, 86, 78, 69, 89, 113, 105, 52, 89, 55, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 84, 87, 67, 65, 32, 71, 108, 111, 98, 97, 108, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 81, 84, 67, 67, 65, 121, 109, 103, 65, 119, 73, 66, 65, 103, 73, 67, 68, 76, 52, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 85, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 70, 99, 120, 69, 106, 65, 81, 66, 103, 78, 86, 66, 65, 111, 84, 10, 67, 86, 82, 66, 83, 86, 100, 66, 84, 105, 49, 68, 81, 84, 69, 81, 77, 65, 52, 71, 65, 49, 85, 69, 67, 120, 77, 72, 85, 109, 57, 118, 100, 67, 66, 68, 81, 84, 69, 99, 77, 66, 111, 71, 65, 49, 85, 69, 65, 120, 77, 84, 86, 70, 100, 68, 81, 83, 66, 72, 98, 71, 57, 105, 89, 87, 119, 103, 85, 109, 57, 118, 100, 67, 66, 68, 10, 81, 84, 65, 101, 70, 119, 48, 120, 77, 106, 65, 50, 77, 106, 99, 119, 78, 106, 73, 52, 77, 122, 78, 97, 70, 119, 48, 122, 77, 68, 69, 121, 77, 122, 69, 120, 78, 84, 85, 53, 78, 84, 108, 97, 77, 70, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 82, 88, 77, 82, 73, 119, 69, 65, 89, 68, 86, 81, 81, 75, 10, 69, 119, 108, 85, 81, 85, 108, 88, 81, 85, 52, 116, 81, 48, 69, 120, 69, 68, 65, 79, 66, 103, 78, 86, 66, 65, 115, 84, 66, 49, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 72, 68, 65, 97, 66, 103, 78, 86, 66, 65, 77, 84, 69, 49, 82, 88, 81, 48, 69, 103, 82, 50, 120, 118, 89, 109, 70, 115, 73, 70, 74, 118, 98, 51, 81, 103, 10, 81, 48, 69, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 119, 66, 100, 118, 73, 54, 52, 122, 69, 98, 111, 111, 104, 55, 52, 53, 78, 110, 72, 69, 75, 72, 49, 74, 119, 55, 87, 50, 67, 10, 110, 74, 102, 70, 49, 48, 120, 79, 82, 85, 110, 76, 81, 69, 75, 49, 69, 106, 82, 115, 71, 99, 74, 48, 112, 68, 70, 102, 104, 81, 75, 88, 55, 69, 77, 122, 67, 108, 80, 83, 110, 73, 121, 79, 116, 55, 104, 53, 50, 121, 118, 86, 97, 118, 75, 79, 90, 115, 84, 117, 75, 119, 69, 72, 107, 116, 83, 122, 48, 65, 76, 102, 85, 80, 90, 86, 10, 114, 50, 89, 79, 121, 43, 66, 72, 89, 67, 56, 114, 77, 106, 107, 49, 85, 106, 111, 111, 103, 47, 104, 55, 70, 115, 89, 89, 117, 71, 76, 87, 82, 121, 87, 82, 122, 118, 65, 90, 69, 107, 50, 116, 89, 47, 88, 84, 80, 51, 86, 102, 75, 102, 67, 104, 77, 66, 119, 113, 111, 74, 105, 109, 70, 98, 51, 117, 47, 82, 107, 50, 56, 79, 75, 82, 10, 81, 52, 47, 54, 121, 116, 89, 81, 74, 48, 108, 77, 55, 57, 51, 66, 56, 89, 86, 119, 109, 56, 114, 113, 113, 70, 112, 68, 47, 71, 50, 71, 98, 51, 80, 112, 78, 48, 87, 112, 56, 68, 98, 72, 122, 73, 104, 49, 72, 114, 116, 115, 66, 118, 43, 98, 97, 122, 52, 88, 55, 71, 71, 113, 99, 88, 122, 71, 72, 97, 76, 51, 83, 101, 107, 86, 10, 116, 84, 122, 87, 111, 87, 72, 49, 69, 102, 99, 70, 98, 120, 51, 57, 69, 98, 55, 81, 77, 65, 102, 67, 75, 98, 65, 74, 84, 105, 98, 99, 52, 54, 75, 111, 107, 87, 111, 102, 119, 112, 70, 70, 105, 70, 122, 108, 109, 76, 104, 120, 112, 82, 85, 90, 121, 88, 120, 49, 69, 99, 120, 119, 100, 69, 56, 116, 109, 120, 50, 82, 82, 80, 49, 87, 10, 75, 75, 68, 43, 117, 52, 90, 113, 121, 80, 112, 99, 67, 49, 106, 99, 120, 107, 116, 50, 121, 75, 115, 105, 50, 88, 77, 80, 112, 102, 82, 97, 65, 111, 107, 47, 84, 53, 52, 105, 103, 117, 54, 105, 100, 70, 77, 113, 80, 86, 77, 110, 97, 82, 49, 115, 106, 106, 73, 115, 90, 65, 65, 109, 89, 50, 69, 50, 84, 113, 78, 71, 116, 122, 57, 57, 10, 115, 121, 50, 115, 98, 90, 67, 105, 108, 97, 76, 79, 122, 57, 113, 67, 53, 119, 99, 48, 71, 90, 98, 112, 117, 67, 71, 113, 75, 88, 54, 109, 79, 76, 54, 79, 75, 85, 111, 104, 90, 110, 107, 102, 115, 56, 79, 49, 67, 87, 102, 101, 49, 116, 81, 72, 82, 118, 77, 113, 50, 117, 89, 105, 78, 50, 68, 76, 103, 98, 89, 80, 111, 65, 47, 112, 10, 121, 74, 86, 47, 118, 49, 87, 82, 66, 88, 114, 80, 80, 82, 88, 65, 98, 57, 52, 74, 108, 65, 71, 68, 49, 122, 81, 98, 122, 69, 67, 108, 56, 76, 105, 98, 90, 57, 87, 89, 107, 84, 117, 110, 104, 72, 105, 86, 74, 113, 82, 97, 67, 80, 103, 114, 100, 76, 81, 65, 66, 68, 122, 102, 117, 66, 83, 79, 54, 78, 43, 112, 106, 87, 120, 110, 10, 107, 106, 77, 100, 119, 76, 102, 83, 55, 74, 76, 73, 118, 103, 109, 47, 76, 67, 107, 70, 98, 119, 74, 114, 110, 117, 43, 56, 118, 121, 113, 56, 87, 56, 66, 81, 106, 48, 70, 119, 99, 89, 101, 121, 84, 98, 99, 69, 113, 89, 83, 106, 77, 113, 43, 117, 55, 109, 115, 88, 105, 55, 75, 120, 47, 109, 122, 104, 107, 73, 121, 73, 113, 74, 100, 73, 10, 122, 115, 104, 78, 121, 47, 77, 71, 122, 49, 57, 113, 67, 107, 75, 120, 72, 104, 53, 51, 76, 52, 54, 103, 53, 112, 73, 79, 66, 118, 119, 70, 73, 116, 73, 109, 52, 84, 70, 82, 102, 84, 76, 99, 68, 119, 73, 68, 65, 81, 65, 66, 111, 121, 77, 119, 73, 84, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 10, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, 67, 65, 103, 69, 65, 88, 122, 83, 66, 100, 117, 43, 87, 72, 100, 88, 108, 116, 100, 107, 67, 89, 52, 81, 87, 119, 97, 54, 103, 10, 99, 70, 71, 110, 57, 48, 120, 72, 78, 99, 103, 76, 49, 121, 103, 57, 105, 88, 72, 90, 113, 106, 78, 66, 54, 104, 81, 98, 98, 67, 69, 65, 119, 71, 120, 67, 71, 88, 54, 102, 97, 86, 115, 103, 81, 116, 43, 105, 48, 116, 114, 69, 102, 74, 100, 76, 106, 98, 68, 111, 114, 77, 106, 117, 112, 87, 107, 69, 109, 81, 113, 83, 112, 113, 115, 110, 10, 76, 104, 112, 78, 103, 98, 43, 69, 49, 72, 65, 101, 114, 85, 102, 43, 47, 85, 113, 100, 77, 43, 68, 121, 117, 99, 82, 70, 67, 67, 69, 75, 50, 109, 108, 112, 99, 51, 73, 78, 118, 106, 84, 43, 108, 73, 117, 116, 119, 120, 52, 49, 49, 54, 75, 68, 55, 43, 85, 52, 120, 54, 87, 70, 72, 54, 118, 80, 78, 79, 119, 47, 75, 80, 52, 77, 10, 56, 86, 101, 71, 84, 115, 108, 86, 57, 120, 122, 85, 50, 75, 86, 57, 66, 110, 112, 118, 49, 100, 56, 81, 51, 52, 70, 79, 73, 87, 87, 120, 116, 117, 69, 88, 101, 90, 86, 70, 66, 115, 53, 102, 122, 78, 120, 71, 105, 87, 78, 111, 82, 73, 50, 84, 57, 71, 82, 119, 111, 68, 50, 100, 75, 65, 88, 68, 79, 88, 67, 52, 89, 110, 115, 103, 10, 47, 101, 84, 98, 54, 81, 105, 104, 117, 74, 52, 57, 67, 99, 100, 80, 43, 121, 122, 52, 107, 51, 90, 66, 51, 108, 76, 103, 52, 86, 102, 83, 110, 81, 79, 56, 100, 53, 55, 43, 110, 105, 108, 101, 57, 56, 70, 82, 89, 66, 47, 101, 50, 103, 117, 121, 76, 88, 87, 51, 81, 48, 105, 84, 53, 47, 90, 53, 120, 111, 82, 100, 103, 70, 108, 103, 10, 108, 80, 120, 52, 109, 73, 56, 56, 107, 49, 72, 116, 81, 74, 65, 72, 51, 50, 82, 106, 74, 77, 116, 79, 99, 81, 87, 104, 49, 53, 81, 97, 105, 68, 76, 120, 73, 110, 81, 105, 114, 113, 87, 109, 50, 66, 74, 112, 84, 71, 67, 106, 65, 117, 52, 114, 55, 78, 82, 106, 107, 103, 116, 101, 118, 105, 57, 50, 97, 54, 79, 50, 74, 114, 121, 80, 10, 65, 57, 103, 75, 56, 107, 120, 107, 82, 114, 48, 53, 89, 117, 87, 87, 54, 122, 82, 106, 69, 83, 106, 77, 108, 102, 71, 116, 55, 43, 47, 99, 103, 70, 104, 73, 54, 85, 117, 52, 54, 109, 87, 115, 54, 102, 121, 65, 116, 98, 88, 73, 82, 102, 109, 115, 119, 90, 47, 90, 117, 101, 112, 105, 105, 73, 55, 69, 56, 85, 117, 68, 69, 113, 51, 109, 10, 105, 52, 84, 87, 110, 115, 76, 114, 103, 120, 105, 102, 97, 114, 115, 98, 74, 71, 65, 122, 99, 77, 122, 115, 57, 122, 76, 122, 88, 78, 108, 53, 102, 101, 43, 101, 112, 80, 55, 74, 73, 56, 77, 107, 55, 104, 87, 83, 115, 84, 50, 82, 84, 121, 97, 71, 118, 87, 90, 122, 74, 66, 80, 113, 112, 75, 53, 106, 119, 97, 49, 57, 104, 65, 77, 56, 10, 69, 72, 105, 71, 71, 51, 110, 106, 120, 80, 80, 121, 66, 74, 85, 103, 114, 105, 79, 67, 120, 76, 77, 54, 65, 71, 75, 47, 53, 106, 89, 107, 52, 86, 101, 54, 120, 120, 54, 81, 100, 100, 86, 102, 80, 53, 86, 104, 75, 56, 69, 55, 122, 101, 87, 122, 97, 71, 72, 81, 82, 105, 97, 112, 73, 86, 74, 112, 76, 101, 115, 117, 120, 43, 116, 51, 10, 122, 113, 89, 54, 116, 81, 77, 122, 84, 51, 98, 82, 53, 49, 120, 85, 65, 86, 51, 76, 101, 80, 84, 74, 68, 76, 47, 80, 69, 111, 52, 88, 76, 83, 78, 111, 108, 79, 101, 114, 47, 113, 109, 121, 75, 119, 98, 81, 66, 77, 48, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 84, 101, 108, 105, 97, 83, 111, 110, 101, 114, 97, 32, 82, 111, 111, 116, 32, 67, 65, 32, 118, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 79, 68, 67, 67, 65, 121, 67, 103, 65, 119, 73, 66, 65, 103, 73, 82, 65, 74, 87, 43, 70, 113, 68, 51, 76, 107, 98, 120, 101, 122, 109, 67, 99, 118, 113, 76, 122, 90, 89, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 70, 66, 81, 65, 119, 78, 122, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 10, 67, 103, 119, 76, 86, 71, 86, 115, 97, 87, 70, 84, 98, 50, 53, 108, 99, 109, 69, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 77, 77, 70, 108, 82, 108, 98, 71, 108, 104, 85, 50, 57, 117, 90, 88, 74, 104, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 100, 106, 69, 119, 72, 104, 99, 78, 77, 68, 99, 120, 77, 68, 69, 52, 10, 77, 84, 73, 119, 77, 68, 85, 119, 87, 104, 99, 78, 77, 122, 73, 120, 77, 68, 69, 52, 77, 84, 73, 119, 77, 68, 85, 119, 87, 106, 65, 51, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 75, 68, 65, 116, 85, 90, 87, 120, 112, 89, 86, 78, 118, 98, 109, 86, 121, 89, 84, 69, 102, 77, 66, 48, 71, 65, 49, 85, 69, 65, 119, 119, 87, 10, 86, 71, 86, 115, 97, 87, 70, 84, 98, 50, 53, 108, 99, 109, 69, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 66, 50, 77, 84, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 77, 75, 43, 10, 54, 121, 102, 119, 73, 97, 80, 122, 97, 83, 90, 86, 102, 112, 51, 70, 86, 82, 97, 82, 88, 80, 51, 118, 73, 98, 57, 84, 103, 72, 111, 116, 48, 112, 71, 77, 89, 122, 72, 119, 55, 67, 84, 119, 119, 54, 88, 83, 99, 110, 119, 81, 98, 102, 81, 51, 116, 43, 88, 109, 102, 72, 110, 113, 106, 76, 87, 67, 105, 54, 53, 73, 116, 113, 119, 65, 10, 51, 71, 86, 49, 55, 67, 112, 78, 88, 56, 71, 72, 57, 83, 66, 108, 75, 52, 71, 111, 82, 122, 54, 74, 73, 53, 85, 119, 70, 112, 66, 47, 54, 70, 99, 72, 83, 79, 99, 90, 114, 114, 57, 70, 90, 55, 69, 51, 71, 119, 89, 113, 47, 116, 55, 53, 114, 72, 50, 68, 43, 49, 54, 54, 53, 73, 43, 88, 90, 55, 53, 76, 106, 111, 49, 107, 10, 66, 49, 99, 52, 86, 87, 107, 48, 78, 106, 48, 84, 83, 79, 57, 80, 52, 116, 78, 109, 72, 113, 84, 80, 71, 114, 100, 101, 78, 106, 80, 85, 116, 65, 97, 57, 71, 65, 72, 57, 100, 52, 82, 81, 65, 69, 88, 49, 106, 70, 51, 111, 73, 55, 120, 43, 47, 106, 88, 104, 55, 86, 66, 55, 113, 84, 67, 78, 71, 100, 77, 74, 106, 109, 104, 110, 10, 88, 98, 56, 56, 108, 120, 104, 84, 117, 121, 108, 105, 120, 99, 112, 101, 99, 115, 72, 72, 108, 116, 84, 98, 76, 97, 67, 48, 72, 50, 107, 68, 55, 79, 114, 105, 85, 80, 69, 77, 80, 80, 67, 115, 56, 49, 77, 116, 56, 66, 122, 49, 55, 87, 119, 53, 79, 88, 79, 65, 70, 115, 104, 83, 115, 67, 80, 78, 52, 68, 55, 99, 51, 84, 120, 72, 10, 111, 76, 115, 49, 105, 117, 75, 89, 97, 73, 117, 43, 53, 98, 57, 121, 55, 116, 76, 54, 112, 101, 48, 83, 55, 102, 121, 89, 71, 75, 107, 109, 100, 116, 119, 111, 83, 120, 65, 103, 72, 78, 78, 47, 70, 110, 99, 116, 55, 87, 43, 65, 57, 48, 109, 55, 85, 119, 87, 55, 88, 87, 106, 72, 49, 77, 104, 49, 70, 106, 43, 74, 87, 111, 118, 51, 10, 70, 48, 102, 85, 84, 80, 72, 83, 105, 88, 107, 43, 84, 84, 50, 89, 113, 71, 72, 101, 79, 104, 55, 83, 43, 70, 52, 68, 52, 77, 72, 74, 72, 73, 122, 84, 106, 85, 51, 84, 108, 84, 97, 122, 78, 49, 57, 106, 89, 53, 115, 122, 70, 80, 65, 116, 74, 109, 116, 84, 102, 73, 109, 77, 77, 115, 74, 117, 55, 68, 48, 104, 65, 68, 110, 74, 10, 111, 87, 106, 105, 85, 73, 77, 117, 115, 68, 111, 114, 56, 122, 97, 103, 114, 67, 47, 107, 98, 50, 72, 67, 85, 81, 107, 53, 80, 111, 116, 84, 117, 98, 116, 110, 50, 116, 120, 84, 117, 88, 90, 90, 78, 112, 49, 68, 53, 83, 68, 103, 80, 84, 74, 103, 104, 83, 74, 82, 116, 56, 99, 122, 117, 57, 48, 86, 76, 54, 82, 52, 112, 103, 100, 55, 10, 103, 85, 89, 50, 66, 73, 98, 100, 101, 84, 88, 72, 108, 83, 119, 55, 115, 75, 77, 88, 78, 101, 86, 122, 72, 55, 82, 99, 87, 101, 47, 97, 54, 104, 66, 108, 101, 51, 114, 81, 102, 53, 43, 122, 116, 67, 111, 51, 79, 51, 67, 76, 109, 49, 117, 53, 75, 55, 102, 115, 115, 108, 69, 83, 108, 49, 77, 112, 87, 116, 84, 119, 69, 104, 68, 99, 10, 84, 119, 75, 55, 69, 112, 73, 118, 89, 116, 81, 47, 97, 85, 78, 56, 68, 100, 98, 56, 87, 72, 85, 66, 105, 74, 49, 89, 70, 107, 118, 101, 117, 112, 68, 47, 82, 119, 71, 74, 66, 109, 114, 50, 88, 55, 75, 81, 97, 114, 77, 67, 112, 103, 75, 73, 118, 55, 78, 72, 102, 105, 114, 90, 49, 102, 112, 111, 101, 68, 86, 78, 65, 103, 77, 66, 10, 65, 65, 71, 106, 80, 122, 65, 57, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 67, 119, 89, 68, 86, 82, 48, 80, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 84, 119, 106, 49, 107, 52, 65, 76, 80, 49, 106, 53, 113, 87, 10, 68, 78, 88, 114, 43, 110, 117, 113, 70, 43, 103, 84, 69, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 65, 79, 67, 65, 103, 69, 65, 118, 117, 82, 99, 89, 107, 52, 107, 57, 65, 119, 73, 47, 47, 68, 84, 68, 71, 106, 107, 107, 48, 107, 105, 80, 48, 81, 110, 98, 55, 116, 116, 51, 111, 78, 109, 10, 122, 113, 106, 77, 68, 102, 122, 49, 109, 103, 98, 108, 100, 120, 83, 82, 54, 53, 49, 66, 101, 53, 107, 113, 104, 79, 88, 47, 47, 67, 72, 66, 88, 102, 68, 107, 72, 49, 101, 51, 100, 97, 109, 104, 88, 119, 73, 109, 47, 57, 102, 72, 57, 48, 55, 101, 84, 47, 106, 51, 72, 69, 98, 65, 101, 107, 57, 65, 76, 67, 73, 49, 56, 66, 109, 120, 10, 48, 71, 116, 110, 76, 76, 67, 111, 52, 77, 66, 65, 78, 122, 88, 50, 104, 70, 120, 99, 52, 54, 57, 67, 101, 80, 54, 110, 121, 81, 49, 81, 54, 103, 50, 69, 100, 118, 90, 82, 55, 52, 78, 84, 120, 110, 114, 47, 68, 108, 90, 74, 76, 111, 57, 54, 49, 103, 122, 109, 74, 49, 84, 106, 84, 81, 112, 103, 99, 109, 76, 78, 107, 81, 102, 87, 10, 112, 98, 47, 73, 109, 87, 118, 116, 120, 66, 110, 109, 113, 48, 119, 82, 79, 77, 86, 118, 77, 101, 74, 117, 83, 99, 103, 47, 100, 111, 65, 109, 65, 121, 89, 112, 52, 68, 98, 50, 57, 105, 66, 84, 52, 120, 100, 119, 78, 66, 101, 100, 89, 50, 103, 101, 97, 43, 122, 68, 84, 89, 97, 52, 69, 122, 65, 118, 88, 85, 89, 78, 82, 48, 80, 86, 10, 71, 54, 112, 90, 68, 114, 108, 99, 106, 81, 90, 73, 114, 88, 83, 72, 88, 56, 102, 56, 77, 86, 82, 66, 69, 43, 76, 72, 73, 81, 54, 101, 52, 66, 52, 78, 52, 99, 66, 55, 81, 52, 87, 81, 120, 89, 112, 89, 120, 109, 85, 75, 101, 70, 102, 121, 120, 105, 77, 80, 65, 100, 107, 103, 83, 57, 52, 80, 43, 53, 75, 70, 100, 83, 112, 99, 10, 99, 52, 49, 116, 101, 121, 87, 82, 121, 117, 53, 70, 114, 103, 90, 76, 65, 77, 122, 84, 115, 86, 108, 81, 50, 106, 113, 73, 79, 121, 108, 68, 82, 108, 54, 88, 75, 49, 84, 79, 85, 50, 43, 78, 83, 117, 101, 87, 43, 114, 57, 120, 68, 107, 75, 76, 102, 80, 48, 111, 111, 78, 66, 73, 121, 116, 114, 69, 103, 85, 121, 55, 111, 110, 79, 84, 10, 74, 115, 106, 114, 68, 78, 89, 109, 105, 76, 98, 65, 74, 77, 43, 55, 118, 86, 118, 114, 100, 88, 51, 112, 67, 73, 54, 71, 77, 121, 120, 53, 100, 119, 108, 112, 112, 89, 110, 56, 115, 51, 67, 81, 104, 51, 97, 80, 48, 121, 75, 55, 81, 115, 54, 57, 99, 119, 115, 103, 74, 105, 114, 81, 109, 122, 49, 119, 72, 105, 82, 115, 122, 89, 100, 50, 10, 113, 82, 101, 87, 116, 56, 56, 78, 107, 118, 117, 79, 71, 75, 109, 89, 83, 100, 71, 101, 47, 109, 66, 69, 99, 105, 71, 53, 71, 101, 51, 67, 57, 84, 72, 120, 79, 85, 105, 73, 107, 67, 82, 49, 86, 66, 97, 116, 122, 118, 84, 52, 97, 82, 82, 107, 79, 102, 117, 106, 117, 76, 112, 119, 81, 77, 99, 110, 72, 76, 47, 69, 86, 108, 80, 54, 10, 89, 50, 88, 81, 56, 120, 119, 79, 70, 118, 86, 114, 104, 108, 104, 78, 71, 78, 84, 107, 68, 89, 54, 108, 110, 86, 117, 82, 51, 72, 89, 107, 85, 68, 47, 71, 75, 118, 118, 90, 116, 53, 121, 49, 49, 117, 98, 81, 50, 101, 103, 90, 105, 120, 86, 120, 83, 75, 50, 51, 54, 116, 104, 90, 105, 78, 83, 81, 118, 120, 97, 122, 50, 101, 109, 115, 10, 87, 87, 70, 85, 121, 66, 121, 54, 121, 115, 72, 75, 52, 98, 107, 103, 84, 73, 56, 54, 107, 52, 109, 108, 111, 77, 121, 47, 48, 47, 90, 49, 112, 72, 87, 87, 98, 86, 89, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 69, 45, 84, 117, 103, 114, 97, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 71, 83, 122, 67, 67, 66, 68, 79, 103, 65, 119, 73, 66, 65, 103, 73, 73, 97, 109, 103, 43, 110, 70, 71, 98, 121, 49, 77, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 103, 98, 73, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 82, 83, 77, 81, 56, 119, 10, 68, 81, 89, 68, 86, 81, 81, 72, 68, 65, 90, 66, 98, 109, 116, 104, 99, 109, 69, 120, 81, 68, 65, 43, 66, 103, 78, 86, 66, 65, 111, 77, 78, 48, 85, 116, 86, 72, 88, 69, 110, 51, 74, 104, 73, 69, 86, 67, 82, 121, 66, 67, 97, 87, 120, 112, 120, 90, 57, 112, 98, 83, 66, 85, 90, 87, 116, 117, 98, 50, 120, 118, 97, 109, 108, 115, 10, 90, 88, 74, 112, 73, 72, 90, 108, 73, 69, 104, 112, 101, 109, 49, 108, 100, 71, 120, 108, 99, 109, 107, 103, 81, 83, 55, 70, 110, 105, 52, 120, 74, 106, 65, 107, 66, 103, 78, 86, 66, 65, 115, 77, 72, 85, 85, 116, 86, 72, 86, 110, 99, 109, 69, 103, 85, 50, 86, 121, 100, 71, 108, 109, 97, 87, 116, 104, 99, 51, 108, 118, 98, 105, 66, 78, 10, 90, 88, 74, 114, 90, 88, 112, 112, 77, 83, 103, 119, 74, 103, 89, 68, 86, 81, 81, 68, 68, 66, 57, 70, 76, 86, 82, 49, 90, 51, 74, 104, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 66, 52, 88, 68, 84, 69, 122, 77, 68, 77, 119, 10, 78, 84, 69, 121, 77, 68, 107, 48, 79, 70, 111, 88, 68, 84, 73, 122, 77, 68, 77, 119, 77, 122, 69, 121, 77, 68, 107, 48, 79, 70, 111, 119, 103, 98, 73, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 82, 83, 77, 81, 56, 119, 68, 81, 89, 68, 86, 81, 81, 72, 68, 65, 90, 66, 98, 109, 116, 104, 99, 109, 69, 120, 10, 81, 68, 65, 43, 66, 103, 78, 86, 66, 65, 111, 77, 78, 48, 85, 116, 86, 72, 88, 69, 110, 51, 74, 104, 73, 69, 86, 67, 82, 121, 66, 67, 97, 87, 120, 112, 120, 90, 57, 112, 98, 83, 66, 85, 90, 87, 116, 117, 98, 50, 120, 118, 97, 109, 108, 115, 90, 88, 74, 112, 73, 72, 90, 108, 73, 69, 104, 112, 101, 109, 49, 108, 100, 71, 120, 108, 10, 99, 109, 107, 103, 81, 83, 55, 70, 110, 105, 52, 120, 74, 106, 65, 107, 66, 103, 78, 86, 66, 65, 115, 77, 72, 85, 85, 116, 86, 72, 86, 110, 99, 109, 69, 103, 85, 50, 86, 121, 100, 71, 108, 109, 97, 87, 116, 104, 99, 51, 108, 118, 98, 105, 66, 78, 90, 88, 74, 114, 90, 88, 112, 112, 77, 83, 103, 119, 74, 103, 89, 68, 86, 81, 81, 68, 10, 68, 66, 57, 70, 76, 86, 82, 49, 90, 51, 74, 104, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 73, 73, 67, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 103, 56, 65, 10, 77, 73, 73, 67, 67, 103, 75, 67, 65, 103, 69, 65, 52, 118, 85, 47, 107, 119, 86, 82, 72, 111, 86, 105, 86, 70, 53, 54, 67, 47, 85, 89, 66, 52, 79, 117, 102, 113, 57, 56, 57, 57, 83, 75, 97, 54, 86, 106, 81, 122, 109, 53, 83, 47, 102, 68, 120, 109, 83, 74, 80, 90, 81, 117, 86, 73, 66, 83, 79, 84, 107, 72, 83, 48, 118, 100, 10, 104, 81, 100, 50, 104, 56, 121, 47, 76, 53, 86, 77, 122, 72, 50, 110, 80, 98, 120, 72, 68, 53, 104, 119, 43, 73, 121, 70, 72, 110, 83, 79, 107, 109, 48, 98, 81, 78, 71, 90, 68, 98, 116, 49, 98, 115, 105, 112, 97, 53, 114, 65, 104, 68, 71, 118, 121, 107, 80, 76, 54, 121, 115, 48, 54, 73, 43, 88, 97, 119, 71, 98, 49, 81, 53, 75, 10, 67, 75, 112, 98, 107, 110, 83, 70, 81, 57, 79, 65, 114, 113, 71, 73, 87, 54, 54, 122, 54, 108, 55, 76, 70, 112, 112, 51, 82, 77, 105, 104, 57, 108, 82, 111, 122, 116, 54, 80, 108, 121, 117, 54, 87, 48, 65, 67, 68, 71, 81, 88, 119, 76, 87, 84, 122, 101, 72, 120, 69, 50, 98, 79, 68, 72, 110, 118, 48, 90, 69, 111, 113, 49, 43, 103, 10, 69, 108, 73, 119, 99, 120, 109, 79, 106, 43, 71, 77, 66, 54, 76, 68, 117, 48, 114, 119, 54, 104, 56, 86, 113, 79, 52, 108, 122, 75, 82, 71, 43, 66, 115, 105, 55, 55, 77, 79, 81, 55, 111, 115, 74, 76, 106, 70, 76, 70, 122, 85, 72, 80, 104, 100, 90, 76, 51, 68, 107, 49, 52, 111, 112, 122, 56, 110, 56, 89, 52, 101, 48, 121, 112, 81, 10, 66, 97, 78, 86, 50, 99, 118, 110, 79, 86, 80, 65, 109, 74, 54, 77, 86, 71, 75, 76, 74, 114, 68, 51, 102, 89, 49, 56, 53, 77, 97, 101, 90, 107, 74, 86, 103, 107, 102, 110, 115, 108, 105, 78, 90, 118, 99, 72, 102, 67, 52, 50, 53, 108, 65, 99, 80, 57, 116, 68, 74, 77, 87, 47, 104, 107, 100, 53, 115, 51, 107, 99, 57, 49, 114, 48, 10, 69, 43, 120, 115, 43, 68, 47, 105, 87, 82, 43, 86, 55, 107, 73, 43, 117, 97, 50, 111, 77, 111, 86, 74, 108, 48, 98, 43, 83, 122, 71, 80, 87, 115, 117, 116, 100, 69, 99, 102, 54, 90, 71, 51, 51, 121, 103, 69, 73, 113, 68, 85, 68, 49, 51, 105, 101, 85, 47, 113, 98, 73, 87, 71, 118, 97, 105, 109, 122, 117, 84, 54, 119, 43, 71, 122, 10, 114, 116, 52, 56, 85, 101, 55, 76, 69, 51, 119, 66, 102, 52, 81, 79, 88, 86, 71, 85, 110, 104, 77, 77, 116, 105, 54, 108, 84, 80, 107, 53, 99, 68, 90, 118, 108, 115, 111, 117, 68, 69, 82, 86, 120, 99, 114, 54, 88, 81, 75, 106, 51, 57, 90, 107, 106, 70, 113, 122, 65, 81, 113, 112, 116, 81, 112, 72, 70, 47, 47, 118, 107, 85, 65, 113, 10, 106, 113, 70, 71, 79, 106, 71, 89, 53, 82, 72, 56, 122, 76, 116, 74, 86, 111, 114, 56, 117, 100, 66, 104, 109, 109, 57, 108, 98, 79, 98, 68, 121, 122, 53, 49, 83, 102, 54, 80, 112, 43, 75, 74, 120, 87, 102, 88, 110, 85, 89, 84, 84, 106, 70, 50, 79, 121, 83, 122, 110, 104, 70, 108, 104, 113, 116, 47, 55, 120, 51, 85, 43, 76, 122, 110, 10, 114, 70, 112, 99, 116, 49, 112, 72, 88, 70, 88, 79, 86, 98, 81, 105, 99, 86, 116, 98, 67, 47, 68, 80, 51, 75, 66, 104, 90, 79, 113, 112, 49, 50, 103, 75, 89, 54, 102, 103, 68, 84, 43, 103, 114, 57, 79, 113, 48, 110, 55, 118, 85, 97, 68, 109, 85, 83, 116, 86, 107, 104, 85, 88, 85, 56, 117, 51, 90, 103, 53, 109, 84, 80, 106, 53, 10, 100, 85, 121, 81, 53, 120, 74, 119, 120, 48, 85, 67, 65, 119, 69, 65, 65, 97, 78, 106, 77, 71, 69, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 67, 55, 106, 50, 55, 74, 74, 48, 74, 120, 85, 101, 86, 122, 54, 74, 121, 114, 43, 122, 69, 55, 83, 54, 69, 53, 85, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 10, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 119, 89, 68, 86, 82, 48, 106, 66, 66, 103, 119, 70, 111, 65, 85, 76, 117, 80, 98, 115, 107, 110, 81, 110, 70, 82, 53, 88, 80, 111, 110, 75, 118, 55, 77, 84, 116, 76, 111, 84, 108, 81, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 10, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 67, 65, 81, 65, 70, 78, 122, 114, 48, 84, 98, 100, 70, 52, 107, 86, 49, 74, 73, 43, 50, 100, 49, 76, 111, 72, 78, 103, 81, 107, 50, 88, 122, 56, 108, 107, 71, 112, 68, 52, 101, 75, 101, 120, 100, 48, 100, 67, 114, 102, 79, 65, 75, 10, 107, 69, 104, 52, 55, 85, 54, 89, 65, 53, 110, 43, 75, 71, 67, 82, 72, 84, 65, 100, 117, 71, 78, 56, 113, 79, 89, 49, 116, 102, 114, 84, 89, 88, 98, 109, 49, 103, 100, 76, 121, 109, 109, 97, 115, 111, 82, 54, 100, 53, 78, 70, 70, 120, 87, 102, 74, 78, 67, 89, 69, 120, 76, 47, 117, 54, 65, 117, 47, 85, 53, 77, 104, 47, 106, 79, 10, 88, 75, 113, 89, 71, 119, 88, 103, 65, 69, 90, 75, 103, 111, 67, 108, 77, 52, 115, 111, 51, 79, 48, 52, 48, 57, 47, 108, 80, 117, 110, 43, 43, 49, 110, 100, 89, 89, 82, 80, 48, 108, 83, 87, 69, 50, 69, 84, 80, 111, 43, 65, 97, 98, 54, 84, 82, 55, 85, 49, 81, 57, 74, 97, 117, 122, 49, 99, 55, 55, 78, 67, 82, 56, 48, 55, 10, 86, 82, 77, 71, 115, 65, 110, 98, 47, 87, 80, 50, 79, 111, 103, 75, 109, 87, 57, 43, 52, 99, 52, 98, 85, 50, 112, 69, 90, 105, 78, 82, 67, 72, 117, 56, 87, 49, 75, 105, 47, 81, 89, 51, 79, 69, 66, 104, 106, 48, 113, 87, 117, 74, 65, 51, 43, 71, 98, 72, 101, 74, 65, 65, 70, 83, 54, 76, 114, 86, 69, 49, 85, 119, 101, 111, 10, 97, 50, 105, 117, 43, 85, 52, 56, 66, 121, 98, 78, 67, 65, 86, 119, 122, 68, 107, 47, 100, 114, 50, 108, 48, 50, 99, 109, 65, 89, 97, 109, 85, 57, 74, 103, 79, 51, 120, 68, 102, 49, 87, 75, 118, 74, 85, 97, 119, 83, 103, 53, 84, 66, 57, 68, 48, 112, 72, 48, 99, 108, 109, 75, 117, 86, 98, 56, 80, 55, 83, 100, 50, 110, 67, 99, 10, 100, 108, 113, 77, 81, 49, 68, 117, 106, 106, 66, 121, 84, 100, 47, 47, 83, 102, 102, 71, 113, 87, 102, 90, 98, 97, 119, 67, 69, 101, 73, 54, 70, 105, 87, 110, 87, 65, 106, 76, 98, 49, 78, 66, 110, 69, 103, 52, 82, 50, 103, 122, 48, 100, 102, 72, 106, 57, 82, 48, 73, 100, 84, 68, 66, 90, 66, 54, 47, 56, 54, 87, 105, 76, 69, 86, 10, 75, 86, 48, 106, 113, 57, 66, 103, 111, 82, 74, 80, 51, 118, 81, 88, 122, 84, 76, 108, 121, 98, 47, 73, 81, 54, 51, 57, 76, 111, 55, 120, 114, 43, 76, 48, 109, 80, 111, 83, 72, 121, 68, 89, 119, 75, 99, 77, 104, 99, 87, 81, 57, 68, 115, 116, 108, 105, 97, 120, 76, 76, 53, 77, 113, 43, 117, 120, 48, 111, 114, 74, 50, 51, 103, 84, 10, 68, 120, 52, 74, 110, 87, 50, 80, 65, 74, 56, 67, 50, 115, 72, 54, 72, 51, 112, 54, 67, 99, 82, 75, 53, 111, 103, 113, 108, 53, 43, 74, 105, 47, 48, 51, 88, 49, 56, 54, 122, 106, 104, 90, 104, 107, 117, 118, 99, 81, 117, 48, 50, 80, 74, 119, 84, 53, 56, 121, 69, 43, 79, 119, 112, 49, 102, 108, 50, 116, 112, 68, 121, 52, 81, 48, 10, 56, 105, 106, 69, 54, 109, 51, 48, 75, 117, 47, 66, 97, 51, 98, 97, 43, 51, 54, 55, 104, 84, 122, 83, 85, 56, 74, 78, 118, 110, 72, 104, 82, 100, 72, 57, 73, 50, 99, 78, 69, 51, 88, 55, 122, 50, 86, 110, 73, 112, 50, 117, 115, 65, 110, 82, 67, 102, 56, 100, 78, 76, 47, 43, 73, 53, 99, 51, 48, 106, 110, 54, 80, 81, 48, 71, 10, 67, 55, 84, 98, 79, 54, 79, 114, 98, 49, 119, 100, 116, 110, 55, 111, 115, 52, 73, 48, 55, 81, 90, 99, 74, 65, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 84, 45, 84, 101, 108, 101, 83, 101, 99, 32, 71, 108, 111, 98, 97, 108, 82, 111, 111, 116, 32, 67, 108, 97, 115, 115, 32, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 119, 122, 67, 67, 65, 113, 117, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 66, 103, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 69, 85, 120, 75, 122, 65, 112, 66, 103, 78, 86, 66, 65, 111, 77, 10, 73, 108, 81, 116, 85, 51, 108, 122, 100, 71, 86, 116, 99, 121, 66, 70, 98, 110, 82, 108, 99, 110, 66, 121, 97, 88, 78, 108, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 86, 122, 73, 69, 100, 116, 89, 107, 103, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 115, 77, 70, 108, 81, 116, 85, 51, 108, 122, 100, 71, 86, 116, 99, 121, 66, 85, 10, 99, 110, 86, 122, 100, 67, 66, 68, 90, 87, 53, 48, 90, 88, 73, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 77, 77, 72, 70, 81, 116, 86, 71, 86, 115, 90, 86, 78, 108, 89, 121, 66, 72, 98, 71, 57, 105, 89, 87, 120, 83, 98, 50, 57, 48, 73, 69, 78, 115, 89, 88, 78, 122, 73, 68, 73, 119, 72, 104, 99, 78, 77, 68, 103, 120, 10, 77, 68, 65, 120, 77, 84, 65, 48, 77, 68, 69, 48, 87, 104, 99, 78, 77, 122, 77, 120, 77, 68, 65, 120, 77, 106, 77, 49, 79, 84, 85, 53, 87, 106, 67, 66, 103, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 69, 85, 120, 75, 122, 65, 112, 66, 103, 78, 86, 66, 65, 111, 77, 73, 108, 81, 116, 85, 51, 108, 122, 10, 100, 71, 86, 116, 99, 121, 66, 70, 98, 110, 82, 108, 99, 110, 66, 121, 97, 88, 78, 108, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 86, 122, 73, 69, 100, 116, 89, 107, 103, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 115, 77, 70, 108, 81, 116, 85, 51, 108, 122, 100, 71, 86, 116, 99, 121, 66, 85, 99, 110, 86, 122, 100, 67, 66, 68, 10, 90, 87, 53, 48, 90, 88, 73, 120, 74, 84, 65, 106, 66, 103, 78, 86, 66, 65, 77, 77, 72, 70, 81, 116, 86, 71, 86, 115, 90, 86, 78, 108, 89, 121, 66, 72, 98, 71, 57, 105, 89, 87, 120, 83, 98, 50, 57, 48, 73, 69, 78, 115, 89, 88, 78, 122, 73, 68, 73, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 10, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 113, 88, 57, 111, 98, 88, 43, 104, 122, 107, 101, 88, 97, 88, 80, 83, 105, 53, 107, 102, 108, 56, 50, 104, 86, 89, 65, 85, 100, 65, 113, 83, 122, 109, 49, 110, 122, 72, 111, 113, 118, 78, 75, 51, 56, 68, 99, 76, 90, 10, 83, 66, 110, 117, 97, 89, 47, 74, 73, 80, 119, 104, 113, 103, 99, 90, 55, 98, 66, 99, 114, 71, 88, 72, 88, 43, 48, 67, 102, 72, 116, 56, 76, 82, 118, 87, 117, 114, 109, 65, 119, 104, 105, 67, 70, 111, 84, 54, 90, 114, 65, 73, 120, 108, 81, 106, 103, 101, 84, 78, 117, 85, 107, 47, 57, 107, 57, 117, 78, 48, 103, 111, 79, 65, 47, 70, 10, 118, 117, 100, 111, 99, 80, 48, 53, 108, 48, 51, 83, 120, 53, 105, 82, 85, 75, 114, 69, 82, 76, 77, 106, 102, 84, 108, 72, 54, 86, 74, 105, 49, 104, 75, 84, 88, 114, 99, 120, 108, 107, 73, 70, 43, 51, 97, 110, 72, 113, 80, 49, 119, 118, 122, 112, 101, 115, 86, 115, 113, 88, 70, 80, 54, 115, 116, 52, 118, 71, 67, 118, 120, 57, 55, 48, 10, 50, 99, 117, 43, 102, 106, 79, 108, 98, 112, 83, 68, 56, 68, 84, 54, 73, 97, 118, 113, 106, 110, 75, 103, 80, 54, 84, 101, 77, 70, 118, 118, 104, 107, 49, 113, 108, 86, 116, 68, 82, 75, 103, 81, 70, 82, 122, 108, 65, 86, 102, 70, 109, 80, 72, 109, 66, 105, 105, 82, 113, 105, 68, 70, 116, 49, 77, 109, 85, 85, 79, 121, 67, 120, 71, 86, 10, 87, 79, 72, 65, 68, 51, 98, 90, 119, 73, 49, 56, 103, 102, 78, 121, 99, 74, 53, 118, 47, 104, 113, 79, 50, 86, 56, 49, 120, 114, 74, 118, 78, 72, 121, 43, 83, 69, 47, 105, 87, 106, 110, 88, 50, 74, 49, 52, 110, 112, 43, 71, 80, 103, 78, 101, 71, 89, 116, 69, 111, 116, 88, 72, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 10, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 83, 47, 87, 83, 65, 50, 65, 72, 109, 103, 111, 67, 74, 114, 106, 78, 88, 121, 10, 89, 100, 75, 52, 76, 77, 117, 67, 83, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, 67, 65, 81, 69, 65, 77, 81, 79, 105, 89, 81, 115, 102, 100, 79, 104, 121, 78, 115, 90, 116, 43, 85, 50, 101, 43, 105, 75, 111, 52, 89, 70, 87, 122, 56, 50, 55, 110, 43, 113, 114, 107, 82, 107, 52, 10, 114, 54, 112, 56, 70, 85, 51, 122, 116, 113, 79, 78, 112, 102, 83, 79, 57, 107, 83, 112, 112, 43, 103, 104, 108, 97, 48, 43, 65, 71, 73, 87, 105, 80, 65, 67, 117, 118, 120, 104, 73, 43, 89, 122, 109, 122, 66, 54, 97, 122, 90, 105, 101, 54, 48, 69, 73, 52, 82, 89, 90, 101, 76, 98, 75, 52, 114, 110, 74, 86, 77, 51, 89, 108, 78, 102, 10, 118, 78, 111, 66, 89, 105, 109, 105, 112, 105, 100, 120, 53, 106, 111, 105, 102, 115, 70, 118, 72, 90, 86, 119, 73, 69, 111, 72, 78, 78, 47, 113, 47, 120, 87, 65, 53, 98, 114, 88, 101, 116, 104, 98, 100, 88, 119, 70, 101, 105, 108, 72, 102, 107, 67, 111, 77, 82, 78, 51, 122, 85, 65, 55, 116, 70, 70, 72, 101, 105, 52, 82, 52, 48, 99, 82, 10, 51, 112, 49, 109, 48, 73, 118, 86, 86, 71, 98, 54, 103, 49, 88, 113, 102, 77, 73, 112, 105, 82, 118, 112, 98, 55, 80, 79, 52, 103, 87, 69, 121, 83, 56, 43, 101, 73, 86, 105, 98, 115, 108, 102, 119, 88, 104, 106, 100, 70, 106, 65, 83, 66, 103, 77, 109, 84, 110, 114, 112, 77, 119, 97, 116, 88, 108, 97, 106, 82, 87, 99, 50, 66, 81, 78, 10, 57, 110, 111, 72, 86, 56, 99, 105, 103, 119, 85, 116, 80, 74, 115, 108, 74, 106, 48, 89, 115, 54, 108, 68, 102, 77, 106, 73, 113, 50, 83, 80, 68, 113, 79, 47, 110, 66, 117, 100, 77, 78, 118, 97, 48, 66, 107, 117, 113, 106, 122, 120, 43, 122, 79, 65, 100, 117, 84, 78, 114, 82, 108, 80, 66, 83, 101, 79, 69, 54, 70, 117, 119, 103, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 116, 111, 115, 32, 84, 114, 117, 115, 116, 101, 100, 82, 111, 111, 116, 32, 50, 48, 49, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 100, 122, 67, 67, 65, 108, 43, 103, 65, 119, 73, 66, 65, 103, 73, 73, 88, 68, 80, 76, 89, 105, 120, 102, 115, 122, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 80, 68, 69, 101, 77, 66, 119, 71, 65, 49, 85, 69, 65, 119, 119, 86, 81, 88, 82, 118, 99, 121, 66, 85, 10, 99, 110, 86, 122, 100, 71, 86, 107, 85, 109, 57, 118, 100, 67, 65, 121, 77, 68, 69, 120, 77, 81, 48, 119, 67, 119, 89, 68, 86, 81, 81, 75, 68, 65, 82, 66, 100, 71, 57, 122, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 69, 82, 84, 65, 101, 70, 119, 48, 120, 77, 84, 65, 51, 77, 68, 99, 120, 78, 68, 85, 52, 10, 77, 122, 66, 97, 70, 119, 48, 122, 77, 68, 69, 121, 77, 122, 69, 121, 77, 122, 85, 53, 78, 84, 108, 97, 77, 68, 119, 120, 72, 106, 65, 99, 66, 103, 78, 86, 66, 65, 77, 77, 70, 85, 70, 48, 98, 51, 77, 103, 86, 72, 74, 49, 99, 51, 82, 108, 90, 70, 74, 118, 98, 51, 81, 103, 77, 106, 65, 120, 77, 84, 69, 78, 77, 65, 115, 71, 10, 65, 49, 85, 69, 67, 103, 119, 69, 81, 88, 82, 118, 99, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 69, 85, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 86, 10, 104, 84, 117, 88, 98, 121, 111, 55, 76, 106, 118, 80, 112, 118, 77, 112, 78, 98, 55, 80, 71, 75, 119, 43, 113, 116, 110, 52, 84, 97, 65, 43, 71, 107, 101, 53, 118, 74, 114, 102, 56, 118, 55, 77, 80, 107, 102, 111, 101, 112, 98, 67, 74, 73, 52, 49, 57, 75, 107, 77, 47, 73, 76, 57, 98, 99, 70, 121, 89, 105, 101, 57, 54, 109, 118, 114, 10, 53, 52, 114, 77, 86, 68, 54, 81, 85, 77, 43, 65, 49, 74, 88, 55, 54, 76, 87, 67, 49, 66, 84, 70, 116, 113, 108, 86, 74, 86, 102, 98, 115, 86, 68, 50, 115, 71, 66, 107, 87, 88, 112, 112, 122, 119, 79, 51, 98, 119, 50, 43, 121, 106, 53, 118, 100, 72, 76, 113, 113, 106, 65, 113, 99, 50, 75, 43, 83, 90, 70, 104, 121, 66, 72, 43, 10, 68, 103, 77, 113, 57, 50, 111, 103, 51, 65, 73, 86, 68, 86, 52, 86, 97, 118, 122, 106, 103, 115, 71, 49, 120, 90, 49, 107, 67, 87, 121, 106, 87, 90, 103, 72, 74, 56, 99, 98, 108, 105, 116, 104, 100, 72, 70, 115, 81, 47, 72, 51, 78, 89, 107, 81, 52, 74, 55, 115, 86, 97, 69, 51, 73, 113, 75, 72, 66, 65, 85, 115, 82, 51, 50, 48, 10, 72, 76, 108, 105, 75, 87, 89, 111, 121, 114, 102, 104, 107, 47, 87, 107, 108, 65, 79, 90, 117, 88, 67, 70, 116, 101, 90, 73, 54, 111, 49, 81, 47, 78, 110, 101, 122, 71, 56, 72, 68, 116, 48, 76, 99, 112, 50, 65, 77, 66, 89, 72, 108, 84, 56, 111, 68, 118, 51, 70, 100, 85, 57, 84, 49, 110, 83, 97, 116, 67, 81, 117, 106, 103, 75, 82, 10, 122, 51, 98, 70, 109, 120, 53, 86, 100, 74, 120, 52, 73, 98, 72, 119, 76, 102, 69, 76, 110, 56, 76, 86, 108, 104, 103, 102, 56, 70, 81, 105, 101, 111, 119, 72, 65, 103, 77, 66, 65, 65, 71, 106, 102, 84, 66, 55, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 83, 110, 112, 81, 97, 120, 76, 75, 89, 74, 89, 79, 55, 82, 10, 108, 43, 108, 119, 114, 114, 119, 55, 71, 87, 122, 98, 73, 84, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 56, 71, 65, 49, 85, 100, 73, 119, 81, 89, 77, 66, 97, 65, 70, 75, 101, 108, 66, 114, 69, 115, 112, 103, 108, 103, 55, 116, 71, 88, 54, 88, 67, 117, 118, 68, 115, 90, 10, 98, 78, 115, 104, 77, 66, 103, 71, 65, 49, 85, 100, 73, 65, 81, 82, 77, 65, 56, 119, 68, 81, 89, 76, 75, 119, 89, 66, 66, 65, 71, 119, 76, 81, 77, 69, 65, 81, 69, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 71, 71, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 10, 67, 119, 85, 65, 65, 52, 73, 66, 65, 81, 65, 109, 100, 122, 84, 98, 108, 69, 105, 71, 75, 107, 71, 100, 76, 68, 52, 71, 107, 71, 68, 69, 106, 75, 119, 76, 86, 76, 103, 102, 117, 88, 118, 84, 66, 122, 110, 107, 43, 106, 53, 55, 115, 106, 49, 79, 55, 90, 56, 106, 118, 90, 102, 122, 97, 49, 122, 118, 55, 118, 49, 65, 112, 116, 43, 104, 10, 107, 54, 69, 75, 104, 113, 122, 118, 73, 78, 66, 53, 65, 98, 49, 52, 57, 120, 110, 89, 74, 68, 69, 48, 66, 65, 71, 109, 117, 104, 87, 97, 119, 121, 102, 99, 50, 69, 56, 80, 122, 66, 104, 106, 47, 53, 107, 80, 68, 112, 70, 114, 100, 82, 98, 104, 73, 102, 122, 89, 74, 115, 100, 72, 116, 54, 98, 80, 87, 72, 74, 120, 102, 114, 114, 104, 10, 84, 90, 86, 72, 79, 56, 109, 118, 98, 97, 71, 48, 119, 101, 121, 74, 57, 114, 81, 80, 79, 76, 88, 105, 90, 78, 119, 108, 122, 54, 98, 98, 54, 53, 112, 99, 109, 97, 72, 70, 67, 78, 55, 57, 53, 116, 114, 86, 49, 108, 112, 70, 68, 77, 83, 51, 119, 114, 85, 85, 55, 55, 81, 82, 47, 119, 52, 86, 116, 102, 88, 49, 50, 56, 97, 57, 10, 54, 49, 113, 110, 56, 70, 89, 105, 113, 84, 120, 108, 86, 77, 89, 86, 113, 76, 50, 71, 110, 115, 50, 68, 108, 109, 104, 54, 99, 89, 71, 74, 52, 81, 118, 104, 54, 104, 69, 98, 97, 65, 106, 77, 97, 90, 55, 115, 110, 107, 71, 101, 82, 68, 73, 109, 101, 117, 75, 72, 67, 110, 69, 57, 54, 43, 82, 97, 112, 78, 76, 98, 120, 99, 51, 71, 10, 51, 109, 66, 47, 117, 102, 78, 80, 82, 74, 76, 118, 75, 114, 99, 89, 80, 113, 99, 90, 50, 81, 116, 57, 115, 84, 100, 66, 81, 114, 67, 54, 89, 66, 51, 121, 47, 103, 107, 82, 115, 80, 67, 72, 101, 54, 101, 100, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 81, 117, 111, 86, 97, 100, 105, 115, 32, 82, 111, 111, 116, 32, 67, 65, 32, 49, 32, 71, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 89, 68, 67, 67, 65, 48, 105, 103, 65, 119, 73, 66, 65, 103, 73, 85, 101, 70, 104, 102, 76, 113, 48, 115, 71, 85, 118, 106, 78, 119, 99, 49, 78, 66, 77, 111, 116, 90, 98, 85, 90, 90, 77, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 83, 68, 69, 76, 77, 65, 107, 71, 10, 65, 49, 85, 69, 66, 104, 77, 67, 81, 107, 48, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 111, 84, 69, 70, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 72, 106, 65, 99, 66, 103, 78, 86, 66, 65, 77, 84, 70, 86, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 70, 74, 118, 10, 98, 51, 81, 103, 81, 48, 69, 103, 77, 83, 66, 72, 77, 122, 65, 101, 70, 119, 48, 120, 77, 106, 65, 120, 77, 84, 73, 120, 78, 122, 73, 51, 78, 68, 82, 97, 70, 119, 48, 48, 77, 106, 65, 120, 77, 84, 73, 120, 78, 122, 73, 51, 78, 68, 82, 97, 77, 69, 103, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 74, 78, 10, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 75, 69, 120, 66, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 77, 97, 87, 49, 112, 100, 71, 86, 107, 77, 82, 52, 119, 72, 65, 89, 68, 86, 81, 81, 68, 69, 120, 86, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 68, 69, 103, 10, 82, 122, 77, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 103, 118, 108, 65, 81, 106, 117, 110, 121, 98, 69, 67, 48, 66, 74, 121, 70, 117, 84, 72, 75, 51, 67, 51, 107, 69, 97, 107, 69, 10, 80, 66, 116, 86, 119, 101, 100, 89, 77, 66, 48, 107, 116, 77, 80, 118, 104, 100, 54, 77, 76, 79, 72, 66, 80, 100, 43, 67, 53, 107, 43, 116, 82, 52, 100, 115, 55, 70, 116, 74, 119, 85, 114, 86, 117, 52, 47, 115, 104, 54, 120, 47, 103, 112, 113, 71, 55, 68, 48, 68, 109, 86, 73, 66, 48, 106, 87, 101, 114, 78, 114, 119, 85, 56, 108, 109, 10, 80, 78, 83, 115, 65, 103, 72, 97, 74, 78, 77, 55, 113, 65, 74, 71, 114, 54, 81, 99, 52, 47, 104, 122, 87, 72, 97, 51, 57, 103, 54, 81, 68, 98, 88, 119, 122, 56, 122, 54, 43, 99, 90, 77, 53, 99, 79, 71, 77, 65, 113, 78, 70, 51, 52, 49, 54, 56, 88, 102, 117, 119, 54, 99, 119, 73, 50, 72, 52, 52, 103, 52, 104, 87, 102, 54, 10, 80, 115, 101, 114, 52, 66, 79, 99, 66, 82, 105, 89, 122, 53, 80, 49, 115, 90, 75, 48, 47, 67, 80, 84, 122, 57, 88, 69, 74, 48, 110, 103, 110, 106, 121, 98, 67, 75, 79, 76, 88, 83, 111, 104, 52, 80, 119, 53, 113, 108, 80, 97, 102, 88, 55, 80, 71, 103, 108, 84, 118, 70, 48, 70, 66, 77, 43, 104, 83, 111, 43, 76, 100, 111, 73, 78, 10, 111, 102, 106, 83, 120, 120, 82, 51, 87, 53, 65, 50, 66, 52, 71, 98, 80, 103, 98, 54, 85, 108, 53, 106, 120, 97, 89, 65, 47, 113, 88, 112, 85, 104, 116, 83, 116, 90, 73, 53, 99, 103, 77, 74, 89, 114, 50, 119, 89, 66, 90, 117, 112, 116, 48, 108, 119, 103, 78, 109, 51, 102, 77, 69, 48, 85, 68, 105, 84, 111, 117, 71, 57, 71, 47, 108, 10, 103, 54, 65, 110, 104, 70, 52, 69, 119, 102, 87, 81, 118, 84, 65, 57, 120, 79, 43, 111, 97, 98, 119, 52, 109, 54, 83, 107, 108, 116, 70, 105, 50, 109, 110, 65, 65, 90, 97, 117, 121, 56, 82, 82, 78, 79, 111, 77, 113, 118, 56, 104, 106, 108, 109, 80, 83, 108, 122, 107, 89, 90, 113, 110, 48, 117, 107, 113, 101, 73, 49, 82, 80, 84, 111, 86, 10, 55, 113, 74, 90, 106, 113, 108, 99, 51, 115, 88, 53, 107, 67, 76, 108, 105, 69, 86, 120, 51, 90, 71, 90, 98, 72, 113, 102, 80, 84, 50, 89, 102, 70, 55, 50, 118, 104, 90, 111, 111, 70, 54, 117, 67, 121, 80, 56, 87, 103, 43, 113, 73, 110, 89, 116, 121, 97, 69, 81, 72, 101, 84, 84, 82, 67, 79, 81, 105, 74, 47, 71, 75, 117, 98, 88, 10, 57, 90, 113, 122, 87, 66, 52, 118, 77, 73, 107, 73, 71, 49, 83, 105, 116, 90, 103, 106, 55, 65, 104, 51, 72, 74, 86, 100, 89, 100, 72, 76, 105, 90, 120, 102, 111, 107, 113, 82, 109, 117, 56, 104, 113, 107, 107, 87, 67, 75, 105, 57, 89, 83, 103, 120, 121, 88, 83, 116, 104, 102, 98, 90, 120, 98, 71, 76, 48, 101, 85, 81, 77, 107, 49, 102, 10, 105, 121, 65, 54, 80, 69, 107, 102, 77, 52, 86, 90, 68, 100, 118, 76, 67, 88, 86, 68, 97, 88, 80, 55, 97, 51, 70, 57, 56, 78, 47, 69, 84, 72, 51, 71, 111, 121, 55, 73, 108, 88, 110, 76, 99, 54, 75, 79, 84, 107, 48, 107, 43, 49, 55, 107, 66, 76, 53, 121, 71, 54, 89, 110, 76, 85, 108, 97, 109, 88, 114, 88, 88, 65, 107, 103, 10, 116, 51, 43, 85, 117, 85, 47, 120, 68, 82, 120, 101, 105, 69, 73, 98, 69, 98, 102, 110, 107, 100, 117, 101, 98, 80, 82, 113, 51, 52, 119, 71, 109, 65, 79, 116, 122, 67, 106, 118, 112, 85, 102, 122, 85, 119, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 10, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 111, 53, 102, 87, 56, 49, 54, 105, 69, 79, 71, 114, 82, 90, 56, 56, 70, 50, 81, 56, 55, 103, 70, 119, 110, 77, 119, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 73, 66, 65, 66, 106, 54, 87, 51, 88, 56, 80, 110, 114, 72, 88, 51, 102, 72, 121, 116, 47, 80, 88, 56, 77, 83, 120, 69, 66, 100, 49, 68, 75, 113, 117, 71, 114, 88, 49, 82, 85, 86, 82, 112, 103, 106, 112, 101, 97, 81, 87, 120, 105, 90, 84, 79, 79, 116, 81, 113, 79, 67, 10, 77, 84, 97, 73, 122, 101, 110, 55, 120, 65, 83, 87, 83, 73, 115, 66, 120, 52, 48, 66, 122, 49, 115, 122, 66, 112, 90, 71, 90, 110, 81, 100, 84, 43, 51, 66, 116, 114, 109, 48, 68, 87, 72, 77, 89, 51, 55, 88, 76, 110, 101, 77, 108, 104, 119, 113, 73, 50, 104, 114, 104, 86, 100, 50, 99, 68, 77, 84, 47, 117, 70, 80, 112, 105, 78, 51, 10, 71, 80, 111, 97, 106, 79, 105, 57, 90, 99, 110, 80, 80, 47, 84, 74, 70, 57, 122, 114, 120, 55, 122, 65, 66, 67, 52, 116, 82, 105, 57, 112, 90, 115, 77, 98, 106, 47, 55, 115, 80, 116, 80, 75, 108, 76, 57, 50, 67, 105, 85, 78, 113, 88, 115, 67, 72, 75, 110, 81, 79, 49, 56, 76, 119, 73, 69, 54, 80, 87, 84, 104, 118, 54, 99, 116, 10, 84, 114, 49, 78, 120, 78, 103, 112, 120, 105, 73, 89, 48, 77, 87, 115, 99, 103, 75, 67, 80, 54, 111, 54, 111, 106, 111, 105, 108, 122, 72, 100, 67, 71, 80, 68, 100, 82, 83, 53, 89, 67, 103, 116, 87, 50, 106, 103, 70, 113, 108, 109, 103, 105, 78, 82, 57, 101, 116, 84, 50, 68, 71, 98, 101, 43, 109, 51, 110, 85, 118, 114, 105, 66, 98, 80, 10, 43, 86, 48, 52, 105, 107, 107, 119, 106, 43, 51, 120, 54, 120, 110, 48, 100, 120, 111, 120, 71, 69, 49, 110, 86, 71, 119, 118, 98, 50, 88, 53, 50, 122, 51, 115, 73, 101, 120, 101, 57, 80, 83, 76, 121, 109, 66, 108, 86, 78, 70, 120, 90, 80, 84, 53, 112, 113, 79, 66, 77, 122, 89, 122, 99, 102, 67, 107, 101, 70, 57, 79, 114, 89, 77, 104, 10, 51, 106, 82, 74, 106, 101, 104, 90, 114, 74, 51, 121, 100, 108, 111, 50, 56, 104, 80, 48, 114, 43, 65, 74, 120, 50, 69, 113, 98, 80, 102, 103, 110, 97, 54, 55, 104, 107, 111, 111, 98, 121, 55, 117, 116, 72, 110, 78, 107, 68, 80, 68, 115, 51, 98, 54, 57, 102, 66, 115, 110, 81, 71, 81, 43, 112, 54, 81, 57, 112, 120, 121, 122, 48, 102, 97, 10, 119, 120, 47, 107, 78, 83, 66, 84, 56, 108, 84, 82, 51, 50, 71, 68, 112, 103, 76, 105, 74, 84, 106, 101, 104, 84, 73, 116, 88, 110, 79, 81, 85, 108, 49, 67, 120, 77, 52, 57, 83, 43, 72, 53, 71, 89, 81, 100, 49, 97, 74, 81, 122, 69, 72, 55, 81, 82, 84, 68, 118, 100, 98, 74, 87, 113, 78, 106, 90, 103, 75, 65, 118, 81, 85, 54, 10, 79, 48, 101, 99, 55, 65, 65, 109, 84, 80, 87, 73, 85, 98, 43, 111, 73, 51, 56, 89, 66, 55, 65, 76, 55, 89, 115, 109, 111, 87, 84, 84, 89, 85, 114, 114, 88, 74, 47, 101, 115, 54, 57, 110, 65, 55, 77, 102, 51, 87, 49, 100, 97, 87, 104, 112, 113, 49, 52, 54, 55, 72, 120, 112, 118, 77, 99, 55, 104, 85, 54, 101, 70, 98, 109, 48, 10, 70, 85, 47, 68, 108, 88, 112, 89, 49, 56, 108, 115, 54, 87, 121, 53, 56, 121, 108, 106, 88, 114, 81, 115, 56, 67, 48, 57, 55, 86, 112, 108, 52, 75, 108, 98, 81, 77, 74, 73, 109, 89, 70, 116, 110, 104, 56, 71, 75, 106, 119, 83, 116, 73, 115, 80, 109, 54, 73, 107, 56, 75, 97, 78, 49, 110, 114, 103, 83, 55, 90, 107, 108, 109, 79, 86, 10, 104, 77, 74, 75, 122, 82, 119, 117, 74, 73, 99, 122, 89, 79, 88, 68, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 81, 117, 111, 86, 97, 100, 105, 115, 32, 82, 111, 111, 116, 32, 67, 65, 32, 50, 32, 71, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 89, 68, 67, 67, 65, 48, 105, 103, 65, 119, 73, 66, 65, 103, 73, 85, 82, 70, 99, 48, 74, 70, 117, 66, 105, 90, 115, 49, 56, 115, 54, 52, 75, 122, 116, 98, 112, 121, 98, 119, 100, 83, 103, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 83, 68, 69, 76, 77, 65, 107, 71, 10, 65, 49, 85, 69, 66, 104, 77, 67, 81, 107, 48, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 111, 84, 69, 70, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 72, 106, 65, 99, 66, 103, 78, 86, 66, 65, 77, 84, 70, 86, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 70, 74, 118, 10, 98, 51, 81, 103, 81, 48, 69, 103, 77, 105, 66, 72, 77, 122, 65, 101, 70, 119, 48, 120, 77, 106, 65, 120, 77, 84, 73, 120, 79, 68, 85, 53, 77, 122, 74, 97, 70, 119, 48, 48, 77, 106, 65, 120, 77, 84, 73, 120, 79, 68, 85, 53, 77, 122, 74, 97, 77, 69, 103, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 74, 78, 10, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 75, 69, 120, 66, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 77, 97, 87, 49, 112, 100, 71, 86, 107, 77, 82, 52, 119, 72, 65, 89, 68, 86, 81, 81, 68, 69, 120, 86, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 68, 73, 103, 10, 82, 122, 77, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 104, 114, 105, 87, 121, 65, 82, 106, 99, 86, 52, 103, 47, 82, 117, 118, 53, 114, 43, 76, 114, 73, 51, 72, 105, 109, 116, 70, 104, 10, 90, 105, 70, 102, 113, 113, 56, 110, 85, 101, 86, 117, 71, 120, 98, 85, 76, 88, 49, 81, 115, 70, 78, 51, 118, 88, 103, 54, 89, 79, 74, 107, 65, 112, 116, 56, 104, 112, 118, 87, 71, 111, 54, 116, 47, 120, 56, 86, 102, 57, 87, 86, 72, 104, 76, 76, 53, 104, 83, 69, 66, 77, 72, 102, 78, 114, 77, 87, 110, 52, 114, 106, 121, 100, 117, 89, 10, 78, 77, 55, 89, 77, 120, 99, 111, 82, 118, 121, 110, 121, 102, 68, 83, 116, 78, 86, 78, 67, 88, 74, 74, 43, 102, 75, 72, 52, 54, 110, 97, 102, 97, 70, 57, 97, 55, 73, 54, 74, 97, 108, 116, 85, 107, 83, 115, 43, 76, 53, 117, 43, 57, 121, 109, 99, 53, 71, 81, 89, 97, 89, 68, 70, 67, 68, 121, 53, 52, 101, 106, 105, 75, 50, 116, 10, 111, 73, 122, 47, 112, 103, 115, 108, 85, 105, 88, 110, 70, 103, 72, 86, 121, 55, 103, 49, 103, 81, 121, 106, 79, 47, 68, 104, 52, 102, 120, 97, 88, 99, 54, 65, 99, 87, 51, 52, 83, 97, 115, 43, 79, 55, 113, 52, 49, 52, 65, 66, 43, 54, 88, 114, 87, 55, 80, 70, 88, 109, 65, 113, 77, 97, 67, 118, 78, 43, 103, 103, 79, 112, 43, 111, 10, 77, 105, 119, 77, 122, 65, 107, 100, 48, 53, 54, 79, 88, 98, 120, 77, 109, 79, 55, 70, 71, 109, 104, 55, 55, 70, 79, 109, 54, 82, 81, 49, 111, 57, 47, 78, 103, 74, 56, 77, 83, 80, 115, 99, 57, 80, 71, 47, 83, 114, 106, 54, 49, 89, 120, 120, 83, 115, 99, 102, 114, 102, 53, 66, 109, 114, 79, 68, 88, 102, 75, 69, 86, 117, 43, 108, 10, 86, 48, 80, 79, 75, 97, 50, 77, 113, 49, 87, 47, 120, 80, 116, 98, 65, 100, 48, 106, 73, 97, 70, 89, 65, 73, 55, 68, 48, 71, 111, 84, 55, 82, 80, 106, 69, 105, 117, 65, 51, 71, 102, 109, 108, 98, 76, 78, 72, 105, 74, 117, 75, 118, 104, 66, 49, 80, 76, 75, 70, 65, 101, 78, 105, 108, 85, 83, 120, 109, 110, 49, 117, 73, 90, 111, 10, 76, 49, 78, 101, 115, 78, 75, 113, 73, 99, 71, 89, 53, 106, 68, 106, 90, 49, 88, 72, 109, 50, 54, 115, 71, 97, 104, 86, 112, 107, 85, 71, 48, 67, 77, 54, 50, 43, 116, 108, 88, 83, 111, 82, 69, 102, 65, 55, 84, 56, 112, 116, 57, 68, 84, 69, 99, 101, 84, 47, 65, 70, 114, 50, 88, 75, 52, 106, 89, 73, 86, 122, 56, 101, 81, 81, 10, 115, 83, 87, 117, 49, 90, 75, 55, 69, 56, 69, 77, 52, 68, 110, 97, 116, 68, 108, 88, 116, 97, 115, 49, 113, 110, 73, 104, 79, 52, 77, 49, 53, 122, 72, 102, 101, 105, 70, 117, 117, 68, 73, 73, 102, 82, 48, 121, 107, 82, 86, 75, 89, 110, 76, 80, 52, 51, 101, 104, 118, 78, 85, 82, 71, 51, 89, 66, 90, 119, 106, 103, 81, 81, 118, 68, 10, 54, 120, 86, 117, 43, 75, 81, 90, 50, 97, 75, 114, 114, 43, 73, 110, 85, 108, 89, 114, 65, 111, 111, 115, 70, 67, 84, 53, 118, 48, 73, 67, 118, 121, 98, 73, 120, 111, 47, 103, 98, 106, 104, 57, 85, 121, 51, 108, 55, 90, 105, 122, 108, 87, 78, 111, 102, 47, 107, 49, 57, 78, 43, 73, 120, 87, 65, 49, 107, 115, 66, 56, 97, 82, 120, 104, 10, 108, 82, 98, 81, 54, 57, 52, 76, 114, 122, 52, 69, 69, 69, 86, 108, 87, 70, 65, 52, 114, 48, 106, 121, 87, 98, 89, 87, 56, 106, 119, 78, 107, 65, 76, 71, 99, 67, 52, 66, 114, 84, 119, 86, 49, 119, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 10, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 55, 101, 100, 118, 100, 108, 113, 47, 89, 79, 120, 74, 87, 56, 97, 108, 100, 55, 116, 121, 70, 110, 71, 98, 120, 68, 48, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 73, 66, 65, 74, 72, 102, 103, 68, 57, 68, 67, 88, 53, 120, 119, 118, 102, 114, 115, 52, 105, 80, 52, 86, 71, 121, 118, 68, 49, 49, 43, 83, 104, 100, 121, 76, 121, 90, 109, 51, 116, 100, 113, 117, 88, 75, 52, 81, 114, 51, 54, 76, 76, 84, 110, 57, 49, 110, 77, 88, 54, 54, 10, 65, 97, 114, 72, 97, 107, 69, 55, 107, 78, 81, 73, 88, 76, 74, 103, 97, 112, 68, 119, 121, 77, 52, 68, 89, 118, 109, 76, 55, 102, 116, 117, 75, 116, 119, 71, 84, 84, 119, 112, 68, 52, 107, 87, 105, 108, 104, 77, 83, 65, 47, 111, 104, 71, 72, 113, 80, 72, 75, 109, 100, 43, 82, 67, 114, 111, 105, 106, 81, 49, 104, 53, 102, 113, 55, 75, 10, 112, 86, 77, 78, 113, 84, 49, 119, 118, 83, 65, 90, 89, 97, 82, 115, 79, 80, 120, 68, 77, 117, 72, 66, 82, 47, 47, 52, 55, 80, 69, 82, 73, 106, 75, 87, 110, 77, 76, 50, 87, 50, 109, 87, 101, 121, 65, 77, 81, 48, 71, 97, 87, 47, 90, 90, 71, 89, 106, 101, 86, 89, 103, 51, 85, 81, 116, 52, 88, 65, 111, 101, 111, 48, 76, 57, 10, 120, 53, 50, 73, 68, 56, 68, 121, 101, 65, 73, 107, 86, 74, 79, 118, 105, 89, 101, 73, 121, 85, 113, 65, 72, 101, 114, 81, 98, 106, 53, 104, 76, 106, 97, 55, 78, 81, 52, 110, 108, 118, 49, 109, 78, 68, 116, 104, 99, 110, 80, 120, 70, 108, 120, 72, 66, 108, 82, 74, 65, 72, 112, 89, 69, 114, 65, 75, 55, 52, 88, 57, 115, 98, 103, 122, 10, 100, 87, 113, 84, 72, 66, 76, 109, 89, 70, 53, 118, 72, 88, 47, 74, 72, 121, 80, 76, 104, 71, 71, 102, 72, 111, 74, 69, 43, 86, 43, 116, 89, 108, 85, 107, 109, 108, 75, 89, 55, 86, 72, 110, 111, 88, 54, 88, 79, 117, 89, 118, 72, 120, 72, 97, 85, 52, 65, 115, 104, 90, 54, 114, 78, 82, 68, 98, 73, 108, 57, 113, 120, 86, 54, 88, 10, 85, 47, 73, 121, 65, 103, 107, 119, 111, 49, 106, 119, 68, 81, 72, 86, 99, 115, 97, 120, 102, 71, 108, 55, 119, 47, 85, 50, 82, 99, 120, 104, 98, 108, 53, 77, 108, 77, 86, 101, 114, 117, 103, 79, 88, 111, 117, 47, 57, 56, 51, 103, 55, 97, 69, 79, 71, 122, 80, 117, 86, 66, 106, 43, 68, 55, 55, 118, 102, 111, 82, 114, 81, 43, 78, 119, 10, 109, 78, 116, 100, 100, 98, 73, 78, 87, 81, 101, 70, 70, 83, 77, 53, 49, 118, 72, 102, 113, 83, 89, 80, 49, 107, 106, 72, 115, 54, 89, 105, 57, 84, 77, 51, 87, 112, 86, 72, 110, 51, 117, 54, 71, 66, 86, 118, 47, 57, 89, 85, 90, 73, 78, 74, 48, 103, 112, 110, 73, 100, 115, 80, 78, 87, 78, 103, 75, 67, 76, 106, 115, 90, 87, 68, 10, 122, 89, 87, 109, 51, 83, 56, 80, 53, 50, 100, 83, 98, 114, 115, 118, 104, 88, 122, 49, 83, 110, 80, 110, 120, 84, 55, 65, 118, 83, 69, 83, 66, 84, 47, 56, 116, 119, 78, 74, 65, 108, 118, 73, 74, 101, 98, 105, 86, 68, 106, 49, 101, 89, 101, 77, 72, 86, 79, 121, 84, 111, 86, 55, 66, 106, 106, 72, 76, 80, 106, 52, 115, 72, 75, 78, 10, 74, 101, 86, 51, 85, 118, 81, 68, 72, 69, 105, 109, 85, 70, 43, 73, 73, 68, 66, 117, 56, 111, 74, 68, 113, 122, 50, 88, 104, 79, 100, 84, 43, 121, 72, 66, 84, 119, 56, 105, 109, 111, 97, 52, 87, 83, 114, 50, 82, 122, 48, 90, 105, 67, 51, 111, 104, 101, 71, 101, 55, 73, 85, 73, 97, 114, 70, 115, 78, 77, 107, 100, 55, 69, 103, 114, 10, 79, 51, 106, 116, 90, 115, 83, 79, 101, 87, 109, 68, 51, 110, 43, 77, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 81, 117, 111, 86, 97, 100, 105, 115, 32, 82, 111, 111, 116, 32, 67, 65, 32, 51, 32, 71, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 89, 68, 67, 67, 65, 48, 105, 103, 65, 119, 73, 66, 65, 103, 73, 85, 76, 118, 87, 98, 65, 105, 105, 110, 50, 51, 114, 47, 49, 97, 79, 112, 55, 114, 48, 68, 111, 77, 56, 83, 97, 104, 48, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 83, 68, 69, 76, 77, 65, 107, 71, 10, 65, 49, 85, 69, 66, 104, 77, 67, 81, 107, 48, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 111, 84, 69, 70, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 72, 106, 65, 99, 66, 103, 78, 86, 66, 65, 77, 84, 70, 86, 70, 49, 98, 49, 90, 104, 90, 71, 108, 122, 73, 70, 74, 118, 10, 98, 51, 81, 103, 81, 48, 69, 103, 77, 121, 66, 72, 77, 122, 65, 101, 70, 119, 48, 120, 77, 106, 65, 120, 77, 84, 73, 121, 77, 68, 73, 50, 77, 122, 74, 97, 70, 119, 48, 48, 77, 106, 65, 120, 77, 84, 73, 121, 77, 68, 73, 50, 77, 122, 74, 97, 77, 69, 103, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 74, 78, 10, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 75, 69, 120, 66, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 77, 97, 87, 49, 112, 100, 71, 86, 107, 77, 82, 52, 119, 72, 65, 89, 68, 86, 81, 81, 68, 69, 120, 86, 82, 100, 87, 57, 87, 89, 87, 82, 112, 99, 121, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 68, 77, 103, 10, 82, 122, 77, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 122, 121, 119, 52, 81, 90, 52, 55, 113, 70, 74, 101, 110, 77, 105, 111, 75, 86, 106, 90, 47, 97, 69, 122, 72, 115, 50, 56, 54, 10, 73, 120, 83, 82, 47, 120, 108, 47, 112, 99, 113, 115, 55, 114, 78, 50, 110, 88, 114, 112, 105, 120, 117, 114, 97, 122, 72, 98, 43, 103, 116, 84, 84, 75, 47, 70, 112, 82, 112, 53, 80, 73, 112, 77, 47, 54, 122, 102, 74, 100, 53, 79, 50, 89, 73, 121, 67, 48, 84, 101, 121, 116, 117, 77, 114, 75, 78, 117, 70, 111, 77, 55, 112, 109, 82, 76, 10, 77, 111, 110, 55, 70, 104, 89, 52, 102, 117, 116, 68, 52, 116, 78, 48, 83, 115, 74, 105, 67, 110, 77, 75, 51, 85, 109, 122, 86, 57, 75, 119, 67, 111, 87, 100, 99, 84, 122, 101, 111, 56, 118, 65, 77, 118, 77, 66, 79, 83, 66, 68, 71, 122, 88, 82, 85, 55, 79, 120, 55, 115, 87, 84, 97, 89, 73, 43, 70, 114, 85, 111, 82, 113, 72, 101, 10, 54, 111, 107, 74, 55, 85, 79, 52, 66, 85, 97, 75, 104, 118, 86, 90, 82, 55, 52, 98, 98, 119, 69, 104, 69, 76, 110, 57, 113, 100, 73, 111, 121, 104, 65, 53, 67, 99, 111, 84, 78, 115, 43, 99, 114, 97, 49, 65, 100, 72, 107, 114, 65, 106, 56, 48, 47, 47, 111, 103, 97, 88, 51, 84, 55, 109, 72, 49, 117, 114, 80, 110, 77, 78, 65, 51, 10, 73, 52, 90, 121, 89, 85, 85, 112, 83, 70, 108, 111, 98, 51, 101, 109, 76, 111, 71, 43, 66, 48, 49, 118, 114, 56, 55, 69, 82, 82, 79, 82, 70, 72, 65, 71, 106, 120, 43, 102, 43, 73, 100, 112, 115, 81, 55, 118, 119, 52, 107, 90, 54, 43, 111, 99, 89, 102, 120, 54, 98, 73, 114, 99, 49, 103, 77, 76, 110, 105, 97, 54, 69, 116, 51, 85, 10, 86, 68, 109, 114, 74, 113, 77, 122, 54, 110, 87, 66, 50, 105, 51, 78, 68, 48, 47, 107, 65, 57, 72, 118, 70, 90, 99, 98, 97, 53, 68, 70, 65, 112, 67, 84, 90, 103, 73, 104, 115, 85, 102, 101, 105, 53, 112, 75, 103, 76, 108, 86, 106, 55, 87, 105, 76, 56, 68, 87, 77, 50, 102, 97, 102, 115, 83, 110, 116, 65, 82, 69, 54, 48, 102, 55, 10, 53, 108, 105, 53, 57, 119, 122, 119, 101, 121, 117, 120, 119, 72, 65, 112, 119, 48, 66, 105, 76, 84, 116, 73, 97, 100, 119, 106, 80, 69, 106, 114, 101, 119, 108, 53, 113, 87, 51, 97, 113, 68, 67, 89, 122, 52, 66, 121, 65, 52, 105, 109, 87, 48, 97, 117, 99, 110, 108, 56, 67, 65, 77, 104, 90, 97, 54, 51, 52, 82, 121, 108, 115, 83, 113, 105, 10, 77, 100, 53, 109, 66, 80, 102, 65, 100, 79, 104, 120, 51, 118, 56, 57, 87, 99, 121, 87, 74, 104, 75, 76, 104, 90, 86, 88, 71, 113, 116, 114, 100, 81, 116, 69, 80, 82, 69, 111, 80, 72, 116, 104, 116, 43, 75, 80, 90, 48, 47, 108, 55, 68, 120, 77, 89, 73, 66, 112, 86, 122, 103, 101, 65, 86, 117, 78, 86, 101, 106, 72, 51, 56, 68, 77, 10, 100, 121, 77, 48, 83, 88, 86, 56, 57, 112, 103, 82, 54, 121, 51, 101, 55, 85, 69, 117, 70, 65, 85, 67, 102, 43, 68, 43, 73, 79, 115, 49, 53, 120, 71, 115, 73, 115, 53, 88, 80, 100, 55, 74, 77, 71, 48, 81, 65, 52, 88, 78, 56, 102, 43, 77, 70, 114, 88, 66, 115, 106, 54, 73, 98, 71, 66, 47, 107, 69, 43, 86, 57, 47, 89, 116, 10, 114, 81, 69, 53, 66, 119, 84, 54, 100, 89, 66, 57, 118, 48, 108, 81, 55, 101, 47, 74, 120, 72, 119, 99, 54, 52, 66, 43, 50, 55, 98, 81, 51, 82, 80, 43, 121, 100, 79, 99, 49, 55, 75, 88, 113, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 10, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 120, 104, 102, 81, 118, 75, 106, 113, 65, 107, 80, 121, 71, 119, 97, 90, 88, 83, 117, 81, 73, 76, 110, 88, 110, 79, 81, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 73, 66, 65, 68, 82, 104, 50, 86, 97, 49, 69, 111, 100, 86, 84, 100, 50, 106, 78, 84, 70, 71, 117, 54, 81, 72, 99, 114, 120, 102, 89, 87, 76, 111, 112, 102, 115, 76, 78, 55, 69, 56, 116, 114, 80, 54, 75, 90, 49, 47, 65, 118, 87, 107, 121, 97, 105, 84, 116, 51, 112, 120, 10, 75, 71, 109, 80, 99, 43, 70, 83, 107, 78, 114, 86, 118, 106, 114, 108, 116, 51, 90, 113, 86, 111, 65, 104, 51, 49, 51, 109, 54, 84, 113, 101, 53, 84, 55, 50, 111, 109, 110, 72, 75, 103, 113, 119, 71, 69, 102, 99, 73, 72, 66, 57, 85, 113, 77, 43, 87, 88, 122, 66, 117, 115, 110, 73, 70, 85, 66, 104, 121, 110, 76, 87, 99, 75, 122, 83, 10, 116, 47, 65, 99, 53, 73, 89, 112, 56, 77, 55, 118, 97, 71, 80, 81, 116, 83, 67, 75, 70, 87, 71, 97, 102, 111, 97, 89, 116, 77, 110, 67, 100, 118, 118, 77, 117, 106, 65, 87, 122, 75, 78, 104, 120, 110, 81, 84, 53, 87, 118, 118, 111, 120, 88, 113, 65, 47, 52, 84, 105, 50, 84, 107, 48, 56, 72, 83, 54, 73, 84, 55, 83, 100, 69, 81, 10, 84, 88, 108, 109, 54, 54, 114, 57, 57, 73, 48, 120, 72, 110, 65, 85, 114, 100, 122, 101, 90, 120, 78, 77, 103, 82, 86, 104, 118, 76, 102, 90, 107, 88, 100, 120, 71, 89, 70, 103, 117, 47, 66, 89, 112, 98, 87, 99, 67, 47, 101, 80, 73, 108, 85, 110, 119, 69, 115, 66, 98, 84, 117, 90, 68, 100, 81, 100, 109, 50, 78, 110, 76, 57, 68, 117, 10, 68, 99, 112, 109, 118, 74, 82, 80, 112, 113, 51, 116, 47, 79, 53, 106, 114, 70, 99, 47, 90, 83, 88, 80, 115, 111, 97, 80, 48, 65, 106, 47, 117, 72, 89, 85, 98, 116, 55, 108, 74, 43, 121, 114, 101, 76, 86, 84, 117, 98, 89, 47, 54, 67, 68, 53, 48, 113, 105, 43, 89, 85, 98, 75, 104, 52, 121, 69, 56, 47, 110, 120, 111, 71, 105, 98, 10, 73, 104, 54, 66, 74, 112, 115, 81, 66, 74, 70, 120, 119, 65, 89, 102, 51, 75, 68, 84, 117, 86, 97, 110, 52, 53, 103, 116, 102, 52, 79, 100, 51, 52, 119, 114, 110, 68, 75, 79, 77, 112, 84, 119, 65, 84, 119, 105, 75, 112, 57, 68, 119, 105, 55, 68, 109, 68, 107, 72, 79, 72, 118, 56, 88, 103, 66, 67, 72, 47, 77, 121, 74, 110, 109, 68, 10, 104, 80, 98, 108, 56, 77, 70, 82, 69, 115, 65, 76, 72, 103, 81, 106, 68, 70, 83, 108, 84, 67, 57, 74, 120, 85, 114, 82, 116, 109, 53, 103, 68, 87, 118, 56, 97, 52, 117, 70, 74, 71, 83, 51, 105, 81, 54, 114, 74, 85, 100, 98, 80, 77, 57, 43, 83, 98, 51, 72, 54, 81, 114, 71, 50, 118, 100, 43, 68, 104, 99, 73, 48, 48, 105, 88, 10, 48, 72, 71, 83, 56, 65, 56, 53, 80, 106, 82, 113, 72, 72, 51, 89, 56, 105, 75, 117, 117, 50, 110, 48, 77, 55, 83, 109, 83, 70, 88, 82, 68, 119, 52, 109, 54, 79, 121, 50, 67, 121, 50, 110, 104, 84, 88, 78, 47, 86, 110, 73, 110, 57, 72, 78, 80, 108, 111, 112, 78, 76, 107, 57, 104, 77, 54, 120, 90, 100, 82, 90, 107, 90, 70, 87, 10, 100, 83, 72, 66, 100, 53, 55, 53, 101, 117, 70, 103, 110, 100, 79, 116, 66, 66, 106, 48, 102, 79, 116, 101, 107, 52, 57, 84, 83, 105, 73, 112, 43, 69, 103, 114, 80, 107, 50, 71, 114, 70, 116, 47, 121, 119, 97, 90, 87, 87, 68, 89, 87, 71, 87, 86, 106, 85, 84, 82, 57, 51, 57, 43, 74, 51, 57, 57, 114, 111, 68, 49, 66, 48, 121, 50, 10, 80, 112, 120, 120, 86, 74, 107, 69, 83, 47, 49, 89, 43, 90, 106, 48, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 105, 103, 105, 67, 101, 114, 116, 32, 65, 115, 115, 117, 114, 101, 100, 32, 73, 68, 32, 82, 111, 111, 116, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 108, 106, 67, 67, 65, 110, 54, 103, 65, 119, 73, 66, 65, 103, 73, 81, 67, 53, 77, 99, 79, 116, 89, 53, 90, 43, 112, 110, 73, 55, 47, 68, 114, 53, 114, 48, 83, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 108, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 87, 53, 106, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 76, 69, 120, 66, 51, 100, 51, 99, 117, 90, 71, 108, 110, 97, 87, 78, 108, 99, 110, 81, 117, 89, 50, 57, 116, 77, 83, 81, 119, 10, 73, 103, 89, 68, 86, 81, 81, 68, 69, 120, 116, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 66, 99, 51, 78, 49, 99, 109, 86, 107, 73, 69, 108, 69, 73, 70, 74, 118, 98, 51, 81, 103, 82, 122, 73, 119, 72, 104, 99, 78, 77, 84, 77, 119, 79, 68, 65, 120, 77, 84, 73, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 122, 103, 119, 10, 77, 84, 69, 49, 77, 84, 73, 119, 77, 68, 65, 119, 87, 106, 66, 108, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 87, 53, 106, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 76, 10, 69, 120, 66, 51, 100, 51, 99, 117, 90, 71, 108, 110, 97, 87, 78, 108, 99, 110, 81, 117, 89, 50, 57, 116, 77, 83, 81, 119, 73, 103, 89, 68, 86, 81, 81, 68, 69, 120, 116, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 66, 99, 51, 78, 49, 99, 109, 86, 107, 73, 69, 108, 69, 73, 70, 74, 118, 98, 51, 81, 103, 82, 122, 73, 119, 10, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 68, 90, 53, 121, 103, 118, 85, 106, 56, 50, 99, 107, 109, 73, 107, 122, 84, 122, 43, 71, 111, 101, 77, 86, 83, 65, 110, 54, 49, 85, 81, 98, 86, 72, 10, 51, 53, 97, 111, 49, 75, 43, 65, 76, 98, 107, 75, 122, 51, 88, 57, 105, 97, 86, 57, 74, 80, 114, 106, 73, 103, 119, 114, 118, 74, 85, 88, 67, 122, 79, 47, 71, 85, 49, 66, 66, 112, 65, 65, 118, 81, 120, 78, 69, 80, 52, 72, 116, 101, 99, 99, 98, 105, 74, 86, 77, 87, 87, 88, 118, 100, 77, 88, 48, 104, 53, 105, 56, 57, 118, 113, 10, 98, 70, 67, 77, 80, 52, 81, 77, 108, 115, 43, 51, 121, 119, 80, 103, 121, 109, 50, 104, 70, 69, 119, 98, 105, 100, 51, 116, 65, 76, 66, 83, 102, 75, 43, 82, 98, 76, 69, 52, 69, 57, 72, 112, 69, 103, 106, 65, 65, 76, 65, 99, 75, 120, 72, 97, 100, 51, 65, 50, 109, 54, 55, 79, 101, 89, 102, 99, 103, 110, 68, 109, 67, 88, 82, 119, 10, 86, 87, 109, 118, 111, 50, 105, 102, 118, 57, 50, 50, 101, 98, 80, 121, 110, 88, 65, 112, 86, 102, 83, 114, 47, 53, 86, 104, 56, 56, 108, 65, 98, 120, 51, 82, 118, 112, 79, 55, 48, 52, 103, 113, 117, 53, 50, 47, 99, 108, 112, 87, 99, 84, 115, 47, 49, 80, 80, 82, 67, 118, 52, 111, 55, 54, 80, 117, 50, 90, 109, 118, 65, 57, 79, 80, 10, 89, 76, 102, 121, 107, 113, 71, 120, 118, 89, 109, 74, 72, 122, 68, 78, 119, 54, 89, 117, 89, 106, 79, 117, 70, 103, 74, 51, 82, 70, 114, 110, 103, 81, 111, 56, 112, 48, 81, 117, 101, 98, 103, 47, 66, 76, 120, 99, 111, 73, 102, 104, 71, 54, 57, 82, 106, 115, 51, 115, 76, 80, 114, 52, 47, 109, 51, 119, 79, 110, 121, 113, 105, 43, 82, 110, 10, 108, 84, 71, 78, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 71, 71, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 84, 79, 10, 119, 48, 113, 53, 109, 86, 88, 121, 117, 78, 116, 103, 118, 54, 108, 43, 118, 86, 97, 49, 108, 122, 97, 110, 49, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, 67, 65, 81, 69, 65, 121, 113, 86, 86, 106, 79, 80, 73, 81, 87, 53, 112, 74, 54, 100, 49, 69, 101, 56, 56, 104, 106, 90, 118, 10, 48, 112, 51, 71, 101, 68, 103, 100, 97, 90, 97, 105, 107, 109, 107, 117, 79, 71, 121, 98, 102, 81, 84, 85, 105, 97, 87, 120, 77, 84, 101, 75, 121, 83, 72, 77, 113, 50, 122, 78, 105, 120, 121, 97, 49, 114, 57, 73, 48, 106, 74, 109, 119, 89, 114, 65, 56, 121, 56, 54, 55, 56, 68, 106, 49, 74, 71, 71, 48, 86, 68, 106, 65, 57, 116, 122, 10, 100, 50, 57, 75, 79, 86, 80, 116, 51, 105, 98, 72, 116, 88, 50, 118, 75, 48, 76, 82, 100, 87, 76, 106, 83, 105, 115, 67, 120, 49, 66, 76, 52, 71, 110, 105, 108, 109, 119, 79, 82, 71, 89, 81, 82, 73, 43, 116, 66, 101, 118, 52, 101, 97, 121, 109, 71, 43, 103, 51, 78, 74, 49, 84, 121, 87, 71, 113, 111, 108, 75, 118, 83, 110, 65, 87, 10, 104, 115, 73, 54, 121, 76, 69, 84, 99, 68, 98, 89, 122, 43, 55, 48, 67, 106, 84, 86, 87, 48, 122, 57, 66, 53, 121, 105, 117, 116, 107, 66, 99, 108, 122, 122, 84, 99, 72, 100, 68, 114, 69, 99, 68, 99, 82, 106, 118, 113, 51, 48, 70, 80, 117, 74, 55, 75, 74, 66, 68, 107, 122, 77, 121, 70, 100, 65, 48, 71, 52, 68, 113, 115, 48, 77, 10, 106, 111, 109, 90, 109, 87, 122, 119, 80, 68, 67, 118, 79, 78, 57, 118, 118, 75, 79, 43, 75, 83, 65, 110, 113, 51, 84, 47, 69, 121, 74, 52, 51, 112, 100, 83, 86, 82, 54, 68, 116, 86, 81, 103, 65, 43, 54, 117, 119, 69, 57, 87, 51, 106, 102, 77, 119, 51, 43, 113, 66, 67, 101, 55, 48, 51, 101, 52, 89, 116, 115, 88, 102, 74, 119, 111, 10, 73, 104, 78, 122, 98, 77, 56, 109, 57, 89, 111, 112, 53, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 105, 103, 105, 67, 101, 114, 116, 32, 65, 115, 115, 117, 114, 101, 100, 32, 73, 68, 32, 82, 111, 111, 116, 32, 71, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 82, 106, 67, 67, 65, 99, 50, 103, 65, 119, 73, 66, 65, 103, 73, 81, 67, 54, 70, 97, 43, 104, 51, 102, 111, 76, 86, 74, 82, 75, 47, 78, 74, 75, 66, 115, 55, 68, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 122, 66, 108, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 10, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 87, 53, 106, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 76, 69, 120, 66, 51, 100, 51, 99, 117, 90, 71, 108, 110, 97, 87, 78, 108, 99, 110, 81, 117, 89, 50, 57, 116, 77, 83, 81, 119, 73, 103, 89, 68, 10, 86, 81, 81, 68, 69, 120, 116, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 66, 99, 51, 78, 49, 99, 109, 86, 107, 73, 69, 108, 69, 73, 70, 74, 118, 98, 51, 81, 103, 82, 122, 77, 119, 72, 104, 99, 78, 77, 84, 77, 119, 79, 68, 65, 120, 77, 84, 73, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 122, 103, 119, 77, 84, 69, 49, 10, 77, 84, 73, 119, 77, 68, 65, 119, 87, 106, 66, 108, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 87, 53, 106, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 76, 69, 120, 66, 51, 10, 100, 51, 99, 117, 90, 71, 108, 110, 97, 87, 78, 108, 99, 110, 81, 117, 89, 50, 57, 116, 77, 83, 81, 119, 73, 103, 89, 68, 86, 81, 81, 68, 69, 120, 116, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 66, 99, 51, 78, 49, 99, 109, 86, 107, 73, 69, 108, 69, 73, 70, 74, 118, 98, 51, 81, 103, 82, 122, 77, 119, 100, 106, 65, 81, 10, 66, 103, 99, 113, 104, 107, 106, 79, 80, 81, 73, 66, 66, 103, 85, 114, 103, 81, 81, 65, 73, 103, 78, 105, 65, 65, 81, 90, 53, 55, 121, 115, 82, 71, 88, 116, 122, 98, 103, 47, 87, 80, 117, 78, 115, 86, 101, 112, 82, 67, 48, 70, 70, 102, 76, 118, 67, 47, 56, 81, 100, 74, 43, 49, 89, 108, 74, 102, 90, 110, 52, 102, 53, 100, 119, 98, 10, 82, 88, 107, 76, 122, 77, 90, 84, 67, 112, 50, 78, 88, 81, 76, 90, 113, 86, 110, 101, 65, 108, 114, 50, 108, 83, 111, 79, 106, 84, 104, 75, 105, 107, 110, 71, 118, 77, 89, 68, 79, 65, 100, 102, 86, 100, 112, 43, 67, 87, 55, 105, 102, 49, 55, 81, 82, 83, 65, 80, 87, 88, 89, 81, 49, 113, 65, 107, 56, 67, 51, 101, 78, 118, 74, 115, 10, 75, 84, 109, 106, 81, 106, 66, 65, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 71, 71, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 84, 76, 48, 76, 50, 112, 52, 90, 103, 70, 10, 85, 97, 70, 78, 78, 54, 75, 68, 101, 99, 54, 78, 72, 83, 114, 107, 104, 68, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 119, 78, 110, 65, 68, 66, 107, 65, 106, 65, 108, 112, 73, 70, 70, 65, 109, 115, 83, 83, 51, 86, 48, 84, 56, 103, 106, 52, 51, 68, 121, 100, 88, 76, 101, 102, 73, 110, 119, 122, 53, 70, 121, 10, 89, 90, 53, 101, 69, 74, 74, 90, 86, 114, 109, 68, 120, 120, 68, 110, 79, 79, 108, 89, 74, 106, 90, 57, 49, 101, 81, 48, 104, 106, 107, 67, 77, 72, 119, 50, 85, 47, 65, 119, 53, 87, 74, 106, 79, 112, 110, 105, 116, 113, 77, 55, 109, 122, 84, 54, 72, 116, 111, 81, 107, 110, 70, 101, 107, 82, 79, 110, 51, 97, 82, 117, 107, 115, 119, 121, 10, 49, 118, 85, 104, 90, 115, 99, 118, 54, 112, 90, 106, 97, 109, 86, 70, 107, 112, 85, 66, 116, 65, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 105, 103, 105, 67, 101, 114, 116, 32, 71, 108, 111, 98, 97, 108, 32, 82, 111, 111, 116, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 106, 106, 67, 67, 65, 110, 97, 103, 65, 119, 73, 66, 65, 103, 73, 81, 65, 122, 114, 120, 53, 113, 99, 82, 113, 97, 67, 55, 75, 71, 83, 120, 72, 81, 110, 54, 53, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 104, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 87, 53, 106, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 76, 69, 120, 66, 51, 100, 51, 99, 117, 90, 71, 108, 110, 97, 87, 78, 108, 99, 110, 81, 117, 89, 50, 57, 116, 77, 83, 65, 119, 10, 72, 103, 89, 68, 86, 81, 81, 68, 69, 120, 100, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 72, 98, 71, 57, 105, 89, 87, 119, 103, 85, 109, 57, 118, 100, 67, 66, 72, 77, 106, 65, 101, 70, 119, 48, 120, 77, 122, 65, 52, 77, 68, 69, 120, 77, 106, 65, 119, 77, 68, 66, 97, 70, 119, 48, 122, 79, 68, 65, 120, 77, 84, 85, 120, 10, 77, 106, 65, 119, 77, 68, 66, 97, 77, 71, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 85, 119, 69, 119, 89, 68, 86, 81, 81, 75, 69, 119, 120, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 74, 98, 109, 77, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 115, 84, 69, 72, 100, 51, 10, 100, 121, 53, 107, 97, 87, 100, 112, 89, 50, 86, 121, 100, 67, 53, 106, 98, 50, 48, 120, 73, 68, 65, 101, 66, 103, 78, 86, 66, 65, 77, 84, 70, 48, 82, 112, 90, 50, 108, 68, 90, 88, 74, 48, 73, 69, 100, 115, 98, 50, 74, 104, 98, 67, 66, 83, 98, 50, 57, 48, 73, 69, 99, 121, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 10, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 117, 122, 102, 78, 78, 78, 120, 55, 97, 56, 109, 121, 97, 74, 67, 116, 83, 110, 88, 47, 82, 114, 111, 104, 67, 103, 105, 78, 57, 82, 108, 85, 121, 102, 117, 73, 50, 47, 79, 117, 56, 106, 113, 74, 10, 107, 84, 120, 54, 53, 113, 115, 71, 71, 109, 118, 80, 114, 67, 51, 111, 88, 103, 107, 107, 82, 76, 112, 105, 109, 110, 55, 87, 111, 54, 104, 43, 52, 70, 82, 49, 73, 65, 87, 115, 85, 76, 101, 99, 89, 120, 112, 115, 77, 78, 122, 97, 72, 120, 109, 120, 49, 120, 55, 101, 47, 100, 102, 103, 121, 53, 83, 68, 78, 54, 55, 115, 72, 48, 78, 79, 10, 51, 88, 115, 115, 48, 114, 48, 117, 112, 83, 47, 107, 113, 98, 105, 116, 79, 116, 83, 90, 112, 76, 89, 108, 54, 90, 116, 114, 65, 71, 67, 83, 89, 80, 57, 80, 73, 85, 107, 89, 57, 50, 101, 81, 113, 50, 69, 71, 110, 73, 47, 121, 117, 117, 109, 48, 54, 90, 73, 121, 97, 55, 88, 122, 86, 43, 104, 100, 71, 56, 50, 77, 72, 97, 117, 86, 10, 66, 74, 86, 74, 56, 122, 85, 116, 108, 117, 78, 74, 98, 100, 49, 51, 52, 47, 116, 74, 83, 55, 83, 115, 86, 81, 101, 112, 106, 53, 87, 122, 116, 67, 79, 55, 84, 71, 49, 70, 56, 80, 97, 112, 115, 112, 85, 119, 116, 80, 49, 77, 86, 89, 119, 110, 83, 108, 99, 85, 102, 73, 75, 100, 122, 88, 79, 83, 48, 120, 90, 75, 66, 103, 121, 77, 10, 85, 78, 71, 80, 72, 103, 109, 43, 70, 54, 72, 109, 73, 99, 114, 57, 103, 43, 85, 81, 118, 73, 79, 108, 67, 115, 82, 110, 75, 80, 90, 122, 70, 66, 81, 57, 82, 110, 98, 68, 104, 120, 83, 74, 73, 84, 82, 78, 114, 119, 57, 70, 68, 75, 90, 74, 111, 98, 113, 55, 110, 77, 87, 120, 77, 52, 77, 112, 104, 81, 73, 68, 65, 81, 65, 66, 10, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 104, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 84, 105, 74, 85, 73, 66, 105, 86, 53, 117, 78, 117, 10, 53, 103, 47, 54, 43, 114, 107, 83, 55, 81, 89, 88, 106, 122, 107, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 69, 66, 65, 71, 66, 110, 75, 74, 82, 118, 68, 107, 104, 106, 54, 122, 72, 100, 54, 109, 99, 89, 49, 89, 108, 57, 80, 77, 87, 76, 83, 110, 47, 112, 118, 116, 115, 114, 10, 70, 57, 43, 119, 88, 51, 78, 51, 75, 106, 73, 84, 79, 89, 70, 110, 81, 111, 81, 106, 56, 107, 86, 110, 78, 101, 121, 73, 118, 47, 105, 80, 115, 71, 69, 77, 78, 75, 83, 117, 73, 69, 121, 69, 120, 116, 118, 52, 78, 101, 70, 50, 50, 100, 43, 109, 81, 114, 118, 72, 82, 65, 105, 71, 102, 122, 90, 48, 74, 70, 114, 97, 98, 65, 48, 85, 10, 87, 84, 87, 57, 56, 107, 110, 100, 116, 104, 47, 74, 115, 119, 49, 72, 75, 106, 50, 90, 76, 55, 116, 99, 117, 55, 88, 85, 73, 79, 71, 90, 88, 49, 78, 71, 70, 100, 116, 111, 109, 47, 68, 122, 77, 78, 85, 43, 77, 101, 75, 78, 104, 74, 55, 106, 105, 116, 114, 97, 108, 106, 52, 49, 69, 54, 86, 102, 56, 80, 108, 119, 85, 72, 66, 72, 10, 81, 82, 70, 88, 71, 85, 55, 65, 106, 54, 52, 71, 120, 74, 85, 84, 70, 121, 56, 98, 74, 90, 57, 49, 56, 114, 71, 79, 109, 97, 70, 118, 69, 55, 70, 66, 99, 102, 54, 73, 75, 115, 104, 80, 69, 67, 66, 86, 49, 47, 77, 85, 82, 101, 88, 103, 82, 80, 84, 113, 104, 53, 85, 121, 107, 119, 55, 43, 85, 48, 98, 54, 76, 74, 51, 47, 10, 105, 121, 75, 53, 83, 57, 107, 74, 82, 97, 84, 101, 112, 76, 105, 97, 87, 78, 48, 98, 102, 86, 75, 102, 106, 108, 108, 68, 105, 73, 71, 107, 110, 105, 98, 86, 98, 54, 51, 100, 68, 99, 89, 51, 102, 101, 48, 68, 107, 104, 118, 108, 100, 49, 57, 50, 55, 106, 121, 78, 120, 70, 49, 87, 87, 54, 76, 90, 90, 109, 54, 122, 78, 84, 102, 108, 10, 77, 114, 89, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 105, 103, 105, 67, 101, 114, 116, 32, 71, 108, 111, 98, 97, 108, 32, 82, 111, 111, 116, 32, 71, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 80, 122, 67, 67, 65, 99, 87, 103, 65, 119, 73, 66, 65, 103, 73, 81, 66, 86, 86, 87, 118, 80, 74, 101, 112, 68, 85, 49, 119, 54, 81, 80, 49, 97, 116, 70, 99, 106, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 122, 66, 104, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 10, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 87, 53, 106, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 76, 69, 120, 66, 51, 100, 51, 99, 117, 90, 71, 108, 110, 97, 87, 78, 108, 99, 110, 81, 117, 89, 50, 57, 116, 77, 83, 65, 119, 72, 103, 89, 68, 10, 86, 81, 81, 68, 69, 120, 100, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 72, 98, 71, 57, 105, 89, 87, 119, 103, 85, 109, 57, 118, 100, 67, 66, 72, 77, 122, 65, 101, 70, 119, 48, 120, 77, 122, 65, 52, 77, 68, 69, 120, 77, 106, 65, 119, 77, 68, 66, 97, 70, 119, 48, 122, 79, 68, 65, 120, 77, 84, 85, 120, 77, 106, 65, 119, 10, 77, 68, 66, 97, 77, 71, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 85, 119, 69, 119, 89, 68, 86, 81, 81, 75, 69, 119, 120, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 74, 98, 109, 77, 120, 71, 84, 65, 88, 66, 103, 78, 86, 66, 65, 115, 84, 69, 72, 100, 51, 100, 121, 53, 107, 10, 97, 87, 100, 112, 89, 50, 86, 121, 100, 67, 53, 106, 98, 50, 48, 120, 73, 68, 65, 101, 66, 103, 78, 86, 66, 65, 77, 84, 70, 48, 82, 112, 90, 50, 108, 68, 90, 88, 74, 48, 73, 69, 100, 115, 98, 50, 74, 104, 98, 67, 66, 83, 98, 50, 57, 48, 73, 69, 99, 122, 77, 72, 89, 119, 69, 65, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 10, 65, 81, 89, 70, 75, 52, 69, 69, 65, 67, 73, 68, 89, 103, 65, 69, 51, 97, 102, 90, 117, 52, 113, 52, 67, 47, 115, 76, 102, 121, 72, 83, 56, 76, 54, 43, 99, 47, 77, 122, 88, 82, 113, 56, 78, 79, 114, 101, 120, 112, 117, 56, 48, 74, 88, 50, 56, 77, 122, 81, 67, 55, 112, 104, 87, 49, 70, 71, 102, 112, 52, 116, 110, 43, 54, 79, 10, 89, 119, 119, 88, 55, 65, 100, 119, 57, 99, 43, 69, 76, 107, 67, 68, 110, 79, 103, 47, 81, 87, 48, 55, 114, 100, 79, 107, 70, 70, 107, 50, 101, 74, 48, 68, 81, 43, 52, 81, 69, 50, 120, 121, 51, 113, 54, 73, 112, 54, 70, 114, 116, 85, 80, 79, 90, 57, 119, 106, 47, 119, 77, 99, 111, 43, 73, 43, 111, 48, 73, 119, 81, 68, 65, 80, 10, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 104, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 115, 57, 116, 73, 112, 80, 109, 104, 120, 100, 105, 117, 78, 107, 72, 77, 69, 87, 78, 112, 10, 89, 105, 109, 56, 83, 56, 89, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 77, 68, 97, 65, 65, 119, 90, 81, 73, 120, 65, 75, 50, 56, 56, 109, 119, 47, 69, 107, 114, 82, 76, 84, 110, 68, 67, 103, 109, 88, 99, 47, 83, 73, 78, 111, 121, 73, 74, 55, 118, 109, 105, 73, 49, 81, 104, 97, 100, 106, 43, 90, 52, 121, 10, 51, 109, 97, 84, 68, 47, 72, 77, 115, 81, 109, 80, 51, 87, 121, 114, 43, 109, 116, 47, 111, 65, 73, 119, 79, 87, 90, 98, 119, 109, 83, 78, 117, 74, 53, 81, 51, 75, 106, 86, 83, 97, 76, 116, 120, 57, 122, 82, 83, 88, 56, 88, 65, 98, 106, 73, 104, 111, 57, 79, 106, 73, 103, 114, 113, 74, 113, 112, 105, 115, 88, 82, 65, 76, 51, 52, 10, 86, 79, 75, 97, 53, 86, 116, 56, 115, 121, 99, 88, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 68, 105, 103, 105, 67, 101, 114, 116, 32, 84, 114, 117, 115, 116, 101, 100, 32, 82, 111, 111, 116, 32, 71, 52, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 107, 68, 67, 67, 65, 51, 105, 103, 65, 119, 73, 66, 65, 103, 73, 81, 66, 90, 115, 98, 86, 53, 54, 79, 73, 84, 76, 105, 79, 81, 101, 57, 112, 51, 100, 49, 88, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 119, 70, 65, 68, 66, 105, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 87, 53, 106, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 76, 69, 120, 66, 51, 100, 51, 99, 117, 90, 71, 108, 110, 97, 87, 78, 108, 99, 110, 81, 117, 89, 50, 57, 116, 77, 83, 69, 119, 10, 72, 119, 89, 68, 86, 81, 81, 68, 69, 120, 104, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 85, 99, 110, 86, 122, 100, 71, 86, 107, 73, 70, 74, 118, 98, 51, 81, 103, 82, 122, 81, 119, 72, 104, 99, 78, 77, 84, 77, 119, 79, 68, 65, 120, 77, 84, 73, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 122, 103, 119, 77, 84, 69, 49, 10, 77, 84, 73, 119, 77, 68, 65, 119, 87, 106, 66, 105, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 86, 77, 66, 77, 71, 65, 49, 85, 69, 67, 104, 77, 77, 82, 71, 108, 110, 97, 85, 78, 108, 99, 110, 81, 103, 83, 87, 53, 106, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 76, 69, 120, 66, 51, 10, 100, 51, 99, 117, 90, 71, 108, 110, 97, 87, 78, 108, 99, 110, 81, 117, 89, 50, 57, 116, 77, 83, 69, 119, 72, 119, 89, 68, 86, 81, 81, 68, 69, 120, 104, 69, 97, 87, 100, 112, 81, 50, 86, 121, 100, 67, 66, 85, 99, 110, 86, 122, 100, 71, 86, 107, 73, 70, 74, 118, 98, 51, 81, 103, 82, 122, 81, 119, 103, 103, 73, 105, 77, 65, 48, 71, 10, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 47, 53, 112, 66, 122, 97, 78, 54, 55, 53, 70, 49, 75, 80, 68, 65, 105, 77, 71, 107, 122, 55, 77, 75, 110, 74, 83, 55, 74, 73, 84, 51, 121, 105, 116, 104, 90, 119, 117, 69, 112, 10, 112, 122, 49, 89, 113, 51, 97, 97, 122, 97, 53, 55, 71, 52, 81, 78, 120, 68, 65, 102, 56, 120, 117, 107, 79, 66, 98, 114, 86, 115, 97, 88, 98, 82, 50, 114, 115, 110, 110, 121, 121, 104, 72, 83, 53, 70, 47, 87, 66, 84, 120, 83, 68, 49, 73, 102, 120, 112, 52, 86, 112, 88, 54, 43, 110, 54, 108, 88, 70, 108, 108, 86, 99, 113, 57, 111, 10, 107, 51, 68, 67, 115, 114, 112, 49, 109, 87, 112, 122, 77, 112, 84, 82, 69, 69, 81, 81, 76, 116, 43, 67, 56, 119, 101, 69, 53, 110, 81, 55, 98, 88, 72, 105, 76, 81, 119, 98, 55, 105, 68, 86, 121, 83, 65, 100, 89, 121, 107, 116, 122, 117, 120, 101, 84, 115, 105, 84, 43, 67, 70, 104, 109, 122, 84, 114, 66, 99, 90, 101, 55, 70, 115, 97, 10, 118, 79, 118, 74, 122, 56, 50, 115, 78, 69, 66, 102, 115, 88, 112, 109, 55, 110, 102, 73, 83, 75, 104, 109, 86, 49, 101, 102, 86, 70, 105, 79, 68, 67, 117, 51, 84, 54, 99, 119, 50, 86, 98, 117, 121, 110, 116, 100, 52, 54, 51, 74, 84, 49, 55, 108, 78, 101, 99, 120, 121, 57, 113, 84, 88, 116, 121, 79, 106, 52, 68, 97, 116, 112, 71, 89, 10, 81, 74, 66, 53, 119, 51, 106, 72, 116, 114, 72, 69, 116, 87, 111, 89, 79, 65, 77, 81, 106, 100, 106, 85, 78, 54, 81, 117, 66, 88, 50, 73, 57, 89, 73, 43, 69, 74, 70, 119, 113, 49, 87, 67, 81, 84, 76, 88, 50, 119, 82, 122, 75, 109, 54, 82, 65, 88, 119, 104, 84, 78, 83, 56, 114, 104, 115, 68, 100, 86, 49, 52, 90, 116, 107, 54, 10, 77, 85, 83, 97, 77, 48, 67, 47, 67, 78, 100, 97, 83, 97, 84, 67, 53, 113, 109, 103, 90, 57, 50, 107, 74, 55, 121, 104, 84, 122, 109, 49, 69, 86, 103, 88, 57, 121, 82, 99, 82, 111, 57, 107, 57, 56, 70, 112, 105, 72, 97, 89, 100, 106, 49, 90, 88, 85, 74, 50, 104, 52, 109, 88, 97, 88, 112, 73, 56, 79, 67, 105, 69, 104, 116, 109, 10, 109, 110, 84, 75, 51, 107, 115, 101, 53, 119, 53, 106, 114, 117, 98, 85, 55, 53, 75, 83, 79, 112, 52, 57, 51, 65, 68, 107, 82, 83, 87, 74, 116, 112, 112, 69, 71, 83, 116, 43, 119, 74, 83, 48, 48, 109, 70, 116, 54, 122, 80, 90, 120, 100, 57, 76, 66, 65, 68, 77, 102, 82, 121, 86, 119, 52, 47, 51, 73, 98, 75, 121, 69, 98, 101, 55, 10, 102, 47, 76, 86, 106, 72, 65, 115, 81, 87, 67, 113, 115, 87, 77, 89, 82, 74, 85, 97, 100, 109, 74, 43, 57, 111, 67, 119, 43, 43, 104, 107, 112, 106, 80, 82, 105, 81, 102, 104, 118, 98, 102, 109, 81, 54, 81, 89, 117, 75, 90, 51, 65, 101, 69, 80, 108, 65, 119, 104, 72, 98, 74, 85, 75, 83, 87, 74, 98, 79, 85, 79, 85, 108, 70, 72, 10, 100, 76, 52, 109, 114, 76, 90, 66, 100, 100, 53, 54, 114, 70, 43, 78, 80, 56, 109, 56, 48, 48, 69, 82, 69, 108, 118, 108, 69, 70, 68, 114, 77, 99, 88, 75, 99, 104, 89, 105, 67, 100, 57, 56, 84, 72, 85, 47, 89, 43, 119, 104, 88, 56, 81, 103, 85, 87, 116, 118, 115, 97, 117, 71, 105, 48, 47, 67, 49, 107, 86, 102, 110, 83, 68, 56, 10, 111, 82, 55, 70, 119, 73, 43, 105, 115, 88, 52, 75, 74, 112, 110, 49, 53, 71, 107, 118, 109, 66, 48, 116, 57, 100, 109, 112, 115, 104, 51, 108, 71, 119, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 10, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 104, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 55, 78, 102, 106, 103, 116, 74, 120, 88, 87, 82, 77, 51, 121, 53, 110, 80, 43, 101, 54, 109, 75, 52, 99, 68, 48, 56, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 77, 66, 81, 65, 68, 10, 103, 103, 73, 66, 65, 76, 116, 104, 50, 88, 50, 112, 98, 76, 52, 88, 120, 74, 69, 98, 119, 54, 71, 105, 65, 73, 51, 106, 90, 71, 103, 80, 86, 115, 57, 51, 114, 110, 68, 53, 47, 90, 112, 75, 109, 98, 110, 74, 101, 70, 119, 77, 68, 70, 47, 107, 53, 104, 81, 112, 86, 103, 115, 50, 83, 86, 49, 69, 89, 43, 67, 116, 110, 74, 89, 89, 10, 90, 104, 115, 106, 68, 84, 49, 53, 54, 87, 49, 114, 49, 108, 84, 52, 48, 106, 122, 66, 81, 48, 67, 117, 72, 86, 68, 49, 85, 118, 121, 81, 79, 55, 117, 89, 109, 87, 108, 114, 120, 56, 71, 110, 113, 71, 105, 107, 74, 57, 121, 100, 43, 83, 101, 117, 77, 73, 87, 53, 57, 109, 100, 78, 79, 106, 54, 80, 87, 84, 107, 105, 85, 48, 84, 114, 10, 121, 70, 48, 68, 121, 117, 49, 81, 101, 110, 49, 105, 73, 81, 113, 65, 121, 72, 78, 109, 48, 97, 65, 70, 89, 70, 47, 111, 112, 98, 83, 110, 114, 54, 106, 51, 98, 84, 87, 99, 102, 70, 113, 75, 49, 113, 73, 52, 109, 102, 78, 52, 105, 47, 82, 78, 48, 105, 65, 76, 51, 103, 84, 117, 106, 74, 116, 72, 103, 88, 73, 78, 119, 66, 81, 121, 10, 55, 122, 66, 90, 76, 113, 55, 103, 99, 102, 74, 87, 53, 71, 113, 88, 98, 53, 74, 81, 98, 90, 97, 78, 97, 72, 113, 97, 115, 106, 89, 85, 101, 103, 98, 121, 74, 76, 107, 74, 69, 86, 68, 88, 67, 76, 71, 52, 105, 88, 113, 69, 73, 50, 70, 67, 75, 101, 87, 106, 122, 97, 73, 103, 81, 100, 102, 82, 110, 71, 84, 90, 54, 105, 97, 104, 10, 105, 120, 84, 88, 84, 66, 109, 121, 85, 69, 70, 120, 80, 84, 57, 78, 99, 67, 79, 71, 68, 69, 114, 99, 103, 100, 76, 77, 77, 112, 83, 69, 68, 81, 103, 74, 108, 120, 120, 80, 119, 79, 53, 114, 73, 72, 81, 119, 48, 117, 65, 53, 78, 66, 67, 70, 73, 82, 85, 66, 67, 79, 104, 86, 77, 116, 53, 120, 83, 100, 107, 111, 70, 49, 66, 78, 10, 53, 114, 53, 78, 48, 88, 87, 115, 48, 77, 114, 55, 81, 98, 104, 68, 112, 97, 114, 84, 119, 119, 86, 69, 84, 121, 119, 50, 109, 43, 76, 54, 52, 107, 87, 52, 73, 49, 78, 115, 66, 109, 57, 110, 86, 88, 57, 71, 116, 85, 119, 47, 98, 105, 104, 97, 101, 83, 98, 83, 112, 75, 104, 105, 108, 57, 73, 101, 52, 117, 49, 75, 105, 55, 119, 98, 10, 47, 85, 100, 75, 68, 100, 57, 110, 90, 110, 54, 121, 87, 48, 72, 81, 79, 43, 84, 48, 79, 47, 81, 69, 89, 43, 110, 118, 119, 108, 81, 65, 85, 97, 67, 75, 75, 115, 110, 79, 101, 77, 122, 86, 54, 111, 99, 69, 71, 76, 80, 79, 114, 48, 109, 73, 114, 47, 79, 83, 109, 98, 97, 122, 53, 109, 69, 80, 48, 111, 85, 65, 53, 49, 65, 97, 10, 53, 66, 117, 86, 110, 82, 109, 104, 117, 90, 121, 120, 109, 55, 69, 65, 72, 117, 47, 81, 68, 48, 57, 67, 98, 77, 107, 75, 118, 79, 53, 68, 43, 106, 112, 120, 112, 99, 104, 78, 74, 113, 85, 49, 47, 89, 108, 100, 118, 73, 86, 105, 72, 84, 76, 83, 111, 67, 116, 85, 55, 90, 112, 88, 119, 100, 118, 54, 69, 77, 56, 90, 116, 52, 116, 75, 10, 71, 52, 56, 66, 116, 105, 101, 86, 85, 43, 105, 50, 105, 87, 49, 98, 118, 71, 106, 85, 73, 43, 105, 76, 85, 97, 74, 87, 43, 102, 67, 109, 103, 75, 68, 87, 72, 114, 79, 56, 68, 119, 57, 84, 100, 83, 109, 113, 54, 104, 78, 51, 53, 78, 54, 77, 103, 83, 71, 116, 66, 120, 66, 72, 69, 97, 50, 72, 80, 81, 102, 82, 100, 98, 122, 80, 10, 56, 50, 90, 43, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 87, 111, 83, 105, 103, 110, 10, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 100, 106, 67, 67, 65, 49, 54, 103, 65, 119, 73, 66, 65, 103, 73, 81, 88, 109, 106, 87, 69, 88, 71, 85, 89, 49, 66, 87, 65, 71, 106, 122, 80, 115, 110, 70, 107, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 85, 70, 65, 68, 66, 86, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 68, 84, 106, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 104, 77, 82, 86, 50, 57, 84, 97, 87, 100, 117, 73, 69, 78, 66, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 75, 106, 65, 111, 66, 103, 78, 86, 66, 65, 77, 84, 73, 85, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 10, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 73, 71, 57, 109, 73, 70, 100, 118, 85, 50, 108, 110, 98, 106, 65, 101, 70, 119, 48, 119, 79, 84, 65, 52, 77, 68, 103, 119, 77, 84, 65, 119, 77, 68, 70, 97, 70, 119, 48, 122, 79, 84, 65, 52, 77, 68, 103, 119, 77, 84, 65, 119, 77, 68, 70, 97, 77, 70, 85, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 78, 79, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 69, 120, 70, 88, 98, 49, 78, 112, 90, 50, 52, 103, 81, 48, 69, 103, 84, 71, 108, 116, 97, 88, 82, 108, 90, 68, 69, 113, 77, 67, 103, 71, 65, 49, 85, 69, 65, 120, 77, 104, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 10, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 103, 98, 50, 89, 103, 86, 50, 57, 84, 97, 87, 100, 117, 77, 73, 73, 67, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 103, 56, 65, 77, 73, 73, 67, 67, 103, 75, 67, 65, 103, 69, 65, 10, 118, 99, 113, 78, 114, 76, 105, 82, 70, 86, 97, 88, 101, 50, 116, 99, 101, 115, 76, 101, 97, 57, 109, 104, 115, 77, 77, 81, 73, 47, 113, 110, 111, 98, 76, 77, 77, 102, 111, 43, 50, 97, 89, 112, 98, 120, 89, 57, 52, 71, 118, 52, 117, 69, 66, 102, 50, 122, 109, 111, 65, 72, 113, 76, 111, 69, 49, 85, 102, 99, 73, 105, 101, 80, 121, 79, 10, 67, 98, 105, 111, 104, 100, 102, 77, 108, 90, 100, 76, 100, 78, 105, 101, 102, 118, 65, 65, 53, 65, 54, 74, 114, 107, 107, 111, 82, 66, 111, 81, 109, 84, 73, 80, 74, 89, 104, 84, 112, 65, 50, 122, 68, 120, 73, 73, 70, 103, 115, 68, 99, 83, 99, 99, 102, 43, 72, 98, 48, 118, 49, 110, 97, 77, 81, 70, 88, 81, 111, 79, 88, 88, 68, 88, 10, 50, 74, 101, 103, 118, 70, 78, 66, 109, 112, 71, 78, 57, 74, 52, 50, 90, 110, 112, 43, 86, 115, 71, 81, 88, 43, 97, 120, 97, 67, 65, 50, 112, 73, 119, 107, 76, 67, 120, 72, 67, 49, 108, 50, 90, 106, 67, 49, 118, 116, 55, 116, 106, 47, 105, 100, 48, 55, 115, 66, 77, 79, 98, 121, 56, 119, 55, 103, 76, 74, 75, 65, 56, 52, 88, 53, 10, 75, 73, 113, 48, 86, 67, 54, 97, 55, 102, 100, 50, 47, 66, 86, 111, 70, 117, 116, 75, 98, 79, 115, 117, 69, 111, 47, 85, 122, 47, 52, 77, 120, 49, 119, 100, 67, 51, 52, 70, 77, 114, 53, 101, 115, 65, 107, 113, 81, 116, 88, 74, 84, 112, 67, 122, 87, 81, 50, 55, 101, 110, 55, 78, 49, 81, 104, 97, 116, 72, 47, 89, 72, 71, 107, 82, 10, 43, 83, 99, 80, 101, 119, 97, 118, 86, 73, 77, 89, 101, 43, 72, 100, 86, 72, 112, 82, 97, 71, 53, 51, 47, 77, 97, 47, 85, 107, 112, 109, 82, 113, 71, 121, 90, 120, 113, 55, 111, 48, 57, 51, 111, 76, 53, 100, 47, 47, 120, 87, 67, 48, 78, 121, 100, 53, 68, 75, 110, 118, 110, 121, 79, 102, 85, 78, 113, 102, 84, 113, 49, 43, 101, 122, 10, 69, 67, 56, 119, 81, 106, 99, 104, 122, 68, 66, 119, 121, 89, 97, 89, 68, 56, 120, 89, 84, 89, 79, 55, 102, 101, 85, 97, 112, 84, 101, 78, 116, 113, 119, 121, 108, 119, 65, 54, 89, 51, 69, 107, 72, 112, 52, 51, 120, 80, 57, 48, 49, 68, 102, 65, 52, 118, 54, 73, 82, 109, 65, 82, 51, 81, 103, 47, 85, 68, 97, 114, 117, 72, 113, 107, 10, 108, 87, 74, 113, 98, 114, 68, 75, 97, 105, 70, 97, 97, 102, 80, 122, 43, 120, 49, 119, 79, 90, 88, 122, 112, 50, 54, 109, 103, 89, 109, 104, 105, 77, 85, 55, 99, 99, 113, 106, 85, 117, 54, 68, 117, 47, 50, 103, 100, 47, 84, 107, 98, 43, 100, 67, 50, 50, 49, 75, 109, 89, 111, 48, 83, 76, 119, 88, 51, 79, 83, 65, 67, 67, 75, 50, 10, 56, 106, 72, 65, 80, 119, 81, 43, 54, 53, 56, 103, 101, 100, 97, 52, 66, 109, 82, 107, 65, 106, 72, 88, 113, 99, 49, 83, 43, 52, 82, 70, 97, 81, 107, 65, 75, 116, 120, 86, 105, 56, 81, 71, 82, 107, 118, 65, 83, 104, 48, 74, 87, 122, 107, 111, 47, 97, 109, 114, 122, 103, 68, 53, 76, 107, 104, 76, 74, 117, 89, 119, 84, 75, 86, 89, 10, 121, 114, 82, 69, 103, 107, 47, 110, 107, 82, 52, 122, 119, 55, 67, 84, 47, 120, 72, 56, 103, 100, 76, 75, 72, 51, 69, 112, 51, 88, 90, 80, 107, 105, 87, 118, 72, 89, 71, 51, 68, 121, 43, 77, 119, 119, 98, 77, 76, 121, 101, 106, 83, 117, 81, 79, 109, 98, 112, 56, 72, 107, 85, 102, 102, 54, 111, 90, 82, 90, 98, 57, 47, 68, 48, 67, 10, 65, 119, 69, 65, 65, 97, 78, 67, 77, 69, 65, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 79, 70, 109, 122, 119, 55, 82, 10, 56, 98, 78, 76, 116, 119, 89, 103, 70, 80, 54, 72, 69, 116, 88, 50, 47, 118, 115, 43, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 66, 81, 85, 65, 65, 52, 73, 67, 65, 81, 67, 111, 121, 51, 74, 65, 115, 110, 98, 66, 102, 110, 118, 56, 114, 87, 84, 106, 77, 110, 118, 77, 80, 76, 90, 100, 82, 116, 80, 49, 10, 76, 79, 74, 119, 88, 99, 103, 117, 50, 65, 90, 57, 109, 78, 69, 76, 73, 97, 67, 74, 87, 83, 81, 66, 110, 102, 109, 118, 67, 88, 48, 75, 73, 52, 73, 48, 49, 102, 120, 56, 99, 112, 109, 53, 111, 57, 100, 85, 57, 79, 112, 83, 99, 65, 55, 70, 57, 100, 89, 55, 52, 84, 111, 74, 77, 117, 89, 104, 79, 90, 79, 57, 115, 120, 88, 113, 10, 84, 50, 114, 48, 57, 89, 115, 47, 76, 51, 121, 78, 87, 67, 55, 70, 52, 84, 109, 103, 80, 115, 99, 57, 83, 110, 79, 101, 81, 72, 114, 65, 75, 50, 71, 112, 90, 56, 110, 122, 74, 76, 109, 122, 98, 86, 85, 115, 87, 104, 50, 101, 74, 88, 76, 79, 67, 54, 50, 113, 120, 49, 86, 105, 67, 55, 55, 55, 89, 55, 78, 104, 82, 67, 79, 106, 10, 121, 43, 69, 97, 68, 118, 101, 97, 66, 107, 51, 101, 49, 67, 78, 79, 73, 90, 90, 98, 79, 86, 116, 88, 72, 83, 57, 100, 67, 70, 52, 74, 101, 102, 57, 56, 108, 55, 86, 78, 103, 54, 52, 78, 49, 117, 97, 106, 101, 101, 65, 122, 48, 74, 109, 87, 65, 106, 67, 110, 80, 118, 47, 83, 111, 48, 77, 47, 66, 86, 111, 71, 54, 107, 81, 67, 10, 50, 110, 122, 52, 83, 78, 65, 122, 113, 102, 107, 72, 120, 53, 88, 104, 57, 84, 55, 49, 88, 88, 71, 54, 56, 112, 87, 112, 100, 73, 104, 104, 87, 101, 79, 47, 121, 108, 111, 84, 117, 110, 75, 48, 106, 70, 48, 50, 104, 43, 109, 109, 120, 84, 119, 84, 118, 57, 55, 81, 82, 67, 98, 117, 116, 43, 119, 117, 99, 80, 114, 88, 110, 98, 101, 115, 10, 53, 99, 86, 65, 87, 117, 98, 88, 98, 72, 115, 115, 119, 49, 97, 98, 82, 56, 48, 76, 122, 118, 111, 98, 116, 67, 72, 88, 116, 50, 97, 52, 57, 67, 85, 119, 105, 49, 119, 78, 117, 101, 112, 110, 115, 118, 82, 116, 114, 116, 87, 104, 110, 107, 47, 89, 110, 43, 107, 110, 65, 114, 65, 100, 66, 116, 97, 80, 52, 47, 116, 73, 69, 112, 57, 47, 10, 69, 97, 69, 81, 80, 107, 120, 82, 79, 112, 97, 119, 48, 82, 80, 120, 120, 57, 103, 109, 114, 106, 114, 75, 107, 99, 82, 112, 110, 100, 56, 66, 75, 87, 82, 82, 98, 50, 106, 97, 70, 79, 119, 73, 81, 90, 101, 81, 106, 100, 67, 121, 103, 80, 76, 80, 119, 106, 50, 47, 107, 87, 106, 70, 103, 71, 99, 101, 120, 71, 65, 84, 86, 100, 86, 104, 10, 109, 86, 100, 56, 117, 112, 85, 80, 89, 85, 107, 54, 121, 110, 87, 56, 121, 81, 113, 84, 80, 50, 99, 79, 69, 118, 73, 111, 52, 106, 69, 98, 119, 70, 99, 87, 51, 119, 104, 56, 71, 99, 70, 43, 68, 120, 43, 70, 72, 103, 111, 50, 102, 70, 116, 43, 74, 55, 120, 54, 118, 43, 68, 98, 57, 78, 112, 83, 118, 100, 52, 77, 86, 72, 65, 120, 10, 107, 85, 79, 86, 121, 76, 122, 119, 80, 116, 48, 74, 102, 106, 66, 107, 85, 79, 49, 47, 65, 97, 81, 122, 90, 48, 49, 111, 84, 55, 52, 86, 55, 55, 68, 50, 65, 104, 71, 105, 71, 120, 77, 108, 79, 116, 122, 67, 87, 102, 72, 106, 88, 69, 97, 55, 90, 121, 119, 67, 82, 117, 111, 101, 83, 75, 98, 109, 87, 57, 109, 49, 118, 70, 71, 105, 10, 107, 112, 98, 98, 113, 115, 89, 51, 73, 113, 98, 43, 122, 67, 66, 48, 111, 121, 50, 112, 76, 109, 118, 76, 119, 73, 73, 82, 73, 98, 87, 84, 101, 101, 53, 69, 104, 114, 55, 88, 72, 117, 81, 101, 43, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 87, 111, 83, 105, 103, 110, 32, 67, 104, 105, 110, 97, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 87, 68, 67, 67, 65, 48, 67, 103, 65, 119, 73, 66, 65, 103, 73, 81, 85, 72, 66, 114, 122, 100, 103, 84, 47, 66, 116, 79, 79, 122, 78, 121, 48, 104, 70, 73, 106, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 71, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 68, 84, 106, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 104, 77, 82, 86, 50, 57, 84, 97, 87, 100, 117, 73, 69, 78, 66, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 77, 77, 69, 107, 78, 66, 73, 79, 97, 121, 103, 43, 109, 65, 109, 117, 97, 103, 117, 101, 105, 118, 10, 103, 101, 83, 53, 112, 106, 65, 101, 70, 119, 48, 119, 79, 84, 65, 52, 77, 68, 103, 119, 77, 84, 65, 119, 77, 68, 70, 97, 70, 119, 48, 122, 79, 84, 65, 52, 77, 68, 103, 119, 77, 84, 65, 119, 77, 68, 70, 97, 77, 69, 89, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 78, 79, 77, 82, 111, 119, 71, 65, 89, 68, 10, 86, 81, 81, 75, 69, 120, 70, 88, 98, 49, 78, 112, 90, 50, 52, 103, 81, 48, 69, 103, 84, 71, 108, 116, 97, 88, 82, 108, 90, 68, 69, 98, 77, 66, 107, 71, 65, 49, 85, 69, 65, 119, 119, 83, 81, 48, 69, 103, 53, 114, 75, 68, 54, 89, 67, 97, 53, 113, 67, 53, 54, 75, 43, 66, 53, 76, 109, 109, 77, 73, 73, 67, 73, 106, 65, 78, 10, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 103, 56, 65, 77, 73, 73, 67, 67, 103, 75, 67, 65, 103, 69, 65, 48, 69, 107, 104, 72, 105, 88, 56, 104, 56, 69, 113, 119, 113, 122, 98, 100, 111, 89, 71, 84, 117, 102, 81, 100, 68, 84, 99, 55, 87, 85, 49, 47, 70, 68, 87, 105, 68, 43, 107, 10, 56, 72, 47, 114, 68, 49, 57, 53, 76, 52, 109, 120, 47, 98, 120, 106, 87, 68, 101, 84, 109, 122, 106, 52, 116, 49, 117, 112, 43, 116, 104, 120, 120, 55, 83, 56, 103, 74, 101, 78, 98, 69, 118, 120, 85, 78, 85, 113, 75, 97, 113, 111, 71, 88, 113, 87, 53, 112, 87, 79, 100, 79, 50, 88, 67, 108, 100, 49, 57, 65, 88, 98, 98, 81, 115, 53, 10, 117, 81, 70, 47, 113, 118, 98, 87, 50, 109, 122, 109, 66, 101, 67, 107, 84, 86, 76, 56, 50, 57, 66, 48, 116, 120, 71, 77, 101, 52, 49, 80, 47, 52, 101, 68, 114, 118, 56, 70, 65, 120, 78, 88, 85, 68, 102, 43, 106, 74, 90, 83, 69, 69, 120, 102, 118, 53, 82, 120, 97, 100, 109, 87, 80, 103, 120, 68, 84, 55, 52, 119, 119, 74, 56, 53, 10, 100, 69, 56, 71, 82, 86, 50, 106, 49, 108, 89, 53, 97, 65, 102, 77, 104, 48, 57, 81, 100, 53, 78, 120, 50, 85, 81, 73, 115, 89, 111, 48, 54, 89, 109, 115, 50, 53, 116, 79, 52, 100, 110, 107, 85, 107, 87, 77, 76, 104, 81, 102, 107, 87, 115, 90, 72, 87, 103, 112, 76, 70, 98, 69, 52, 104, 52, 84, 86, 50, 84, 119, 89, 101, 79, 53, 10, 69, 100, 43, 119, 52, 86, 101, 103, 71, 54, 51, 88, 88, 57, 71, 118, 50, 121, 115, 116, 80, 57, 66, 111, 106, 103, 47, 113, 110, 119, 43, 76, 78, 86, 103, 98, 69, 120, 122, 48, 51, 106, 87, 104, 67, 108, 51, 87, 54, 116, 56, 83, 98, 56, 68, 55, 97, 81, 100, 71, 99, 116, 121, 66, 57, 103, 81, 106, 70, 43, 66, 78, 100, 101, 70, 121, 10, 98, 55, 65, 111, 54, 53, 118, 104, 52, 89, 79, 104, 110, 48, 112, 100, 114, 56, 121, 98, 43, 103, 73, 103, 116, 104, 104, 105, 100, 53, 69, 55, 111, 57, 86, 108, 114, 100, 120, 56, 107, 72, 99, 99, 82, 69, 71, 107, 83, 111, 118, 114, 108, 88, 76, 112, 57, 103, 108, 107, 51, 75, 103, 116, 110, 51, 82, 52, 54, 77, 71, 105, 67, 87, 79, 99, 10, 55, 54, 68, 98, 84, 53, 50, 86, 113, 121, 66, 80, 116, 55, 68, 51, 104, 49, 121, 109, 111, 79, 81, 51, 79, 77, 100, 99, 52, 122, 85, 80, 76, 75, 50, 106, 103, 75, 76, 115, 76, 108, 51, 65, 122, 43, 50, 76, 66, 99, 76, 109, 99, 50, 55, 50, 105, 100, 88, 49, 48, 107, 97, 79, 54, 109, 49, 106, 71, 120, 54, 75, 121, 88, 50, 109, 10, 43, 74, 122, 114, 53, 100, 86, 106, 104, 85, 49, 122, 90, 109, 107, 82, 47, 115, 103, 79, 57, 77, 72, 72, 90, 107, 108, 84, 102, 117, 81, 90, 97, 47, 72, 112, 101, 108, 109, 106, 98, 88, 55, 70, 70, 43, 89, 110, 120, 117, 56, 98, 50, 50, 47, 56, 68, 85, 48, 71, 65, 98, 81, 79, 88, 68, 66, 71, 86, 87, 67, 118, 79, 71, 85, 54, 10, 121, 107, 101, 54, 114, 67, 122, 77, 82, 104, 43, 121, 82, 112, 89, 47, 56, 43, 48, 109, 66, 101, 53, 51, 111, 87, 112, 114, 102, 105, 49, 116, 87, 70, 120, 75, 49, 73, 53, 110, 117, 80, 72, 97, 49, 85, 97, 75, 74, 47, 107, 82, 56, 115, 108, 67, 47, 107, 55, 101, 51, 120, 57, 99, 120, 75, 83, 71, 104, 120, 89, 122, 111, 97, 99, 88, 10, 71, 75, 85, 78, 53, 65, 88, 108, 75, 56, 73, 114, 67, 54, 75, 86, 107, 76, 110, 57, 89, 68, 120, 79, 105, 84, 55, 110, 110, 79, 52, 102, 117, 119, 69, 67, 65, 119, 69, 65, 65, 97, 78, 67, 77, 69, 65, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 10, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 79, 66, 78, 118, 57, 121, 98, 81, 86, 48, 84, 54, 71, 84, 119, 112, 43, 107, 86, 112, 79, 71, 66, 119, 98, 111, 120, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 10, 65, 52, 73, 67, 65, 81, 66, 113, 105, 110, 65, 52, 87, 98, 98, 97, 105, 120, 106, 73, 118, 105, 114, 84, 116, 104, 110, 86, 90, 105, 108, 54, 88, 99, 49, 98, 76, 51, 77, 99, 74, 107, 54, 106, 102, 87, 43, 114, 116, 121, 108, 78, 112, 117, 109, 108, 69, 89, 79, 110, 79, 88, 79, 118, 69, 69, 83, 83, 53, 105, 86, 100, 84, 50, 72, 54, 10, 121, 65, 97, 43, 84, 107, 118, 118, 47, 118, 77, 120, 47, 115, 90, 56, 99, 65, 112, 66, 87, 78, 114, 111, 109, 85, 117, 87, 121, 88, 105, 56, 109, 72, 119, 67, 75, 101, 48, 74, 103, 79, 89, 75, 79, 111, 73, 67, 75, 117, 76, 74, 76, 56, 104, 87, 71, 83, 98, 117, 101, 66, 119, 106, 47, 102, 101, 84, 90, 85, 55, 110, 56, 53, 105, 89, 10, 114, 56, 51, 100, 50, 90, 53, 65, 105, 68, 69, 111, 79, 113, 115, 117, 67, 55, 67, 115, 68, 67, 84, 54, 101, 105, 97, 89, 56, 120, 74, 104, 69, 80, 82, 100, 70, 47, 100, 43, 52, 110, 105, 88, 86, 79, 75, 77, 54, 67, 109, 54, 106, 66, 65, 121, 118, 100, 48, 122, 97, 122, 105, 71, 102, 106, 107, 57, 68, 103, 78, 121, 112, 49, 49, 53, 10, 106, 48, 87, 75, 87, 97, 53, 98, 73, 87, 52, 120, 82, 116, 86, 90, 106, 99, 56, 86, 88, 57, 48, 120, 74, 99, 47, 98, 89, 78, 97, 66, 82, 72, 73, 112, 65, 108, 102, 50, 108, 116, 84, 87, 47, 43, 111, 112, 50, 122, 110, 70, 117, 67, 121, 75, 71, 111, 51, 79, 121, 43, 100, 67, 77, 89, 89, 70, 97, 65, 54, 101, 70, 78, 48, 65, 10, 107, 76, 112, 112, 82, 81, 106, 98, 98, 112, 67, 66, 104, 113, 99, 113, 66, 84, 47, 109, 104, 68, 110, 52, 116, 47, 108, 88, 88, 48, 121, 107, 101, 86, 111, 81, 68, 70, 55, 86, 97, 47, 56, 49, 88, 119, 86, 82, 72, 109, 121, 106, 100, 97, 110, 80, 85, 73, 80, 84, 102, 80, 82, 109, 57, 52, 75, 78, 80, 81, 120, 57, 54, 78, 57, 55, 10, 113, 65, 52, 98, 76, 74, 121, 117, 81, 72, 67, 72, 50, 117, 50, 110, 70, 111, 74, 97, 118, 106, 86, 115, 73, 69, 52, 105, 89, 100, 109, 56, 85, 88, 114, 78, 101, 109, 72, 99, 83, 120, 72, 53, 47, 109, 99, 48, 122, 121, 52, 69, 90, 109, 70, 99, 86, 53, 99, 106, 106, 80, 79, 71, 71, 48, 106, 102, 75, 113, 43, 110, 119, 102, 47, 89, 10, 106, 106, 52, 68, 117, 57, 103, 113, 115, 80, 111, 85, 74, 98, 74, 82, 97, 52, 90, 68, 104, 83, 52, 72, 73, 120, 97, 65, 106, 85, 122, 55, 116, 71, 77, 55, 122, 77, 78, 48, 55, 82, 117, 106, 72, 118, 52, 49, 68, 49, 57, 56, 72, 82, 97, 71, 57, 81, 55, 68, 108, 102, 69, 118, 114, 49, 48, 108, 79, 49, 72, 109, 49, 51, 90, 66, 10, 79, 78, 70, 76, 65, 122, 107, 111, 112, 82, 54, 82, 99, 116, 82, 57, 113, 53, 99, 122, 120, 78, 77, 43, 52, 71, 109, 50, 75, 72, 109, 103, 67, 89, 48, 99, 48, 102, 57, 66, 99, 107, 103, 71, 47, 74, 111, 117, 53, 121, 68, 53, 109, 54, 76, 101, 105, 101, 50, 117, 80, 65, 109, 118, 121, 108, 101, 122, 107, 111, 108, 119, 81, 79, 81, 118, 10, 84, 56, 74, 119, 103, 48, 68, 88, 74, 67, 120, 114, 53, 119, 107, 102, 48, 57, 88, 72, 119, 81, 106, 48, 50, 119, 52, 55, 72, 65, 99, 76, 81, 120, 71, 69, 73, 89, 98, 112, 103, 78, 82, 49, 50, 75, 118, 120, 65, 109, 76, 66, 115, 88, 53, 86, 89, 99, 56, 84, 49, 121, 97, 119, 49, 53, 122, 76, 75, 89, 115, 52, 83, 103, 115, 79, 10, 107, 73, 50, 54, 111, 81, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 79, 77, 79, 68, 79, 32, 82, 83, 65, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 50, 68, 67, 67, 65, 56, 67, 103, 65, 119, 73, 66, 65, 103, 73, 81, 84, 75, 114, 53, 121, 116, 116, 106, 98, 43, 65, 102, 57, 48, 55, 89, 87, 119, 79, 71, 110, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 119, 70, 65, 68, 67, 66, 104, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 82, 48, 73, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 103, 84, 69, 107, 100, 121, 90, 87, 70, 48, 90, 88, 73, 103, 84, 87, 70, 117, 89, 50, 104, 108, 99, 51, 82, 108, 99, 106, 69, 81, 77, 65, 52, 71, 65, 49, 85, 69, 66, 120, 77, 72, 85, 50, 70, 115, 90, 109, 57, 121, 90, 68, 69, 97, 77, 66, 103, 71, 10, 65, 49, 85, 69, 67, 104, 77, 82, 81, 48, 57, 78, 84, 48, 82, 80, 73, 69, 78, 66, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 75, 122, 65, 112, 66, 103, 78, 86, 66, 65, 77, 84, 73, 107, 78, 80, 84, 85, 57, 69, 84, 121, 66, 83, 85, 48, 69, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 10, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 72, 104, 99, 78, 77, 84, 65, 119, 77, 84, 69, 53, 77, 68, 65, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 122, 103, 119, 77, 84, 69, 52, 77, 106, 77, 49, 79, 84, 85, 53, 87, 106, 67, 66, 104, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 10, 82, 48, 73, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 103, 84, 69, 107, 100, 121, 90, 87, 70, 48, 90, 88, 73, 103, 84, 87, 70, 117, 89, 50, 104, 108, 99, 51, 82, 108, 99, 106, 69, 81, 77, 65, 52, 71, 65, 49, 85, 69, 66, 120, 77, 72, 85, 50, 70, 115, 90, 109, 57, 121, 90, 68, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 10, 67, 104, 77, 82, 81, 48, 57, 78, 84, 48, 82, 80, 73, 69, 78, 66, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 75, 122, 65, 112, 66, 103, 78, 86, 66, 65, 77, 84, 73, 107, 78, 80, 84, 85, 57, 69, 84, 121, 66, 83, 85, 48, 69, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 10, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 82, 54, 70, 83, 83, 48, 103, 112, 87, 115, 97, 119, 78, 74, 78, 51, 70, 122, 48, 82, 110, 10, 100, 74, 107, 114, 78, 54, 78, 57, 73, 51, 65, 65, 99, 98, 120, 84, 51, 56, 84, 54, 75, 104, 75, 80, 83, 51, 56, 81, 86, 114, 50, 102, 99, 72, 75, 51, 89, 88, 47, 74, 83, 119, 56, 88, 112, 122, 51, 106, 115, 65, 82, 104, 55, 118, 56, 82, 108, 56, 102, 48, 104, 106, 52, 75, 43, 106, 53, 99, 43, 90, 80, 109, 78, 72, 114, 90, 10, 70, 71, 118, 110, 110, 76, 79, 70, 111, 73, 74, 54, 100, 113, 57, 120, 107, 78, 102, 115, 47, 81, 51, 54, 110, 71, 122, 54, 51, 55, 67, 67, 57, 66, 82, 43, 43, 98, 55, 69, 112, 105, 57, 80, 102, 53, 108, 47, 116, 102, 120, 110, 81, 51, 75, 57, 68, 65, 68, 87, 105, 101, 116, 114, 76, 78, 80, 116, 106, 53, 103, 99, 70, 75, 116, 43, 10, 53, 101, 78, 117, 47, 78, 105, 111, 53, 74, 73, 107, 50, 107, 78, 114, 89, 114, 104, 86, 47, 101, 114, 66, 118, 71, 121, 50, 105, 47, 77, 79, 106, 90, 114, 107, 109, 50, 120, 112, 109, 102, 104, 52, 83, 68, 66, 70, 49, 97, 51, 104, 68, 84, 120, 70, 89, 80, 119, 121, 108, 108, 69, 110, 118, 71, 102, 68, 121, 105, 54, 50, 97, 43, 112, 71, 10, 120, 56, 99, 103, 111, 76, 69, 102, 90, 100, 53, 73, 67, 76, 113, 107, 84, 113, 110, 121, 103, 48, 89, 51, 104, 79, 118, 111, 122, 73, 70, 73, 81, 50, 100, 79, 99, 105, 113, 98, 88, 76, 49, 77, 71, 121, 105, 75, 88, 67, 74, 55, 116, 75, 117, 89, 50, 101, 55, 103, 85, 89, 80, 68, 67, 85, 90, 79, 98, 84, 54, 90, 43, 112, 85, 88, 10, 50, 110, 119, 122, 86, 48, 69, 56, 106, 86, 72, 116, 67, 55, 90, 99, 114, 121, 120, 106, 71, 116, 57, 88, 121, 68, 43, 56, 54, 86, 51, 69, 109, 54, 57, 70, 109, 101, 75, 106, 87, 105, 83, 48, 117, 113, 108, 87, 80, 99, 57, 118, 113, 118, 57, 74, 87, 76, 55, 119, 113, 80, 47, 48, 117, 75, 51, 112, 78, 47, 117, 54, 117, 80, 81, 76, 10, 79, 118, 110, 111, 81, 48, 73, 101, 105, 100, 105, 69, 121, 120, 80, 120, 50, 98, 118, 104, 105, 87, 67, 52, 106, 67, 104, 87, 114, 66, 81, 100, 110, 65, 114, 110, 99, 101, 118, 80, 68, 116, 48, 57, 113, 90, 97, 104, 83, 76, 48, 56, 57, 54, 43, 49, 68, 83, 74, 77, 119, 66, 71, 66, 55, 70, 89, 55, 57, 116, 79, 105, 52, 108, 117, 51, 10, 115, 103, 81, 105, 85, 112, 87, 65, 107, 50, 110, 111, 106, 107, 120, 108, 56, 90, 69, 68, 76, 88, 66, 48, 65, 117, 113, 76, 90, 120, 85, 112, 97, 86, 73, 67, 117, 57, 102, 102, 85, 71, 112, 86, 82, 114, 43, 103, 111, 121, 104, 104, 102, 51, 68, 81, 119, 54, 75, 113, 76, 67, 71, 113, 82, 56, 52, 111, 110, 65, 90, 70, 100, 114, 43, 67, 10, 71, 67, 101, 48, 49, 97, 54, 48, 121, 49, 68, 109, 97, 47, 82, 77, 104, 110, 69, 119, 54, 97, 98, 102, 70, 111, 98, 103, 50, 80, 57, 65, 51, 102, 118, 81, 81, 111, 104, 47, 111, 122, 77, 54, 76, 108, 119, 101, 81, 82, 71, 66, 89, 56, 52, 89, 99, 87, 115, 114, 55, 75, 97, 75, 116, 122, 70, 99, 79, 109, 112, 72, 52, 77, 78, 53, 10, 87, 100, 89, 103, 71, 113, 47, 121, 97, 112, 105, 113, 99, 114, 120, 88, 83, 116, 74, 76, 110, 98, 115, 81, 47, 76, 66, 77, 81, 101, 88, 116, 72, 84, 49, 101, 75, 74, 50, 99, 122, 76, 43, 122, 85, 100, 113, 110, 82, 43, 87, 69, 85, 119, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 10, 70, 103, 81, 85, 117, 54, 57, 43, 65, 106, 51, 54, 112, 118, 69, 56, 104, 73, 54, 116, 55, 106, 105, 89, 55, 78, 107, 121, 77, 116, 81, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 10, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 77, 66, 81, 65, 68, 103, 103, 73, 66, 65, 65, 114, 120, 49, 85, 97, 69, 116, 54, 53, 82, 117, 50, 121, 121, 84, 85, 69, 85, 65, 74, 78, 77, 110, 77, 118, 108, 119, 70, 84, 80, 111, 67, 87, 79, 65, 118, 110, 57, 115, 75, 73, 78, 57, 83, 67, 89, 80, 66, 77, 116, 10, 114, 70, 97, 105, 115, 78, 90, 43, 69, 90, 76, 112, 76, 114, 113, 101, 76, 112, 112, 121, 115, 98, 48, 90, 82, 71, 120, 104, 78, 97, 75, 97, 116, 66, 89, 83, 97, 86, 113, 77, 52, 100, 99, 43, 112, 66, 114, 111, 76, 119, 80, 48, 114, 109, 69, 100, 69, 66, 115, 113, 112, 73, 116, 54, 120, 102, 52, 70, 112, 117, 72, 65, 49, 115, 106, 43, 10, 110, 113, 54, 80, 75, 55, 111, 57, 109, 102, 106, 89, 99, 119, 108, 89, 82, 109, 54, 109, 110, 80, 84, 88, 74, 57, 79, 86, 50, 106, 101, 68, 99, 104, 122, 84, 99, 43, 67, 105, 82, 53, 107, 68, 79, 70, 51, 86, 83, 88, 107, 65, 75, 82, 122, 72, 55, 74, 115, 103, 72, 65, 99, 107, 97, 86, 100, 52, 115, 106, 110, 56, 79, 111, 83, 103, 10, 116, 90, 120, 56, 106, 98, 56, 117, 107, 50, 73, 110, 116, 122, 110, 97, 70, 120, 105, 117, 118, 84, 119, 74, 97, 80, 43, 69, 109, 122, 122, 86, 49, 103, 115, 68, 52, 49, 101, 101, 70, 80, 102, 82, 54, 48, 47, 73, 118, 89, 99, 106, 116, 55, 90, 74, 81, 51, 109, 70, 88, 76, 114, 114, 107, 103, 117, 104, 120, 117, 104, 111, 113, 69, 119, 87, 10, 115, 82, 113, 90, 67, 117, 104, 84, 76, 74, 75, 55, 111, 81, 107, 89, 100, 81, 120, 108, 113, 72, 118, 76, 73, 55, 99, 97, 119, 105, 105, 70, 119, 120, 118, 47, 48, 67, 116, 105, 55, 54, 82, 55, 67, 90, 71, 89, 90, 52, 119, 85, 65, 99, 49, 111, 66, 109, 112, 106, 73, 88, 85, 68, 103, 73, 105, 75, 98, 111, 72, 71, 104, 102, 75, 112, 10, 112, 67, 51, 110, 57, 75, 85, 107, 69, 69, 101, 68, 121, 115, 51, 48, 106, 88, 108, 89, 115, 81, 97, 98, 53, 120, 111, 113, 50, 90, 48, 66, 49, 53, 82, 57, 55, 81, 78, 75, 121, 118, 68, 98, 54, 75, 107, 66, 80, 118, 86, 87, 109, 99, 107, 101, 106, 107, 107, 57, 117, 43, 85, 74, 117, 101, 66, 80, 83, 90, 73, 57, 70, 111, 74, 65, 10, 122, 77, 120, 90, 120, 117, 89, 54, 55, 82, 73, 117, 97, 84, 120, 115, 108, 98, 72, 57, 113, 104, 49, 55, 102, 52, 97, 43, 72, 103, 52, 121, 82, 118, 118, 55, 69, 52, 57, 49, 102, 48, 121, 76, 83, 48, 90, 106, 47, 103, 65, 48, 81, 72, 68, 66, 119, 55, 109, 104, 51, 97, 90, 119, 52, 103, 83, 122, 81, 98, 122, 112, 103, 74, 72, 113, 10, 90, 74, 120, 54, 52, 83, 73, 68, 113, 90, 120, 117, 98, 119, 53, 108, 84, 50, 121, 72, 104, 49, 55, 122, 98, 113, 68, 53, 100, 97, 87, 98, 81, 79, 104, 84, 115, 105, 101, 100, 83, 114, 110, 65, 100, 121, 71, 78, 47, 52, 102, 121, 51, 114, 121, 77, 55, 120, 102, 102, 116, 48, 107, 76, 48, 102, 74, 117, 77, 65, 115, 97, 68, 107, 53, 50, 10, 55, 82, 72, 56, 57, 101, 108, 87, 115, 110, 50, 47, 120, 50, 48, 75, 107, 52, 121, 108, 48, 77, 67, 50, 72, 98, 52, 54, 84, 112, 83, 105, 49, 50, 53, 115, 67, 56, 75, 75, 102, 80, 111, 103, 56, 56, 84, 107, 53, 99, 48, 78, 113, 77, 117, 82, 107, 114, 70, 56, 104, 101, 121, 49, 70, 71, 108, 109, 68, 111, 76, 110, 122, 99, 55, 73, 10, 76, 97, 90, 82, 102, 121, 72, 66, 78, 86, 79, 70, 66, 107, 112, 100, 110, 54, 50, 55, 71, 49, 57, 48, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 85, 83, 69, 82, 84, 114, 117, 115, 116, 32, 82, 83, 65, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 51, 106, 67, 67, 65, 56, 97, 103, 65, 119, 73, 66, 65, 103, 73, 81, 65, 102, 49, 116, 77, 80, 121, 106, 121, 108, 71, 111, 71, 55, 120, 107, 68, 106, 85, 68, 76, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 119, 70, 65, 68, 67, 66, 105, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 86, 86, 77, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 103, 84, 67, 107, 53, 108, 100, 121, 66, 75, 90, 88, 74, 122, 90, 88, 107, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 99, 84, 67, 48, 112, 108, 99, 110, 78, 108, 101, 83, 66, 68, 97, 88, 82, 53, 77, 82, 52, 119, 72, 65, 89, 68, 86, 81, 81, 75, 10, 69, 120, 86, 85, 97, 71, 85, 103, 86, 86, 78, 70, 85, 108, 82, 83, 86, 86, 78, 85, 73, 69, 53, 108, 100, 72, 100, 118, 99, 109, 115, 120, 76, 106, 65, 115, 66, 103, 78, 86, 66, 65, 77, 84, 74, 86, 86, 84, 82, 86, 74, 85, 99, 110, 86, 122, 100, 67, 66, 83, 85, 48, 69, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 10, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 72, 104, 99, 78, 77, 84, 65, 119, 77, 106, 65, 120, 77, 68, 65, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 122, 103, 119, 77, 84, 69, 52, 77, 106, 77, 49, 79, 84, 85, 53, 87, 106, 67, 66, 105, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 86, 86, 77, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 103, 84, 67, 107, 53, 108, 100, 121, 66, 75, 90, 88, 74, 122, 90, 88, 107, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 99, 84, 67, 48, 112, 108, 99, 110, 78, 108, 101, 83, 66, 68, 97, 88, 82, 53, 77, 82, 52, 119, 72, 65, 89, 68, 86, 81, 81, 75, 10, 69, 120, 86, 85, 97, 71, 85, 103, 86, 86, 78, 70, 85, 108, 82, 83, 86, 86, 78, 85, 73, 69, 53, 108, 100, 72, 100, 118, 99, 109, 115, 120, 76, 106, 65, 115, 66, 103, 78, 86, 66, 65, 77, 84, 74, 86, 86, 84, 82, 86, 74, 85, 99, 110, 86, 122, 100, 67, 66, 83, 85, 48, 69, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 10, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 65, 69, 109, 85, 88, 78, 103, 55, 68, 50, 119, 105, 122, 10, 48, 75, 120, 88, 68, 88, 98, 116, 122, 83, 102, 84, 84, 75, 49, 81, 103, 50, 72, 105, 113, 105, 66, 78, 67, 83, 49, 107, 67, 100, 122, 79, 105, 90, 47, 77, 80, 97, 110, 115, 57, 115, 47, 66, 51, 80, 72, 84, 115, 100, 90, 55, 78, 121, 103, 82, 75, 48, 102, 97, 79, 99, 97, 56, 79, 104, 109, 48, 88, 54, 97, 57, 102, 90, 50, 106, 10, 89, 48, 75, 50, 100, 118, 75, 112, 79, 121, 117, 82, 43, 79, 74, 118, 48, 79, 119, 87, 73, 74, 65, 74, 80, 117, 76, 111, 100, 77, 107, 89, 116, 74, 72, 85, 89, 109, 84, 98, 102, 54, 77, 71, 56, 89, 103, 89, 97, 112, 65, 105, 80, 76, 122, 43, 69, 47, 67, 72, 70, 72, 118, 50, 53, 66, 43, 79, 49, 79, 82, 82, 120, 104, 70, 110, 10, 82, 103, 104, 82, 121, 52, 89, 85, 86, 68, 43, 56, 77, 47, 53, 43, 98, 74, 122, 47, 70, 112, 48, 89, 118, 86, 71, 79, 78, 97, 97, 110, 90, 115, 104, 121, 90, 57, 115, 104, 90, 114, 72, 85, 109, 51, 103, 68, 119, 70, 65, 54, 54, 77, 122, 119, 51, 76, 121, 101, 84, 80, 54, 118, 66, 90, 89, 49, 72, 49, 100, 97, 116, 47, 47, 79, 10, 43, 84, 50, 51, 76, 76, 98, 50, 86, 78, 51, 73, 53, 120, 73, 54, 84, 97, 53, 77, 105, 114, 100, 99, 109, 114, 83, 51, 73, 68, 51, 75, 102, 121, 73, 48, 114, 110, 52, 55, 97, 71, 89, 66, 82, 79, 99, 66, 84, 107, 90, 84, 109, 122, 78, 103, 57, 53, 83, 43, 85, 122, 101, 81, 99, 48, 80, 122, 77, 115, 78, 84, 55, 57, 117, 113, 10, 47, 110, 82, 79, 97, 99, 100, 114, 106, 71, 67, 84, 51, 115, 84, 72, 68, 78, 47, 104, 77, 113, 55, 77, 107, 122, 116, 82, 101, 74, 86, 110, 105, 43, 52, 57, 86, 118, 52, 77, 48, 71, 107, 80, 71, 119, 47, 122, 74, 83, 90, 114, 77, 50, 51, 51, 98, 107, 102, 54, 99, 48, 80, 108, 102, 103, 54, 108, 90, 114, 69, 112, 102, 68, 75, 69, 10, 89, 49, 87, 74, 120, 65, 51, 66, 107, 49, 81, 119, 71, 82, 79, 115, 48, 51, 48, 51, 112, 43, 116, 100, 79, 109, 119, 49, 88, 78, 116, 66, 49, 120, 76, 97, 113, 85, 107, 76, 51, 57, 105, 65, 105, 103, 109, 84, 89, 111, 54, 49, 90, 115, 56, 108, 105, 77, 50, 69, 117, 76, 69, 47, 112, 68, 107, 80, 50, 81, 75, 101, 54, 120, 74, 77, 10, 108, 88, 122, 122, 97, 119, 87, 112, 88, 104, 97, 68, 122, 76, 104, 110, 52, 117, 103, 84, 110, 99, 120, 98, 103, 116, 78, 77, 115, 43, 49, 98, 47, 57, 55, 108, 99, 54, 119, 106, 79, 121, 48, 65, 118, 122, 86, 86, 100, 65, 108, 74, 50, 69, 108, 89, 71, 110, 43, 83, 78, 117, 90, 82, 107, 103, 55, 122, 74, 110, 48, 99, 84, 82, 101, 56, 10, 121, 101, 120, 68, 74, 116, 67, 47, 81, 86, 57, 65, 113, 85, 82, 69, 57, 74, 110, 110, 86, 52, 101, 101, 85, 66, 57, 88, 86, 75, 103, 43, 47, 88, 82, 106, 76, 55, 70, 81, 90, 81, 110, 109, 87, 69, 73, 117, 81, 120, 112, 77, 116, 80, 65, 108, 82, 49, 110, 54, 66, 66, 54, 84, 49, 67, 90, 71, 83, 108, 67, 66, 115, 116, 54, 43, 10, 101, 76, 102, 56, 90, 120, 88, 104, 121, 86, 101, 69, 72, 103, 57, 106, 49, 117, 108, 105, 117, 116, 90, 102, 86, 83, 55, 113, 88, 77, 89, 111, 67, 65, 81, 108, 79, 98, 103, 79, 75, 54, 110, 121, 84, 74, 99, 99, 66, 122, 56, 78, 85, 118, 88, 116, 55, 121, 43, 67, 68, 119, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 100, 10, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 85, 51, 109, 47, 87, 113, 111, 114, 83, 115, 57, 85, 103, 79, 72, 89, 109, 56, 67, 100, 56, 114, 73, 68, 90, 115, 115, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 10, 77, 65, 77, 66, 65, 102, 56, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 77, 66, 81, 65, 68, 103, 103, 73, 66, 65, 70, 122, 85, 102, 65, 51, 80, 57, 119, 70, 57, 81, 90, 108, 108, 68, 72, 80, 70, 85, 112, 47, 76, 43, 77, 43, 90, 66, 110, 56, 98, 50, 107, 77, 86, 110, 53, 52, 67, 86, 86, 101, 87, 10, 70, 80, 70, 83, 80, 67, 101, 72, 108, 67, 106, 116, 72, 122, 111, 66, 78, 54, 74, 50, 47, 70, 78, 81, 119, 73, 83, 98, 120, 109, 116, 79, 117, 111, 119, 104, 84, 54, 75, 79, 86, 87, 75, 82, 56, 50, 107, 86, 50, 76, 121, 73, 52, 56, 83, 113, 67, 47, 51, 118, 113, 79, 108, 76, 86, 83, 111, 71, 73, 71, 49, 86, 101, 67, 107, 90, 10, 55, 108, 56, 119, 88, 69, 115, 107, 69, 86, 88, 47, 74, 74, 112, 117, 88, 105, 111, 114, 55, 103, 116, 78, 110, 51, 47, 51, 65, 84, 105, 85, 70, 74, 86, 68, 66, 119, 110, 55, 89, 75, 110, 117, 72, 75, 115, 83, 106, 75, 67, 97, 88, 113, 101, 89, 97, 108, 108, 116, 105, 122, 56, 73, 43, 56, 106, 82, 82, 97, 56, 89, 70, 87, 83, 81, 10, 69, 103, 57, 122, 75, 67, 55, 70, 52, 105, 82, 79, 47, 70, 106, 115, 56, 80, 82, 70, 47, 105, 75, 122, 54, 121, 43, 79, 48, 116, 108, 70, 89, 81, 88, 66, 108, 50, 43, 111, 100, 110, 75, 80, 105, 52, 119, 50, 114, 55, 56, 78, 66, 99, 53, 120, 106, 101, 97, 109, 98, 120, 57, 115, 112, 110, 70, 105, 120, 100, 106, 81, 103, 51, 73, 77, 10, 56, 87, 99, 82, 105, 81, 121, 99, 69, 48, 120, 121, 78, 78, 43, 56, 49, 88, 72, 102, 113, 110, 72, 100, 52, 98, 108, 115, 106, 68, 119, 83, 88, 87, 88, 97, 118, 86, 99, 83, 116, 107, 78, 114, 47, 43, 88, 101, 84, 87, 89, 82, 85, 99, 43, 90, 114, 117, 119, 88, 116, 117, 104, 120, 107, 89, 122, 101, 83, 102, 55, 100, 78, 88, 71, 105, 10, 70, 83, 101, 85, 72, 77, 57, 104, 52, 121, 97, 55, 98, 54, 78, 110, 74, 83, 70, 100, 53, 116, 48, 100, 67, 121, 53, 111, 71, 122, 117, 67, 114, 43, 121, 68, 90, 52, 88, 85, 109, 70, 70, 48, 115, 98, 109, 90, 103, 73, 110, 47, 102, 51, 103, 90, 88, 72, 108, 75, 89, 67, 54, 83, 81, 75, 53, 77, 78, 121, 111, 115, 121, 99, 100, 105, 10, 121, 65, 53, 100, 57, 122, 90, 98, 121, 117, 65, 108, 74, 81, 71, 48, 51, 82, 111, 72, 110, 72, 99, 65, 80, 57, 68, 99, 49, 101, 119, 57, 49, 80, 113, 55, 80, 56, 121, 70, 49, 109, 57, 47, 113, 83, 51, 102, 117, 81, 76, 51, 57, 90, 101, 97, 116, 84, 88, 97, 119, 50, 101, 119, 104, 48, 113, 112, 75, 74, 52, 106, 106, 118, 57, 99, 10, 74, 50, 118, 104, 115, 69, 47, 122, 66, 43, 52, 65, 76, 116, 82, 90, 104, 56, 116, 83, 81, 90, 88, 113, 57, 69, 102, 88, 55, 109, 82, 66, 86, 88, 121, 78, 87, 81, 75, 86, 51, 87, 75, 100, 119, 114, 110, 117, 87, 105, 104, 48, 104, 75, 87, 98, 116, 53, 68, 72, 68, 65, 102, 102, 57, 89, 107, 50, 100, 68, 76, 87, 75, 77, 71, 119, 10, 115, 65, 118, 103, 110, 69, 122, 68, 72, 78, 98, 56, 52, 50, 109, 49, 82, 48, 97, 66, 76, 54, 75, 67, 113, 57, 78, 106, 82, 72, 68, 69, 106, 102, 56, 116, 77, 55, 113, 116, 106, 51, 117, 49, 99, 73, 105, 117, 80, 104, 110, 80, 81, 67, 106, 89, 47, 77, 105, 81, 117, 49, 50, 90, 73, 118, 86, 83, 53, 108, 106, 70, 72, 52, 103, 120, 10, 81, 43, 54, 73, 72, 100, 102, 71, 106, 106, 120, 68, 97, 104, 50, 110, 71, 78, 53, 57, 80, 82, 98, 120, 89, 118, 110, 75, 107, 75, 106, 57, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 85, 83, 69, 82, 84, 114, 117, 115, 116, 32, 69, 67, 67, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 106, 122, 67, 67, 65, 104, 87, 103, 65, 119, 73, 66, 65, 103, 73, 81, 88, 73, 117, 90, 120, 86, 113, 85, 120, 100, 74, 120, 86, 116, 55, 78, 105, 89, 68, 77, 74, 106, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 122, 67, 66, 105, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 10, 86, 86, 77, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 103, 84, 67, 107, 53, 108, 100, 121, 66, 75, 90, 88, 74, 122, 90, 88, 107, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 99, 84, 67, 48, 112, 108, 99, 110, 78, 108, 101, 83, 66, 68, 97, 88, 82, 53, 77, 82, 52, 119, 72, 65, 89, 68, 86, 81, 81, 75, 69, 120, 86, 85, 10, 97, 71, 85, 103, 86, 86, 78, 70, 85, 108, 82, 83, 86, 86, 78, 85, 73, 69, 53, 108, 100, 72, 100, 118, 99, 109, 115, 120, 76, 106, 65, 115, 66, 103, 78, 86, 66, 65, 77, 84, 74, 86, 86, 84, 82, 86, 74, 85, 99, 110, 86, 122, 100, 67, 66, 70, 81, 48, 77, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 10, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 72, 104, 99, 78, 77, 84, 65, 119, 77, 106, 65, 120, 77, 68, 65, 119, 77, 68, 65, 119, 87, 104, 99, 78, 77, 122, 103, 119, 77, 84, 69, 52, 77, 106, 77, 49, 79, 84, 85, 53, 87, 106, 67, 66, 105, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 10, 86, 86, 77, 120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 103, 84, 67, 107, 53, 108, 100, 121, 66, 75, 90, 88, 74, 122, 90, 88, 107, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 99, 84, 67, 48, 112, 108, 99, 110, 78, 108, 101, 83, 66, 68, 97, 88, 82, 53, 77, 82, 52, 119, 72, 65, 89, 68, 86, 81, 81, 75, 69, 120, 86, 85, 10, 97, 71, 85, 103, 86, 86, 78, 70, 85, 108, 82, 83, 86, 86, 78, 85, 73, 69, 53, 108, 100, 72, 100, 118, 99, 109, 115, 120, 76, 106, 65, 115, 66, 103, 78, 86, 66, 65, 77, 84, 74, 86, 86, 84, 82, 86, 74, 85, 99, 110, 86, 122, 100, 67, 66, 70, 81, 48, 77, 103, 81, 50, 86, 121, 100, 71, 108, 109, 97, 87, 78, 104, 100, 71, 108, 118, 10, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 119, 100, 106, 65, 81, 66, 103, 99, 113, 104, 107, 106, 79, 80, 81, 73, 66, 66, 103, 85, 114, 103, 81, 81, 65, 73, 103, 78, 105, 65, 65, 81, 97, 114, 70, 82, 97, 113, 102, 108, 111, 73, 43, 100, 54, 49, 83, 82, 118, 85, 56, 90, 97, 50, 69, 117, 114, 120, 116, 87, 50, 10, 48, 101, 90, 122, 99, 97, 55, 100, 110, 78, 89, 77, 89, 102, 51, 98, 111, 73, 107, 68, 117, 65, 85, 85, 55, 70, 102, 79, 55, 108, 48, 47, 52, 105, 71, 122, 122, 118, 102, 85, 105, 110, 110, 103, 111, 52, 78, 43, 76, 90, 102, 81, 89, 99, 84, 120, 109, 100, 119, 108, 107, 87, 79, 114, 102, 122, 67, 106, 116, 72, 68, 105, 120, 54, 69, 122, 10, 110, 80, 79, 47, 76, 108, 120, 84, 115, 86, 43, 122, 102, 84, 74, 47, 105, 106, 84, 106, 101, 88, 109, 106, 81, 106, 66, 65, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 81, 54, 52, 81, 109, 71, 49, 77, 56, 90, 119, 112, 90, 50, 100, 69, 108, 50, 51, 79, 65, 49, 120, 109, 78, 106, 109, 106, 65, 79, 66, 103, 78, 86, 10, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 119, 78, 111, 65, 68, 66, 108, 65, 106, 65, 50, 90, 54, 69, 87, 67, 78, 122, 107, 108, 119, 66, 66, 10, 72, 85, 54, 43, 52, 87, 77, 66, 122, 122, 117, 113, 81, 104, 70, 107, 111, 74, 50, 85, 79, 81, 73, 82, 101, 86, 120, 55, 72, 102, 112, 107, 117, 101, 52, 87, 81, 114, 79, 47, 105, 115, 73, 74, 120, 79, 122, 107, 115, 85, 48, 67, 77, 81, 68, 112, 75, 109, 70, 72, 106, 70, 74, 75, 83, 48, 52, 89, 99, 80, 98, 87, 82, 78, 90, 117, 10, 57, 89, 79, 54, 98, 86, 105, 57, 74, 78, 108, 87, 83, 79, 114, 118, 120, 75, 74, 71, 103, 89, 104, 113, 79, 107, 98, 82, 113, 90, 116, 78, 121, 87, 72, 97, 48, 86, 49, 88, 97, 104, 103, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 108, 111, 98, 97, 108, 83, 105, 103, 110, 32, 69, 67, 67, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 82, 52, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 66, 52, 84, 67, 67, 65, 89, 101, 103, 65, 119, 73, 66, 65, 103, 73, 82, 75, 106, 105, 107, 72, 74, 89, 75, 66, 78, 53, 67, 115, 105, 105, 108, 67, 43, 103, 48, 109, 65, 73, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 85, 68, 69, 107, 77, 67, 73, 71, 65, 49, 85, 69, 67, 120, 77, 98, 10, 82, 50, 120, 118, 89, 109, 70, 115, 85, 50, 108, 110, 98, 105, 66, 70, 81, 48, 77, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 116, 73, 70, 73, 48, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 75, 69, 119, 112, 72, 98, 71, 57, 105, 89, 87, 120, 84, 97, 87, 100, 117, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 68, 10, 69, 119, 112, 72, 98, 71, 57, 105, 89, 87, 120, 84, 97, 87, 100, 117, 77, 66, 52, 88, 68, 84, 69, 121, 77, 84, 69, 120, 77, 122, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 77, 52, 77, 68, 69, 120, 79, 84, 65, 122, 77, 84, 81, 119, 78, 49, 111, 119, 85, 68, 69, 107, 77, 67, 73, 71, 65, 49, 85, 69, 67, 120, 77, 98, 10, 82, 50, 120, 118, 89, 109, 70, 115, 85, 50, 108, 110, 98, 105, 66, 70, 81, 48, 77, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 116, 73, 70, 73, 48, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 75, 69, 119, 112, 72, 98, 71, 57, 105, 89, 87, 120, 84, 97, 87, 100, 117, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 68, 10, 69, 119, 112, 72, 98, 71, 57, 105, 89, 87, 120, 84, 97, 87, 100, 117, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 117, 77, 90, 53, 48, 52, 57, 115, 74, 81, 54, 102, 76, 106, 107, 90, 72, 65, 79, 107, 114, 112, 114, 108, 10, 79, 81, 99, 74, 70, 115, 112, 106, 115, 98, 109, 71, 43, 73, 112, 88, 119, 86, 102, 79, 81, 118, 112, 122, 111, 102, 100, 108, 81, 118, 56, 101, 119, 81, 67, 121, 98, 110, 77, 79, 47, 56, 99, 104, 53, 82, 105, 107, 113, 116, 108, 120, 80, 54, 106, 85, 117, 99, 54, 77, 72, 97, 78, 67, 77, 69, 65, 119, 68, 103, 89, 68, 86, 82, 48, 80, 10, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 70, 83, 119, 101, 54, 49, 70, 117, 79, 74, 65, 102, 47, 115, 75, 98, 118, 117, 43, 77, 56, 107, 56, 111, 52, 84, 86, 10, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 65, 48, 103, 65, 77, 69, 85, 67, 73, 81, 68, 99, 107, 113, 71, 103, 69, 54, 98, 80, 65, 55, 68, 109, 120, 67, 71, 88, 107, 80, 111, 85, 86, 121, 48, 68, 55, 79, 52, 56, 48, 50, 55, 75, 113, 71, 120, 50, 118, 75, 76, 101, 117, 119, 73, 103, 74, 54, 105, 70, 10, 74, 122, 87, 98, 86, 115, 97, 106, 56, 107, 102, 83, 116, 50, 52, 98, 65, 103, 65, 88, 113, 109, 101, 109, 70, 90, 72, 101, 43, 112, 84, 115, 101, 119, 118, 52, 110, 52, 81, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 71, 108, 111, 98, 97, 108, 83, 105, 103, 110, 32, 69, 67, 67, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 82, 53, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 72, 106, 67, 67, 65, 97, 83, 103, 65, 119, 73, 66, 65, 103, 73, 82, 89, 70, 108, 74, 52, 67, 89, 117, 117, 49, 88, 53, 67, 110, 101, 75, 99, 102, 108, 75, 50, 71, 119, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 77, 119, 85, 68, 69, 107, 77, 67, 73, 71, 65, 49, 85, 69, 67, 120, 77, 98, 10, 82, 50, 120, 118, 89, 109, 70, 115, 85, 50, 108, 110, 98, 105, 66, 70, 81, 48, 77, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 116, 73, 70, 73, 49, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 75, 69, 119, 112, 72, 98, 71, 57, 105, 89, 87, 120, 84, 97, 87, 100, 117, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 68, 10, 69, 119, 112, 72, 98, 71, 57, 105, 89, 87, 120, 84, 97, 87, 100, 117, 77, 66, 52, 88, 68, 84, 69, 121, 77, 84, 69, 120, 77, 122, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 77, 52, 77, 68, 69, 120, 79, 84, 65, 122, 77, 84, 81, 119, 78, 49, 111, 119, 85, 68, 69, 107, 77, 67, 73, 71, 65, 49, 85, 69, 67, 120, 77, 98, 10, 82, 50, 120, 118, 89, 109, 70, 115, 85, 50, 108, 110, 98, 105, 66, 70, 81, 48, 77, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 116, 73, 70, 73, 49, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 75, 69, 119, 112, 72, 98, 71, 57, 105, 89, 87, 120, 84, 97, 87, 100, 117, 77, 82, 77, 119, 69, 81, 89, 68, 86, 81, 81, 68, 10, 69, 119, 112, 72, 98, 71, 57, 105, 89, 87, 120, 84, 97, 87, 100, 117, 77, 72, 89, 119, 69, 65, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 70, 75, 52, 69, 69, 65, 67, 73, 68, 89, 103, 65, 69, 82, 48, 85, 79, 108, 118, 116, 57, 88, 98, 47, 112, 79, 100, 69, 104, 43, 74, 56, 76, 116, 116, 86, 55, 72, 112, 73, 54, 10, 83, 70, 107, 99, 56, 71, 73, 120, 76, 99, 66, 54, 75, 80, 52, 97, 112, 49, 121, 122, 116, 115, 121, 88, 53, 48, 88, 85, 87, 80, 114, 82, 100, 50, 49, 68, 111, 115, 67, 72, 90, 84, 81, 75, 72, 51, 114, 100, 54, 122, 119, 122, 111, 99, 87, 100, 84, 97, 82, 118, 81, 90, 85, 52, 102, 56, 107, 101, 104, 79, 118, 82, 110, 107, 109, 83, 10, 104, 53, 83, 72, 68, 68, 113, 70, 83, 109, 97, 102, 110, 86, 109, 84, 84, 90, 100, 104, 66, 111, 90, 75, 111, 48, 73, 119, 81, 68, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 100, 10, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 80, 101, 89, 112, 83, 74, 118, 113, 66, 56, 111, 104, 82, 69, 111, 109, 51, 109, 55, 101, 48, 111, 80, 81, 110, 49, 107, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 77, 68, 97, 65, 65, 119, 90, 81, 73, 120, 65, 79, 86, 112, 69, 115, 108, 117, 50, 56, 89, 120, 10, 117, 103, 108, 66, 52, 90, 102, 52, 43, 47, 50, 97, 52, 110, 48, 83, 121, 101, 49, 56, 90, 78, 80, 76, 66, 83, 87, 76, 86, 116, 109, 103, 53, 49, 53, 100, 84, 103, 117, 68, 110, 70, 116, 50, 75, 97, 65, 74, 74, 105, 70, 113, 89, 103, 73, 119, 99, 100, 75, 49, 106, 49, 122, 113, 79, 43, 70, 52, 67, 89, 87, 111, 100, 90, 73, 55, 10, 121, 70, 122, 57, 83, 79, 56, 78, 100, 67, 75, 111, 67, 79, 74, 117, 120, 85, 110, 79, 120, 119, 121, 56, 112, 50, 70, 112, 56, 102, 99, 55, 52, 83, 114, 76, 43, 83, 118, 122, 90, 112, 65, 51, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 116, 97, 97, 116, 32, 100, 101, 114, 32, 78, 101, 100, 101, 114, 108, 97, 110, 100, 101, 110, 32, 82, 111, 111, 116, 32, 67, 65, 32, 45, 32, 71, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 100, 68, 67, 67, 65, 49, 121, 103, 65, 119, 73, 66, 65, 103, 73, 69, 65, 74, 105, 105, 79, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 97, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 79, 84, 68, 69, 101, 77, 66, 119, 71, 65, 49, 85, 69, 10, 67, 103, 119, 86, 85, 51, 82, 104, 89, 88, 81, 103, 90, 71, 86, 121, 73, 69, 53, 108, 90, 71, 86, 121, 98, 71, 70, 117, 90, 71, 86, 117, 77, 83, 115, 119, 75, 81, 89, 68, 86, 81, 81, 68, 68, 67, 74, 84, 100, 71, 70, 104, 100, 67, 66, 107, 90, 88, 73, 103, 84, 109, 86, 107, 90, 88, 74, 115, 89, 87, 53, 107, 90, 87, 52, 103, 10, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 116, 73, 69, 99, 122, 77, 66, 52, 88, 68, 84, 69, 122, 77, 84, 69, 120, 78, 68, 69, 120, 77, 106, 103, 48, 77, 108, 111, 88, 68, 84, 73, 52, 77, 84, 69, 120, 77, 122, 73, 122, 77, 68, 65, 119, 77, 70, 111, 119, 87, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 10, 84, 107, 119, 120, 72, 106, 65, 99, 66, 103, 78, 86, 66, 65, 111, 77, 70, 86, 78, 48, 89, 87, 70, 48, 73, 71, 82, 108, 99, 105, 66, 79, 90, 87, 82, 108, 99, 109, 120, 104, 98, 109, 82, 108, 98, 106, 69, 114, 77, 67, 107, 71, 65, 49, 85, 69, 65, 119, 119, 105, 85, 51, 82, 104, 89, 88, 81, 103, 90, 71, 86, 121, 73, 69, 53, 108, 10, 90, 71, 86, 121, 98, 71, 70, 117, 90, 71, 86, 117, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 76, 83, 66, 72, 77, 122, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 76, 52, 121, 10, 111, 108, 81, 80, 99, 80, 115, 115, 88, 70, 110, 114, 98, 77, 83, 107, 85, 101, 105, 70, 75, 114, 80, 77, 83, 106, 84, 121, 115, 70, 47, 122, 68, 115, 99, 99, 80, 86, 77, 101, 105, 65, 104, 111, 50, 71, 56, 57, 114, 99, 75, 101, 122, 73, 74, 110, 66, 121, 101, 72, 97, 72, 69, 54, 110, 51, 87, 87, 73, 107, 89, 70, 115, 79, 50, 116, 10, 120, 49, 117, 101, 75, 116, 54, 99, 47, 68, 114, 71, 108, 97, 102, 49, 70, 50, 99, 89, 53, 121, 57, 74, 67, 65, 120, 99, 122, 43, 98, 77, 78, 79, 49, 52, 43, 49, 67, 120, 51, 71, 115, 121, 56, 75, 76, 43, 116, 106, 122, 107, 55, 70, 113, 88, 120, 122, 56, 101, 99, 65, 103, 119, 111, 78, 122, 70, 115, 50, 49, 118, 48, 73, 74, 121, 10, 69, 97, 118, 83, 103, 87, 104, 90, 103, 104, 101, 51, 101, 74, 74, 103, 43, 115, 122, 101, 80, 52, 84, 114, 106, 84, 103, 122, 107, 65, 112, 121, 73, 47, 111, 49, 122, 67, 90, 120, 77, 100, 70, 121, 75, 74, 76, 90, 87, 121, 78, 116, 90, 114, 86, 116, 66, 48, 76, 114, 112, 106, 80, 79, 107, 116, 118, 65, 57, 109, 120, 106, 101, 77, 51, 75, 10, 84, 106, 50, 49, 53, 86, 75, 98, 56, 98, 52, 55, 53, 108, 82, 103, 115, 71, 89, 101, 67, 97, 115, 72, 47, 108, 83, 74, 69, 85, 76, 82, 57, 121, 83, 54, 89, 72, 103, 97, 109, 80, 102, 74, 69, 102, 48, 87, 119, 84, 85, 97, 86, 72, 88, 118, 81, 57, 80, 108, 114, 107, 55, 79, 53, 51, 118, 68, 120, 107, 53, 104, 85, 85, 117, 114, 10, 109, 107, 86, 76, 111, 82, 57, 66, 118, 85, 104, 84, 70, 88, 70, 107, 67, 52, 97, 122, 53, 83, 54, 43, 122, 113, 81, 98, 119, 83, 109, 69, 111, 114, 88, 76, 67, 67, 78, 50, 81, 121, 73, 107, 72, 120, 99, 69, 49, 71, 54, 99, 120, 118, 120, 47, 75, 50, 89, 97, 55, 73, 114, 108, 49, 115, 57, 78, 57, 87, 77, 74, 116, 120, 85, 53, 10, 49, 110, 117, 115, 54, 43, 78, 56, 54, 85, 55, 56, 100, 85, 76, 73, 55, 86, 105, 86, 68, 65, 90, 67, 111, 112, 122, 51, 53, 72, 67, 122, 51, 51, 74, 118, 87, 106, 100, 65, 105, 100, 105, 70, 112, 78, 102, 120, 67, 57, 53, 68, 71, 100, 82, 75, 87, 67, 121, 77, 105, 106, 109, 101, 118, 52, 83, 72, 56, 82, 89, 55, 78, 103, 122, 112, 10, 48, 55, 84, 75, 98, 66, 108, 66, 85, 103, 109, 104, 72, 98, 66, 113, 118, 52, 76, 118, 99, 70, 69, 104, 77, 116, 119, 70, 100, 111, 122, 76, 57, 50, 84, 107, 65, 49, 67, 118, 106, 74, 70, 110, 113, 56, 88, 121, 55, 108, 106, 89, 51, 114, 55, 51, 53, 122, 72, 80, 98, 77, 107, 55, 99, 99, 72, 86, 105, 76, 86, 108, 118, 77, 68, 111, 10, 70, 120, 99, 72, 69, 114, 86, 99, 48, 113, 115, 103, 107, 55, 84, 109, 103, 111, 78, 119, 78, 115, 88, 78, 111, 52, 50, 116, 105, 43, 121, 106, 119, 85, 79, 72, 53, 107, 80, 105, 78, 76, 54, 86, 105, 122, 88, 116, 66, 122, 110, 97, 113, 66, 49, 54, 110, 122, 97, 101, 69, 114, 65, 77, 90, 82, 75, 81, 70, 87, 68, 90, 74, 107, 66, 69, 10, 52, 49, 90, 103, 112, 82, 68, 85, 97, 106, 122, 57, 81, 100, 119, 79, 87, 107, 101, 50, 55, 53, 100, 104, 100, 85, 47, 90, 47, 115, 101, 121, 72, 100, 84, 116, 88, 85, 109, 122, 113, 87, 114, 76, 90, 111, 81, 84, 49, 86, 121, 103, 51, 78, 57, 117, 100, 119, 98, 82, 99, 88, 88, 73, 86, 50, 43, 118, 68, 51, 100, 98, 65, 103, 77, 66, 10, 65, 65, 71, 106, 81, 106, 66, 65, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 85, 114, 102, 114, 72, 107, 108, 101, 117, 10, 121, 106, 87, 99, 76, 104, 76, 55, 53, 76, 112, 100, 73, 78, 121, 85, 86, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, 67, 65, 103, 69, 65, 77, 74, 109, 100, 66, 84, 76, 73, 88, 103, 52, 55, 109, 65, 69, 54, 105, 113, 84, 110, 66, 47, 100, 54, 43, 79, 101, 97, 51, 49, 66, 68, 10, 85, 53, 99, 113, 80, 99, 111, 56, 82, 53, 103, 117, 52, 82, 86, 55, 56, 90, 76, 122, 89, 100, 113, 81, 74, 82, 90, 108, 119, 74, 57, 85, 88, 81, 52, 68, 79, 49, 116, 51, 65, 112, 121, 69, 116, 103, 50, 89, 88, 122, 84, 100, 79, 50, 80, 67, 119, 121, 105, 66, 119, 112, 119, 112, 76, 105, 110, 105, 121, 77, 77, 66, 56, 106, 80, 113, 10, 75, 113, 114, 77, 67, 81, 106, 51, 90, 87, 102, 71, 122, 100, 47, 84, 116, 105, 117, 110, 118, 99, 122, 82, 68, 110, 66, 102, 117, 67, 80, 82, 121, 53, 70, 79, 67, 118, 84, 73, 101, 117, 88, 90, 89, 122, 98, 66, 49, 78, 47, 56, 73, 112, 102, 51, 89, 70, 51, 113, 75, 83, 57, 89, 115, 114, 49, 89, 118, 89, 50, 87, 84, 120, 66, 49, 10, 118, 48, 104, 55, 80, 86, 71, 72, 111, 84, 120, 48, 73, 115, 76, 56, 66, 51, 43, 65, 51, 77, 83, 115, 47, 109, 114, 66, 99, 68, 67, 119, 54, 89, 53, 112, 52, 105, 120, 112, 103, 90, 81, 74, 117, 116, 51, 43, 84, 99, 67, 68, 106, 74, 82, 89, 119, 69, 89, 103, 114, 53, 119, 102, 65, 118, 103, 49, 86, 85, 107, 118, 82, 116, 84, 65, 10, 56, 75, 67, 87, 65, 103, 56, 122, 120, 88, 72, 122, 110, 105, 78, 57, 108, 76, 102, 57, 79, 116, 77, 74, 103, 119, 89, 104, 47, 87, 65, 57, 114, 106, 76, 65, 48, 117, 54, 78, 112, 118, 68, 110, 116, 73, 74, 56, 67, 115, 120, 119, 121, 88, 109, 65, 43, 80, 53, 77, 57, 122, 87, 69, 71, 89, 111, 120, 43, 119, 114, 90, 49, 51, 43, 98, 10, 56, 75, 75, 97, 97, 56, 77, 70, 83, 117, 49, 66, 89, 66, 81, 119, 48, 97, 111, 82, 81, 109, 55, 84, 73, 119, 73, 69, 67, 56, 90, 108, 51, 100, 49, 83, 100, 57, 113, 66, 97, 55, 75, 111, 43, 103, 69, 52, 117, 90, 98, 113, 75, 109, 120, 110, 108, 52, 109, 85, 110, 114, 122, 104, 86, 78, 88, 107, 97, 110, 106, 118, 83, 114, 48, 114, 10, 109, 106, 49, 65, 102, 115, 98, 65, 100, 100, 74, 117, 43, 50, 103, 119, 55, 79, 121, 76, 110, 102, 108, 74, 78, 90, 111, 97, 76, 78, 109, 122, 108, 84, 110, 86, 72, 112, 76, 51, 112, 114, 108, 108, 76, 43, 85, 57, 98, 84, 112, 73, 84, 65, 106, 99, 53, 67, 103, 83, 75, 76, 53, 57, 78, 86, 122, 113, 52, 66, 90, 43, 69, 120, 116, 113, 10, 49, 122, 55, 88, 110, 118, 119, 116, 100, 98, 76, 66, 70, 78, 85, 106, 65, 57, 116, 98, 98, 119, 115, 43, 101, 67, 56, 78, 51, 106, 79, 78, 70, 114, 100, 73, 53, 52, 79, 97, 103, 81, 57, 55, 119, 85, 78, 78, 86, 81, 81, 88, 79, 69, 112, 82, 49, 86, 109, 105, 105, 88, 84, 84, 110, 55, 52, 101, 83, 57, 102, 71, 98, 98, 101, 73, 10, 74, 71, 57, 103, 107, 97, 83, 67, 104, 86, 116, 87, 81, 98, 122, 81, 82, 75, 116, 113, 69, 55, 55, 82, 76, 70, 105, 51, 69, 106, 78, 89, 115, 106, 100, 106, 51, 66, 80, 49, 108, 66, 48, 47, 81, 70, 72, 49, 84, 47, 85, 54, 55, 99, 106, 70, 54, 56, 73, 101, 72, 82, 97, 86, 101, 115, 100, 43, 81, 110, 71, 84, 98, 107, 115, 86, 10, 116, 122, 68, 102, 113, 117, 49, 88, 104, 85, 105, 115, 72, 87, 114, 100, 79, 87, 110, 107, 52, 88, 108, 52, 118, 115, 52, 70, 118, 54, 69, 77, 57, 52, 66, 55, 73, 87, 99, 110, 77, 70, 107, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 116, 97, 97, 116, 32, 100, 101, 114, 32, 78, 101, 100, 101, 114, 108, 97, 110, 100, 101, 110, 32, 69, 86, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 99, 68, 67, 67, 65, 49, 105, 103, 65, 119, 73, 66, 65, 103, 73, 69, 65, 74, 105, 87, 106, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 89, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 79, 84, 68, 69, 101, 77, 66, 119, 71, 65, 49, 85, 69, 10, 67, 103, 119, 86, 85, 51, 82, 104, 89, 88, 81, 103, 90, 71, 86, 121, 73, 69, 53, 108, 90, 71, 86, 121, 98, 71, 70, 117, 90, 71, 86, 117, 77, 83, 107, 119, 74, 119, 89, 68, 86, 81, 81, 68, 68, 67, 66, 84, 100, 71, 70, 104, 100, 67, 66, 107, 90, 88, 73, 103, 84, 109, 86, 107, 90, 88, 74, 115, 89, 87, 53, 107, 90, 87, 52, 103, 10, 82, 86, 89, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 84, 65, 101, 70, 119, 48, 120, 77, 68, 69, 121, 77, 68, 103, 120, 77, 84, 69, 53, 77, 106, 108, 97, 70, 119, 48, 121, 77, 106, 69, 121, 77, 68, 103, 120, 77, 84, 69, 119, 77, 106, 104, 97, 77, 70, 103, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 53, 77, 10, 77, 82, 52, 119, 72, 65, 89, 68, 86, 81, 81, 75, 68, 66, 86, 84, 100, 71, 70, 104, 100, 67, 66, 107, 90, 88, 73, 103, 84, 109, 86, 107, 90, 88, 74, 115, 89, 87, 53, 107, 90, 87, 52, 120, 75, 84, 65, 110, 66, 103, 78, 86, 66, 65, 77, 77, 73, 70, 78, 48, 89, 87, 70, 48, 73, 71, 82, 108, 99, 105, 66, 79, 90, 87, 82, 108, 10, 99, 109, 120, 104, 98, 109, 82, 108, 98, 105, 66, 70, 86, 105, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 73, 73, 67, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 103, 56, 65, 77, 73, 73, 67, 67, 103, 75, 67, 65, 103, 69, 65, 52, 56, 100, 43, 105, 102, 107, 107, 10, 83, 122, 114, 83, 77, 52, 77, 49, 76, 71, 110, 115, 51, 65, 109, 107, 52, 49, 71, 111, 74, 83, 116, 53, 117, 65, 103, 57, 52, 74, 71, 54, 104, 73, 88, 71, 104, 97, 84, 75, 53, 115, 107, 117, 85, 54, 84, 74, 74, 66, 55, 57, 86, 87, 90, 120, 88, 83, 122, 70, 89, 71, 103, 69, 116, 57, 110, 67, 85, 105, 89, 52, 105, 75, 84, 87, 10, 79, 48, 67, 109, 119, 115, 48, 47, 122, 90, 105, 84, 115, 49, 81, 85, 87, 74, 90, 86, 49, 86, 68, 43, 104, 113, 50, 107, 89, 51, 57, 99, 104, 47, 97, 79, 53, 105, 101, 83, 90, 120, 101, 83, 65, 103, 77, 115, 51, 78, 90, 109, 100, 79, 51, 100, 90, 47, 47, 66, 89, 89, 49, 106, 84, 119, 43, 98, 98, 82, 99, 119, 74, 117, 43, 114, 10, 48, 104, 56, 81, 111, 80, 110, 70, 102, 120, 90, 112, 103, 81, 78, 72, 55, 82, 53, 111, 106, 88, 75, 104, 84, 98, 73, 109, 120, 114, 112, 115, 88, 50, 51, 87, 114, 57, 71, 120, 69, 52, 54, 112, 114, 102, 78, 101, 97, 88, 85, 109, 71, 68, 53, 66, 75, 121, 70, 47, 55, 111, 116, 100, 66, 119, 97, 100, 81, 56, 81, 112, 67, 105, 118, 56, 10, 75, 106, 54, 71, 121, 122, 121, 68, 79, 118, 110, 74, 68, 100, 114, 70, 109, 101, 75, 56, 101, 69, 69, 122, 100, 117, 71, 47, 76, 49, 51, 108, 112, 74, 104, 81, 68, 66, 88, 100, 52, 80, 113, 99, 102, 122, 104, 111, 48, 76, 75, 109, 101, 113, 102, 82, 77, 98, 49, 43, 105, 108, 103, 110, 81, 55, 79, 54, 77, 53, 72, 84, 112, 53, 103, 86, 10, 88, 74, 114, 109, 48, 119, 57, 49, 50, 102, 120, 66, 109, 74, 99, 43, 113, 105, 88, 98, 106, 53, 73, 117, 115, 72, 115, 77, 88, 47, 70, 106, 113, 84, 102, 53, 109, 51, 86, 112, 84, 67, 103, 109, 74, 100, 114, 86, 56, 104, 74, 119, 82, 86, 88, 106, 51, 51, 78, 101, 78, 47, 85, 104, 98, 74, 67, 79, 78, 86, 114, 74, 48, 121, 80, 114, 10, 48, 56, 67, 43, 101, 75, 120, 67, 75, 70, 104, 109, 112, 85, 90, 116, 99, 65, 76, 88, 69, 80, 108, 76, 86, 80, 120, 100, 104, 107, 113, 72, 122, 51, 47, 75, 82, 97, 119, 82, 87, 114, 85, 103, 85, 89, 48, 118, 105, 69, 101, 88, 79, 99, 68, 80, 117, 115, 66, 67, 65, 85, 67, 90, 83, 67, 69, 76, 97, 54, 102, 83, 47, 90, 98, 86, 10, 48, 98, 53, 71, 110, 85, 110, 103, 67, 54, 97, 103, 73, 107, 52, 52, 48, 77, 69, 56, 77, 76, 120, 119, 106, 121, 120, 49, 122, 78, 68, 70, 106, 70, 69, 55, 80, 90, 81, 73, 90, 67, 90, 104, 102, 98, 110, 68, 90, 89, 56, 85, 110, 67, 72, 81, 113, 118, 48, 88, 99, 103, 79, 80, 118, 90, 117, 77, 53, 108, 53, 84, 110, 114, 109, 100, 10, 55, 52, 75, 55, 52, 98, 122, 105, 99, 107, 70, 98, 73, 90, 84, 84, 82, 84, 101, 85, 48, 100, 56, 74, 79, 86, 51, 110, 73, 54, 113, 97, 72, 99, 112, 116, 113, 65, 113, 71, 104, 89, 113, 67, 118, 107, 73, 72, 49, 118, 73, 52, 103, 110, 80, 97, 104, 49, 118, 108, 80, 78, 79, 101, 80, 113, 99, 55, 110, 118, 81, 68, 115, 47, 110, 120, 10, 102, 82, 78, 48, 65, 118, 43, 55, 111, 101, 88, 54, 65, 72, 107, 99, 112, 109, 90, 66, 105, 70, 120, 103, 86, 54, 89, 117, 67, 99, 83, 54, 47, 90, 114, 80, 112, 120, 57, 65, 119, 55, 118, 77, 87, 103, 112, 86, 83, 122, 115, 52, 100, 108, 71, 52, 89, 52, 117, 69, 108, 66, 98, 109, 86, 118, 77, 67, 65, 119, 69, 65, 65, 97, 78, 67, 10, 77, 69, 65, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 80, 54, 114, 65, 74, 67, 89, 110, 105, 84, 56, 113, 99, 119, 97, 10, 105, 118, 115, 110, 117, 76, 56, 119, 98, 113, 103, 55, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 67, 65, 81, 68, 80, 100, 121, 120, 117, 86, 114, 53, 79, 115, 55, 97, 69, 65, 74, 83, 114, 82, 56, 107, 78, 48, 110, 98, 72, 104, 112, 56, 100, 66, 57, 79, 50, 116, 76, 115, 73, 10, 101, 75, 57, 112, 48, 103, 116, 74, 51, 106, 80, 70, 114, 75, 51, 67, 105, 65, 74, 57, 66, 114, 99, 49, 65, 115, 70, 103, 121, 98, 47, 69, 54, 74, 84, 101, 49, 78, 79, 112, 69, 121, 86, 97, 47, 109, 54, 105, 114, 110, 48, 70, 51, 72, 51, 122, 98, 80, 66, 43, 112, 111, 51, 117, 50, 100, 102, 79, 87, 66, 102, 111, 113, 83, 109, 117, 10, 99, 48, 105, 72, 53, 53, 118, 75, 98, 105, 109, 104, 90, 70, 56, 90, 69, 47, 101, 117, 66, 104, 68, 47, 85, 99, 97, 98, 84, 86, 85, 108, 84, 53, 79, 90, 69, 65, 70, 84, 100, 102, 69, 84, 122, 115, 101, 109, 81, 85, 72, 83, 118, 52, 105, 108, 102, 48, 88, 56, 114, 76, 105, 108, 116, 84, 77, 77, 103, 115, 84, 55, 66, 47, 90, 113, 10, 53, 83, 87, 69, 88, 119, 98, 75, 119, 89, 89, 53, 69, 100, 116, 89, 122, 88, 99, 55, 76, 77, 74, 77, 68, 49, 54, 97, 52, 47, 67, 114, 80, 109, 69, 98, 85, 67, 84, 67, 119, 80, 84, 120, 71, 102, 65, 82, 75, 98, 97, 108, 71, 65, 75, 98, 49, 50, 78, 77, 99, 73, 120, 72, 111, 119, 78, 68, 88, 76, 108, 100, 82, 113, 65, 78, 10, 98, 47, 57, 90, 106, 114, 55, 100, 110, 51, 76, 68, 87, 121, 118, 102, 106, 70, 118, 79, 53, 81, 120, 71, 98, 74, 75, 121, 67, 113, 78, 77, 86, 69, 73, 89, 70, 82, 73, 89, 118, 100, 114, 56, 117, 110, 82, 117, 47, 56, 71, 50, 111, 71, 84, 89, 113, 86, 57, 86, 114, 112, 57, 99, 97, 110, 97, 87, 50, 72, 78, 110, 104, 47, 116, 78, 10, 102, 49, 122, 117, 97, 99, 112, 122, 69, 80, 117, 75, 113, 102, 50, 101, 118, 84, 89, 52, 83, 85, 109, 72, 57, 65, 52, 85, 56, 79, 109, 72, 117, 68, 43, 110, 84, 51, 112, 97, 106, 110, 110, 85, 107, 43, 83, 55, 97, 70, 75, 69, 114, 71, 122, 112, 56, 53, 104, 119, 86, 88, 73, 121, 43, 84, 83, 114, 75, 48, 109, 49, 122, 83, 66, 105, 10, 53, 68, 112, 54, 90, 50, 79, 114, 108, 116, 120, 116, 114, 112, 102, 115, 47, 74, 57, 50, 86, 111, 103, 117, 90, 115, 57, 98, 116, 115, 109, 107, 115, 78, 99, 70, 117, 117, 69, 110, 76, 53, 79, 55, 74, 105, 113, 105, 107, 55, 65, 98, 56, 52, 54, 43, 72, 85, 67, 106, 117, 84, 97, 80, 80, 111, 73, 97, 71, 108, 54, 73, 54, 108, 68, 52, 10, 87, 101, 75, 68, 82, 105, 107, 76, 52, 48, 82, 99, 52, 90, 87, 50, 97, 90, 67, 97, 70, 71, 43, 88, 114, 111, 72, 80, 97, 79, 43, 90, 109, 114, 54, 49, 53, 43, 70, 47, 43, 80, 111, 84, 82, 120, 90, 77, 122, 71, 48, 73, 81, 79, 101, 76, 101, 71, 57, 81, 103, 107, 82, 81, 80, 50, 89, 71, 105, 113, 116, 68, 104, 70, 90, 75, 10, 68, 121, 65, 116, 104, 103, 55, 49, 48, 116, 118, 83, 101, 111, 112, 76, 122, 97, 88, 111, 84, 118, 70, 101, 74, 105, 85, 66, 87, 83, 79, 103, 102, 116, 76, 50, 102, 105, 70, 88, 49, 121, 101, 56, 70, 86, 100, 77, 112, 69, 98, 66, 52, 73, 77, 101, 68, 69, 120, 78, 72, 48, 56, 71, 71, 101, 76, 53, 113, 80, 81, 54, 103, 113, 71, 121, 10, 101, 85, 78, 53, 49, 113, 49, 118, 101, 105, 101, 81, 65, 54, 84, 113, 74, 73, 99, 47, 50, 98, 51, 90, 54, 102, 74, 102, 85, 69, 107, 99, 55, 117, 122, 88, 76, 103, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 73, 100, 101, 110, 84, 114, 117, 115, 116, 32, 67, 111, 109, 109, 101, 114, 99, 105, 97, 108, 32, 82, 111, 111, 116, 32, 67, 65, 32, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 89, 68, 67, 67, 65, 48, 105, 103, 65, 119, 73, 66, 65, 103, 73, 81, 67, 103, 70, 67, 103, 65, 65, 65, 65, 85, 85, 106, 121, 69, 83, 49, 65, 65, 65, 65, 65, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 75, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 83, 77, 66, 65, 71, 65, 49, 85, 69, 67, 104, 77, 74, 83, 87, 82, 108, 98, 108, 82, 121, 100, 88, 78, 48, 77, 83, 99, 119, 74, 81, 89, 68, 86, 81, 81, 68, 69, 120, 53, 74, 90, 71, 86, 117, 86, 72, 74, 49, 99, 51, 81, 103, 81, 50, 57, 116, 98, 87, 86, 121, 89, 50, 108, 104, 98, 67, 66, 83, 10, 98, 50, 57, 48, 73, 69, 78, 66, 73, 68, 69, 119, 72, 104, 99, 78, 77, 84, 81, 119, 77, 84, 69, 50, 77, 84, 103, 120, 77, 106, 73, 122, 87, 104, 99, 78, 77, 122, 81, 119, 77, 84, 69, 50, 77, 84, 103, 120, 77, 106, 73, 122, 87, 106, 66, 75, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 83, 10, 77, 66, 65, 71, 65, 49, 85, 69, 67, 104, 77, 74, 83, 87, 82, 108, 98, 108, 82, 121, 100, 88, 78, 48, 77, 83, 99, 119, 74, 81, 89, 68, 86, 81, 81, 68, 69, 120, 53, 74, 90, 71, 86, 117, 86, 72, 74, 49, 99, 51, 81, 103, 81, 50, 57, 116, 98, 87, 86, 121, 89, 50, 108, 104, 98, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 10, 73, 68, 69, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 110, 85, 66, 110, 101, 80, 53, 107, 57, 49, 68, 78, 71, 56, 87, 57, 82, 89, 89, 75, 121, 113, 85, 43, 80, 90, 52, 108, 100, 10, 104, 78, 108, 84, 51, 81, 119, 111, 50, 100, 102, 119, 47, 54, 54, 86, 81, 51, 75, 90, 43, 98, 86, 100, 102, 73, 114, 66, 81, 117, 69, 120, 85, 72, 84, 82, 103, 81, 49, 56, 122, 90, 115, 104, 113, 48, 80, 105, 114, 75, 49, 101, 104, 109, 55, 122, 67, 89, 111, 102, 87, 106, 75, 57, 111, 117, 117, 85, 43, 101, 104, 99, 67, 117, 122, 47, 10, 109, 78, 75, 118, 99, 98, 79, 48, 85, 53, 57, 79, 104, 43, 43, 83, 118, 76, 51, 115, 84, 122, 73, 119, 105, 69, 115, 88, 88, 108, 102, 69, 85, 56, 76, 50, 65, 112, 101, 78, 50, 87, 73, 114, 118, 121, 81, 102, 89, 111, 51, 102, 119, 55, 103, 112, 83, 48, 108, 52, 80, 74, 78, 103, 105, 67, 76, 56, 109, 100, 111, 50, 121, 77, 75, 105, 10, 49, 67, 120, 85, 65, 71, 99, 49, 98, 110, 79, 47, 65, 108, 106, 119, 112, 78, 51, 108, 115, 75, 73, 109, 101, 115, 114, 103, 78, 113, 85, 90, 70, 118, 88, 57, 116, 43, 43, 117, 80, 48, 68, 49, 98, 86, 111, 69, 47, 99, 52, 48, 121, 105, 84, 99, 100, 67, 77, 98, 88, 84, 77, 84, 69, 108, 51, 69, 65, 83, 88, 50, 77, 78, 48, 67, 10, 88, 90, 47, 103, 49, 85, 101, 57, 116, 79, 115, 98, 111, 98, 116, 74, 83, 100, 105, 102, 87, 119, 76, 122, 105, 117, 81, 107, 107, 79, 82, 105, 84, 48, 47, 66, 114, 52, 115, 79, 100, 66, 101, 111, 48, 88, 75, 73, 97, 110, 111, 66, 83, 99, 121, 48, 82, 110, 110, 71, 70, 55, 72, 97, 109, 66, 52, 72, 87, 102, 112, 49, 73, 89, 86, 108, 10, 51, 90, 66, 87, 122, 118, 117, 114, 112, 87, 67, 100, 120, 74, 51, 53, 85, 114, 67, 76, 118, 89, 102, 53, 106, 121, 115, 106, 67, 105, 78, 50, 79, 47, 99, 122, 52, 99, 107, 65, 56, 50, 110, 53, 83, 54, 76, 103, 84, 114, 120, 43, 107, 122, 109, 69, 66, 47, 100, 69, 99, 72, 55, 43, 66, 49, 114, 108, 115, 97, 122, 82, 71, 77, 122, 121, 10, 78, 101, 86, 74, 83, 81, 106, 75, 86, 115, 107, 57, 43, 119, 56, 89, 102, 89, 115, 55, 119, 82, 80, 67, 84, 89, 47, 74, 84, 119, 52, 51, 54, 82, 43, 104, 68, 109, 114, 102, 89, 105, 55, 76, 78, 81, 90, 82, 101, 83, 122, 73, 74, 84, 106, 48, 43, 107, 117, 110, 105, 86, 121, 99, 48, 117, 77, 78, 79, 89, 90, 75, 100, 72, 122, 86, 10, 87, 89, 102, 67, 80, 48, 52, 77, 88, 70, 76, 48, 80, 102, 100, 83, 103, 118, 72, 113, 111, 54, 122, 57, 83, 84, 81, 97, 75, 80, 78, 66, 105, 68, 111, 84, 55, 117, 106, 101, 47, 53, 107, 100, 88, 55, 114, 76, 54, 66, 55, 121, 117, 86, 66, 103, 119, 68, 72, 84, 99, 43, 88, 118, 118, 113, 68, 116, 77, 119, 116, 48, 118, 105, 65, 103, 10, 120, 71, 100, 115, 56, 65, 103, 68, 101, 108, 87, 65, 102, 48, 90, 79, 108, 113, 102, 48, 72, 106, 55, 104, 57, 116, 103, 74, 52, 84, 78, 107, 75, 50, 80, 88, 77, 108, 54, 102, 43, 99, 66, 55, 68, 51, 104, 118, 108, 55, 121, 84, 109, 118, 109, 99, 69, 112, 66, 52, 101, 111, 67, 72, 70, 100, 100, 121, 100, 74, 120, 86, 100, 72, 105, 120, 10, 117, 117, 70, 117, 99, 65, 83, 54, 84, 54, 67, 54, 97, 77, 78, 55, 47, 122, 72, 119, 99, 122, 48, 57, 108, 67, 113, 120, 67, 48, 69, 79, 111, 80, 53, 78, 105, 71, 86, 114, 101, 84, 79, 48, 49, 119, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 10, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 55, 85, 81, 90, 119, 78, 80, 119, 66, 111, 118, 117, 112, 72, 117, 43, 81, 117, 99, 109, 86, 77, 105, 79, 78, 110, 89, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 73, 66, 65, 65, 50, 117, 107, 68, 76, 50, 112, 107, 116, 56, 82, 72, 89, 90, 89, 82, 52, 110, 75, 77, 49, 101, 86, 79, 56, 108, 118, 79, 77, 73, 107, 80, 107, 112, 49, 54, 53, 111, 67, 79, 71, 85, 65, 70, 106, 118, 76, 105, 53, 43, 85, 49, 75, 77, 116, 108, 119, 72, 10, 54, 111, 105, 54, 109, 89, 116, 81, 108, 78, 101, 67, 103, 78, 57, 104, 67, 81, 67, 84, 114, 81, 48, 85, 53, 115, 55, 66, 56, 106, 101, 85, 101, 76, 66, 102, 110, 76, 79, 105, 99, 55, 105, 80, 66, 90, 77, 52, 122, 89, 48, 43, 115, 76, 106, 55, 119, 77, 43, 120, 56, 117, 119, 116, 76, 82, 118, 77, 55, 75, 113, 97, 115, 54, 112, 103, 10, 103, 104, 115, 116, 79, 56, 79, 69, 80, 86, 101, 75, 108, 104, 54, 99, 100, 98, 106, 84, 77, 77, 49, 103, 67, 73, 79, 81, 48, 52, 53, 85, 56, 85, 49, 109, 119, 70, 49, 48, 65, 48, 67, 106, 55, 111, 86, 43, 119, 104, 57, 51, 110, 65, 98, 111, 119, 97, 99, 89, 88, 86, 75, 86, 55, 99, 110, 100, 74, 90, 53, 116, 43, 113, 110, 116, 10, 111, 122, 111, 48, 48, 70, 108, 55, 50, 117, 49, 81, 56, 122, 87, 47, 55, 101, 115, 85, 84, 84, 72, 72, 89, 80, 84, 97, 56, 89, 101, 99, 52, 107, 106, 105, 120, 115, 85, 51, 43, 119, 89, 81, 43, 110, 86, 90, 90, 106, 70, 72, 75, 100, 112, 50, 109, 104, 122, 112, 103, 113, 55, 118, 109, 114, 108, 82, 57, 52, 103, 106, 109, 109, 109, 86, 10, 89, 106, 122, 108, 86, 89, 65, 50, 49, 49, 81, 67, 47, 47, 71, 53, 88, 99, 55, 85, 73, 50, 47, 89, 82, 89, 82, 75, 87, 50, 88, 118, 105, 81, 122, 100, 70, 75, 99, 103, 121, 120, 105, 108, 74, 98, 81, 78, 43, 81, 72, 119, 111, 116, 76, 48, 65, 77, 104, 48, 106, 113, 69, 113, 83, 73, 53, 108, 50, 120, 80, 69, 52, 105, 85, 88, 10, 102, 101, 117, 43, 104, 49, 115, 88, 73, 70, 82, 82, 107, 48, 112, 84, 65, 119, 118, 115, 88, 99, 111, 122, 55, 87, 76, 57, 82, 99, 99, 118, 87, 57, 120, 89, 111, 73, 65, 53, 53, 118, 114, 88, 47, 104, 77, 85, 112, 117, 48, 57, 108, 69, 112, 67, 100, 78, 84, 68, 100, 49, 108, 122, 122, 89, 57, 71, 118, 108, 85, 52, 55, 47, 114, 111, 10, 107, 84, 76, 113, 108, 49, 103, 69, 73, 116, 52, 52, 119, 56, 121, 56, 98, 99, 107, 122, 79, 109, 111, 75, 97, 84, 43, 103, 121, 79, 112, 121, 106, 52, 120, 106, 104, 105, 79, 57, 98, 84, 121, 87, 110, 112, 88, 103, 83, 85, 121, 113, 111, 114, 107, 113, 71, 53, 119, 50, 103, 88, 106, 116, 119, 43, 104, 71, 52, 105, 90, 90, 82, 72, 85, 101, 10, 50, 88, 87, 74, 85, 99, 48, 81, 104, 74, 49, 104, 89, 77, 116, 100, 43, 90, 99, 105, 84, 89, 54, 89, 53, 117, 78, 47, 57, 108, 117, 55, 114, 115, 51, 75, 83, 111, 70, 114, 88, 103, 118, 122, 85, 101, 70, 48, 75, 43, 108, 43, 74, 54, 102, 90, 109, 85, 108, 79, 43, 75, 87, 65, 50, 121, 85, 80, 72, 71, 78, 105, 105, 115, 107, 122, 10, 90, 50, 115, 56, 69, 73, 80, 71, 114, 100, 54, 111, 122, 82, 97, 79, 106, 102, 65, 72, 78, 51, 71, 102, 56, 113, 118, 56, 81, 102, 88, 66, 105, 43, 119, 65, 78, 49, 48, 74, 53, 85, 54, 65, 55, 47, 113, 120, 88, 68, 103, 71, 112, 82, 116, 75, 52, 100, 119, 52, 76, 84, 122, 99, 113, 120, 43, 81, 71, 116, 86, 75, 110, 79, 55, 82, 10, 99, 71, 122, 77, 55, 118, 82, 88, 43, 66, 105, 54, 104, 71, 54, 72, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 73, 100, 101, 110, 84, 114, 117, 115, 116, 32, 80, 117, 98, 108, 105, 99, 32, 83, 101, 99, 116, 111, 114, 32, 82, 111, 111, 116, 32, 67, 65, 32, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 90, 106, 67, 67, 65, 48, 54, 103, 65, 119, 73, 66, 65, 103, 73, 81, 67, 103, 70, 67, 103, 65, 65, 65, 65, 85, 85, 106, 122, 48, 90, 56, 65, 65, 65, 65, 65, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 78, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 83, 77, 66, 65, 71, 65, 49, 85, 69, 67, 104, 77, 74, 83, 87, 82, 108, 98, 108, 82, 121, 100, 88, 78, 48, 77, 83, 111, 119, 75, 65, 89, 68, 86, 81, 81, 68, 69, 121, 70, 74, 90, 71, 86, 117, 86, 72, 74, 49, 99, 51, 81, 103, 85, 72, 86, 105, 98, 71, 108, 106, 73, 70, 78, 108, 89, 51, 82, 118, 10, 99, 105, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 68, 69, 119, 72, 104, 99, 78, 77, 84, 81, 119, 77, 84, 69, 50, 77, 84, 99, 49, 77, 122, 77, 121, 87, 104, 99, 78, 77, 122, 81, 119, 77, 84, 69, 50, 77, 84, 99, 49, 77, 122, 77, 121, 87, 106, 66, 78, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 10, 85, 122, 69, 83, 77, 66, 65, 71, 65, 49, 85, 69, 67, 104, 77, 74, 83, 87, 82, 108, 98, 108, 82, 121, 100, 88, 78, 48, 77, 83, 111, 119, 75, 65, 89, 68, 86, 81, 81, 68, 69, 121, 70, 74, 90, 71, 86, 117, 86, 72, 74, 49, 99, 51, 81, 103, 85, 72, 86, 105, 98, 71, 108, 106, 73, 70, 78, 108, 89, 51, 82, 118, 99, 105, 66, 83, 10, 98, 50, 57, 48, 73, 69, 78, 66, 73, 68, 69, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 50, 73, 112, 84, 56, 112, 69, 105, 118, 54, 69, 100, 114, 67, 118, 115, 110, 100, 117, 84, 121, 10, 80, 52, 111, 55, 101, 107, 111, 115, 77, 83, 113, 77, 106, 98, 67, 112, 119, 122, 70, 114, 113, 72, 100, 50, 104, 67, 97, 50, 114, 73, 70, 67, 68, 81, 106, 114, 86, 86, 105, 55, 101, 118, 105, 56, 90, 88, 51, 121, 111, 71, 50, 76, 113, 69, 102, 112, 89, 110, 89, 101, 69, 101, 52, 73, 70, 78, 71, 121, 82, 66, 98, 48, 54, 116, 68, 54, 10, 72, 105, 57, 101, 50, 56, 116, 122, 81, 97, 54, 56, 65, 76, 66, 75, 75, 48, 67, 121, 114, 79, 69, 55, 83, 56, 73, 116, 110, 101, 83, 104, 109, 43, 119, 97, 79, 104, 55, 119, 67, 76, 80, 81, 53, 67, 81, 49, 66, 53, 43, 99, 116, 77, 108, 83, 98, 100, 115, 72, 121, 111, 43, 49, 87, 47, 67, 68, 56, 48, 47, 72, 76, 97, 88, 73, 10, 114, 99, 117, 86, 73, 75, 81, 120, 75, 70, 100, 89, 87, 117, 83, 78, 71, 53, 113, 114, 110, 103, 48, 77, 56, 103, 111, 122, 79, 83, 73, 53, 67, 112, 99, 117, 56, 49, 78, 51, 117, 85, 82, 70, 47, 89, 84, 76, 78, 105, 67, 66, 87, 83, 50, 97, 98, 50, 49, 73, 83, 71, 72, 75, 84, 78, 57, 84, 48, 97, 57, 83, 118, 69, 83, 102, 10, 113, 121, 57, 114, 103, 51, 76, 118, 100, 89, 68, 97, 66, 106, 77, 98, 88, 99, 106, 97, 89, 56, 90, 78, 122, 97, 120, 109, 77, 99, 51, 82, 51, 106, 54, 72, 69, 68, 98, 104, 117, 97, 82, 54, 55, 50, 66, 81, 115, 115, 118, 75, 112, 108, 98, 103, 78, 54, 43, 114, 78, 66, 77, 53, 74, 101, 103, 53, 90, 117, 83, 89, 101, 113, 111, 83, 10, 109, 74, 120, 90, 90, 111, 89, 43, 114, 102, 71, 119, 121, 106, 52, 71, 68, 51, 118, 119, 69, 85, 115, 51, 111, 69, 82, 116, 101, 56, 117, 111, 106, 72, 72, 48, 49, 98, 87, 82, 78, 115, 122, 119, 70, 99, 89, 114, 51, 108, 69, 88, 115, 90, 100, 77, 85, 68, 50, 120, 108, 86, 108, 56, 66, 88, 48, 116, 73, 100, 85, 65, 118, 119, 70, 110, 10, 111, 108, 53, 55, 112, 108, 122, 121, 57, 121, 76, 120, 107, 65, 50, 84, 50, 54, 112, 69, 85, 87, 98, 77, 102, 88, 89, 68, 54, 50, 113, 111, 75, 106, 103, 90, 108, 51, 89, 78, 97, 52, 112, 104, 43, 98, 122, 50, 55, 110, 98, 57, 99, 67, 118, 100, 75, 84, 122, 52, 67, 104, 53, 98, 81, 104, 121, 76, 86, 105, 57, 86, 71, 120, 121, 104, 10, 76, 114, 88, 72, 70, 117, 98, 52, 113, 106, 121, 83, 106, 109, 109, 50, 65, 99, 71, 49, 104, 112, 50, 74, 68, 119, 115, 52, 108, 70, 84, 111, 54, 116, 121, 101, 80, 83, 87, 56, 85, 121, 98, 116, 49, 97, 115, 53, 113, 115, 86, 65, 84, 70, 83, 114, 115, 114, 84, 90, 50, 102, 106, 88, 99, 116, 115, 99, 118, 71, 50, 57, 90, 86, 47, 118, 10, 105, 68, 85, 113, 90, 105, 47, 117, 57, 114, 78, 108, 56, 68, 79, 78, 102, 74, 104, 66, 97, 85, 89, 80, 81, 120, 120, 112, 43, 112, 117, 49, 48, 71, 70, 113, 122, 99, 112, 76, 50, 85, 121, 81, 82, 113, 115, 86, 87, 97, 70, 72, 86, 67, 107, 117, 103, 121, 104, 102, 72, 77, 75, 105, 113, 51, 73, 88, 65, 65, 97, 79, 82, 101, 121, 76, 10, 52, 106, 77, 57, 102, 57, 111, 90, 82, 79, 82, 105, 99, 115, 80, 102, 73, 115, 98, 121, 86, 116, 84, 100, 88, 53, 86, 121, 55, 87, 49, 102, 57, 48, 103, 68, 87, 47, 51, 70, 75, 113, 68, 50, 99, 121, 79, 69, 69, 66, 115, 66, 53, 119, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 10, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 52, 51, 72, 103, 110, 116, 105, 110, 81, 116, 110, 98, 99, 90, 70, 114, 108, 74, 80, 114, 119, 54, 80, 82, 70, 75, 77, 119, 10, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 73, 66, 65, 69, 102, 54, 51, 81, 113, 119, 69, 90, 69, 52, 114, 85, 49, 100, 57, 43, 85, 79, 108, 49, 81, 90, 103, 107, 105, 72, 86, 73, 121, 113, 90, 74, 110, 89, 87, 118, 54, 73, 65, 99, 86, 89, 112, 90, 109, 120, 73, 49, 81, 106, 10, 116, 50, 111, 100, 73, 70, 102, 108, 65, 87, 74, 66, 70, 57, 77, 74, 50, 51, 88, 76, 98, 108, 83, 81, 100, 102, 52, 97, 110, 52, 69, 75, 119, 116, 51, 88, 57, 119, 110, 81, 87, 51, 73, 86, 53, 66, 52, 74, 97, 106, 48, 122, 56, 121, 71, 97, 53, 104, 86, 43, 114, 86, 72, 86, 68, 82, 68, 116, 102, 85, 76, 65, 106, 43, 55, 65, 10, 109, 103, 106, 86, 81, 100, 90, 99, 68, 105, 70, 112, 98, 111, 66, 104, 68, 104, 88, 65, 117, 77, 47, 70, 83, 82, 74, 83, 122, 76, 52, 54, 122, 78, 81, 117, 79, 65, 88, 101, 78, 102, 48, 102, 98, 55, 105, 65, 97, 74, 103, 57, 84, 97, 68, 75, 81, 71, 88, 83, 99, 51, 122, 49, 105, 57, 107, 75, 108, 84, 47, 89, 80, 121, 78, 116, 10, 71, 116, 69, 113, 74, 66, 110, 90, 104, 98, 77, 88, 55, 51, 104, 117, 113, 86, 106, 82, 73, 57, 80, 72, 69, 43, 49, 121, 74, 88, 57, 100, 115, 88, 78, 119, 48, 72, 56, 71, 108, 119, 109, 69, 75, 89, 66, 104, 72, 102, 112, 101, 47, 51, 79, 115, 111, 79, 79, 74, 117, 66, 120, 120, 70, 99, 98, 101, 77, 88, 56, 83, 51, 79, 70, 116, 10, 109, 54, 47, 110, 54, 74, 57, 49, 101, 69, 121, 114, 82, 106, 117, 97, 122, 114, 56, 70, 71, 70, 49, 78, 70, 84, 119, 87, 109, 104, 108, 81, 66, 74, 113, 121, 109, 109, 57, 108, 105, 49, 74, 102, 80, 70, 103, 69, 75, 67, 88, 65, 90, 109, 69, 120, 102, 114, 110, 103, 100, 98, 107, 97, 113, 73, 72, 87, 99, 104, 101, 122, 120, 81, 77, 120, 10, 78, 82, 70, 52, 101, 75, 76, 103, 54, 84, 67, 77, 102, 52, 68, 102, 87, 78, 56, 56, 117, 105, 101, 87, 52, 111, 65, 48, 98, 101, 79, 89, 48, 50, 81, 110, 114, 69, 104, 43, 75, 72, 100, 99, 120, 105, 86, 104, 74, 102, 105, 70, 68, 71, 88, 54, 120, 68, 73, 118, 112, 90, 103, 70, 53, 80, 103, 76, 90, 120, 89, 87, 120, 111, 75, 52, 10, 77, 104, 110, 53, 43, 98, 108, 53, 51, 66, 47, 78, 54, 54, 43, 114, 68, 116, 48, 98, 50, 48, 88, 107, 101, 117, 99, 67, 52, 112, 86, 100, 47, 71, 110, 119, 85, 50, 108, 104, 108, 88, 86, 53, 67, 49, 53, 86, 53, 106, 103, 99, 108, 75, 108, 90, 77, 53, 55, 73, 99, 88, 82, 53, 102, 49, 71, 74, 116, 115, 104, 113, 117, 68, 68, 73, 10, 97, 106, 106, 68, 98, 112, 55, 104, 78, 120, 98, 113, 66, 87, 74, 77, 87, 120, 74, 72, 55, 97, 101, 48, 115, 49, 104, 87, 120, 48, 110, 122, 102, 120, 74, 111, 67, 84, 70, 120, 56, 71, 51, 52, 84, 107, 102, 55, 49, 111, 88, 117, 120, 86, 104, 65, 71, 97, 81, 100, 112, 47, 108, 76, 81, 122, 102, 99, 97, 70, 112, 80, 122, 43, 118, 67, 10, 90, 72, 84, 101, 116, 66, 88, 90, 57, 70, 82, 85, 71, 105, 56, 99, 49, 53, 100, 120, 86, 74, 67, 79, 50, 83, 67, 100, 85, 121, 116, 47, 113, 52, 47, 105, 54, 106, 67, 56, 85, 68, 102, 118, 56, 85, 101, 49, 102, 88, 119, 115, 66, 79, 120, 111, 110, 98, 82, 74, 82, 66, 68, 48, 99, 107, 115, 99, 90, 79, 102, 56, 53, 109, 117, 81, 10, 51, 87, 108, 57, 97, 102, 48, 65, 86, 113, 87, 51, 114, 76, 97, 116, 116, 56, 111, 43, 65, 101, 43, 99, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 69, 110, 116, 114, 117, 115, 116, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 45, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 80, 106, 67, 67, 65, 121, 97, 103, 65, 119, 73, 66, 65, 103, 73, 69, 83, 108, 79, 77, 75, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 66, 118, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 106, 65, 85, 66, 103, 78, 86, 10, 66, 65, 111, 84, 68, 85, 86, 117, 100, 72, 74, 49, 99, 51, 81, 115, 73, 69, 108, 117, 89, 121, 52, 120, 75, 68, 65, 109, 66, 103, 78, 86, 66, 65, 115, 84, 72, 49, 78, 108, 90, 83, 66, 51, 100, 51, 99, 117, 90, 87, 53, 48, 99, 110, 86, 122, 100, 67, 53, 117, 90, 88, 81, 118, 98, 71, 86, 110, 89, 87, 119, 116, 100, 71, 86, 121, 10, 98, 88, 77, 120, 79, 84, 65, 51, 66, 103, 78, 86, 66, 65, 115, 84, 77, 67, 104, 106, 75, 83, 65, 121, 77, 68, 65, 53, 73, 69, 86, 117, 100, 72, 74, 49, 99, 51, 81, 115, 73, 69, 108, 117, 89, 121, 52, 103, 76, 83, 66, 109, 98, 51, 73, 103, 89, 88, 86, 48, 97, 71, 57, 121, 97, 88, 112, 108, 90, 67, 66, 49, 99, 50, 85, 103, 10, 98, 50, 53, 115, 101, 84, 69, 121, 77, 68, 65, 71, 65, 49, 85, 69, 65, 120, 77, 112, 82, 87, 53, 48, 99, 110, 86, 122, 100, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 73, 67, 48, 103, 82, 122, 73, 119, 10, 72, 104, 99, 78, 77, 68, 107, 119, 78, 122, 65, 51, 77, 84, 99, 121, 78, 84, 85, 48, 87, 104, 99, 78, 77, 122, 65, 120, 77, 106, 65, 51, 77, 84, 99, 49, 78, 84, 85, 48, 87, 106, 67, 66, 118, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 70, 106, 65, 85, 66, 103, 78, 86, 66, 65, 111, 84, 10, 68, 85, 86, 117, 100, 72, 74, 49, 99, 51, 81, 115, 73, 69, 108, 117, 89, 121, 52, 120, 75, 68, 65, 109, 66, 103, 78, 86, 66, 65, 115, 84, 72, 49, 78, 108, 90, 83, 66, 51, 100, 51, 99, 117, 90, 87, 53, 48, 99, 110, 86, 122, 100, 67, 53, 117, 90, 88, 81, 118, 98, 71, 86, 110, 89, 87, 119, 116, 100, 71, 86, 121, 98, 88, 77, 120, 10, 79, 84, 65, 51, 66, 103, 78, 86, 66, 65, 115, 84, 77, 67, 104, 106, 75, 83, 65, 121, 77, 68, 65, 53, 73, 69, 86, 117, 100, 72, 74, 49, 99, 51, 81, 115, 73, 69, 108, 117, 89, 121, 52, 103, 76, 83, 66, 109, 98, 51, 73, 103, 89, 88, 86, 48, 97, 71, 57, 121, 97, 88, 112, 108, 90, 67, 66, 49, 99, 50, 85, 103, 98, 50, 53, 115, 10, 101, 84, 69, 121, 77, 68, 65, 71, 65, 49, 85, 69, 65, 120, 77, 112, 82, 87, 53, 48, 99, 110, 86, 122, 100, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 73, 67, 48, 103, 82, 122, 73, 119, 103, 103, 69, 105, 10, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 54, 104, 76, 90, 121, 50, 53, 52, 77, 97, 43, 75, 90, 54, 84, 65, 66, 112, 51, 98, 113, 77, 114, 105, 86, 81, 82, 114, 74, 50, 109, 70, 79, 87, 72, 76, 80, 10, 47, 118, 97, 67, 101, 98, 57, 122, 89, 81, 89, 75, 112, 83, 102, 89, 115, 49, 47, 84, 82, 85, 52, 99, 99, 116, 90, 79, 77, 118, 74, 121, 105, 103, 47, 51, 103, 120, 110, 81, 97, 111, 67, 65, 65, 69, 85, 101, 115, 77, 102, 110, 109, 114, 56, 83, 86, 121, 99, 99, 111, 50, 103, 118, 67, 111, 101, 57, 97, 109, 115, 79, 88, 109, 88, 122, 10, 72, 72, 102, 86, 49, 73, 87, 78, 99, 67, 71, 48, 115, 122, 76, 110, 105, 54, 76, 86, 104, 106, 107, 67, 115, 98, 106, 83, 82, 56, 55, 107, 121, 85, 110, 69, 79, 54, 102, 101, 43, 49, 82, 57, 86, 55, 55, 119, 54, 71, 55, 67, 101, 98, 73, 54, 67, 49, 88, 105, 85, 74, 103, 87, 77, 104, 78, 99, 76, 51, 104, 87, 119, 99, 75, 85, 10, 115, 47, 74, 97, 53, 67, 101, 97, 110, 121, 84, 88, 120, 117, 122, 81, 109, 121, 87, 67, 52, 56, 122, 67, 120, 69, 88, 70, 106, 74, 100, 54, 66, 109, 115, 113, 69, 90, 43, 112, 67, 109, 53, 73, 79, 50, 47, 98, 49, 66, 69, 90, 81, 118, 101, 80, 66, 55, 47, 49, 85, 49, 43, 99, 80, 118, 81, 88, 76, 79, 90, 112, 114, 69, 52, 121, 10, 84, 71, 74, 51, 54, 114, 102, 111, 53, 98, 115, 48, 118, 66, 109, 76, 114, 112, 120, 82, 53, 55, 100, 43, 116, 86, 79, 120, 77, 121, 76, 108, 98, 99, 57, 119, 80, 66, 114, 54, 52, 112, 116, 110, 116, 111, 80, 48, 106, 97, 87, 118, 89, 107, 120, 78, 52, 70, 105, 115, 90, 68, 81, 83, 65, 47, 105, 50, 106, 90, 82, 106, 74, 75, 82, 120, 10, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 113, 99, 105, 90, 54, 10, 48, 66, 55, 118, 102, 101, 99, 55, 97, 86, 72, 85, 98, 73, 50, 102, 107, 66, 74, 109, 113, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, 67, 65, 81, 69, 65, 101, 90, 56, 100, 108, 115, 97, 50, 101, 84, 56, 105, 106, 89, 102, 84, 104, 119, 77, 69, 89, 71, 112, 114, 109, 105, 53, 90, 10, 105, 88, 77, 82, 114, 69, 80, 82, 57, 82, 80, 47, 106, 84, 107, 114, 119, 80, 75, 57, 84, 51, 67, 77, 113, 83, 47, 113, 70, 56, 81, 76, 86, 74, 55, 85, 71, 53, 97, 89, 77, 122, 121, 111, 114, 87, 75, 105, 65, 72, 97, 114, 87, 87, 108, 117, 66, 104, 49, 43, 120, 76, 108, 69, 106, 90, 105, 118, 69, 116, 82, 104, 50, 119, 111, 90, 10, 82, 107, 102, 122, 54, 47, 100, 106, 119, 85, 65, 70, 81, 75, 88, 83, 116, 47, 83, 49, 109, 106, 97, 47, 113, 89, 104, 50, 105, 65, 82, 86, 66, 67, 117, 99, 104, 51, 56, 97, 78, 122, 120, 43, 76, 97, 85, 97, 50, 78, 83, 74, 88, 115, 113, 57, 114, 68, 49, 115, 50, 71, 50, 118, 49, 102, 78, 50, 68, 56, 48, 55, 105, 68, 103, 105, 10, 110, 87, 121, 84, 109, 115, 81, 57, 118, 52, 73, 98, 90, 84, 43, 109, 68, 49, 50, 113, 47, 79, 87, 121, 70, 99, 113, 49, 114, 99, 97, 56, 80, 100, 67, 69, 54, 79, 111, 71, 99, 114, 66, 78, 79, 84, 74, 52, 118, 122, 52, 82, 110, 65, 117, 107, 110, 90, 111, 104, 56, 47, 67, 98, 67, 122, 66, 52, 50, 56, 72, 99, 104, 48, 80, 43, 10, 118, 71, 79, 97, 121, 115, 88, 67, 72, 77, 110, 72, 106, 102, 56, 55, 69, 108, 103, 73, 53, 114, 89, 57, 55, 72, 111, 115, 84, 118, 117, 68, 108, 115, 52, 77, 80, 71, 109, 72, 86, 72, 79, 107, 99, 56, 75, 84, 47, 49, 69, 81, 114, 66, 86, 85, 65, 100, 106, 56, 66, 98, 71, 74, 111, 88, 57, 48, 103, 53, 112, 74, 49, 57, 120, 79, 10, 101, 52, 112, 73, 98, 52, 116, 70, 57, 103, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 69, 110, 116, 114, 117, 115, 116, 32, 82, 111, 111, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 45, 32, 69, 67, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 43, 84, 67, 67, 65, 111, 67, 103, 65, 119, 73, 66, 65, 103, 73, 78, 65, 75, 97, 76, 101, 83, 107, 65, 65, 65, 65, 65, 85, 78, 67, 82, 43, 84, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 122, 67, 66, 118, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 10, 70, 106, 65, 85, 66, 103, 78, 86, 66, 65, 111, 84, 68, 85, 86, 117, 100, 72, 74, 49, 99, 51, 81, 115, 73, 69, 108, 117, 89, 121, 52, 120, 75, 68, 65, 109, 66, 103, 78, 86, 66, 65, 115, 84, 72, 49, 78, 108, 90, 83, 66, 51, 100, 51, 99, 117, 90, 87, 53, 48, 99, 110, 86, 122, 100, 67, 53, 117, 90, 88, 81, 118, 98, 71, 86, 110, 10, 89, 87, 119, 116, 100, 71, 86, 121, 98, 88, 77, 120, 79, 84, 65, 51, 66, 103, 78, 86, 66, 65, 115, 84, 77, 67, 104, 106, 75, 83, 65, 121, 77, 68, 69, 121, 73, 69, 86, 117, 100, 72, 74, 49, 99, 51, 81, 115, 73, 69, 108, 117, 89, 121, 52, 103, 76, 83, 66, 109, 98, 51, 73, 103, 89, 88, 86, 48, 97, 71, 57, 121, 97, 88, 112, 108, 10, 90, 67, 66, 49, 99, 50, 85, 103, 98, 50, 53, 115, 101, 84, 69, 122, 77, 68, 69, 71, 65, 49, 85, 69, 65, 120, 77, 113, 82, 87, 53, 48, 99, 110, 86, 122, 100, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 10, 73, 67, 48, 103, 82, 85, 77, 120, 77, 66, 52, 88, 68, 84, 69, 121, 77, 84, 73, 120, 79, 68, 69, 49, 77, 106, 85, 122, 78, 108, 111, 88, 68, 84, 77, 51, 77, 84, 73, 120, 79, 68, 69, 49, 78, 84, 85, 122, 78, 108, 111, 119, 103, 98, 56, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 82, 89, 119, 10, 70, 65, 89, 68, 86, 81, 81, 75, 69, 119, 49, 70, 98, 110, 82, 121, 100, 88, 78, 48, 76, 67, 66, 74, 98, 109, 77, 117, 77, 83, 103, 119, 74, 103, 89, 68, 86, 81, 81, 76, 69, 120, 57, 84, 90, 87, 85, 103, 100, 51, 100, 51, 76, 109, 86, 117, 100, 72, 74, 49, 99, 51, 81, 117, 98, 109, 86, 48, 76, 50, 120, 108, 90, 50, 70, 115, 10, 76, 88, 82, 108, 99, 109, 49, 122, 77, 84, 107, 119, 78, 119, 89, 68, 86, 81, 81, 76, 69, 122, 65, 111, 89, 121, 107, 103, 77, 106, 65, 120, 77, 105, 66, 70, 98, 110, 82, 121, 100, 88, 78, 48, 76, 67, 66, 74, 98, 109, 77, 117, 73, 67, 48, 103, 90, 109, 57, 121, 73, 71, 70, 49, 100, 71, 104, 118, 99, 109, 108, 54, 90, 87, 81, 103, 10, 100, 88, 78, 108, 73, 71, 57, 117, 98, 72, 107, 120, 77, 122, 65, 120, 66, 103, 78, 86, 66, 65, 77, 84, 75, 107, 86, 117, 100, 72, 74, 49, 99, 51, 81, 103, 85, 109, 57, 118, 100, 67, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 83, 65, 116, 10, 73, 69, 86, 68, 77, 84, 66, 50, 77, 66, 65, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 66, 83, 117, 66, 66, 65, 65, 105, 65, 50, 73, 65, 66, 73, 81, 84, 121, 100, 67, 54, 98, 85, 70, 55, 52, 109, 122, 81, 54, 49, 86, 102, 90, 103, 73, 97, 74, 80, 82, 98, 105, 87, 108, 72, 52, 55, 106, 67, 102, 102, 72, 121, 10, 65, 115, 87, 102, 111, 80, 90, 98, 49, 89, 115, 71, 71, 89, 90, 80, 85, 120, 66, 116, 66, 121, 81, 110, 111, 97, 68, 52, 49, 85, 99, 90, 89, 85, 120, 57, 121, 112, 77, 110, 54, 110, 81, 77, 55, 50, 43, 87, 67, 102, 53, 106, 55, 72, 66, 100, 78, 113, 49, 110, 100, 54, 55, 74, 110, 88, 120, 86, 82, 68, 113, 105, 89, 49, 69, 102, 10, 57, 101, 78, 105, 49, 75, 108, 72, 66, 122, 55, 77, 73, 75, 78, 67, 77, 69, 65, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 10, 70, 76, 100, 106, 53, 120, 114, 100, 106, 101, 107, 73, 112, 108, 87, 68, 112, 79, 66, 113, 85, 69, 70, 108, 69, 85, 74, 74, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 68, 65, 50, 99, 65, 77, 71, 81, 67, 77, 71, 70, 53, 50, 79, 86, 67, 82, 57, 56, 99, 114, 108, 79, 90, 70, 55, 90, 118, 72, 72, 51, 104, 10, 118, 120, 71, 85, 48, 81, 79, 73, 100, 101, 83, 78, 105, 97, 83, 75, 100, 48, 98, 101, 98, 87, 72, 118, 65, 118, 88, 55, 116, 100, 47, 77, 47, 107, 55, 47, 47, 113, 110, 109, 112, 119, 73, 119, 87, 53, 110, 88, 104, 84, 99, 71, 116, 88, 115, 73, 47, 101, 115, 110, 105, 48, 113, 85, 43, 101, 72, 54, 112, 52, 52, 109, 67, 79, 104, 56, 10, 107, 109, 104, 116, 99, 57, 104, 118, 74, 113, 119, 104, 65, 114, 105, 90, 116, 121, 90, 66, 87, 121, 86, 103, 114, 116, 66, 73, 71, 117, 52, 71, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 70, 67, 65, 32, 69, 86, 32, 82, 79, 79, 84, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 106, 84, 67, 67, 65, 51, 87, 103, 65, 119, 73, 66, 65, 103, 73, 69, 71, 69, 114, 77, 49, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 87, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 68, 84, 106, 69, 119, 77, 67, 52, 71, 65, 49, 85, 69, 10, 67, 103, 119, 110, 81, 50, 104, 112, 98, 109, 69, 103, 82, 109, 108, 117, 89, 87, 53, 106, 97, 87, 70, 115, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 82, 85, 119, 69, 119, 89, 68, 86, 81, 81, 68, 68, 65, 120, 68, 82, 107, 78, 66, 10, 73, 69, 86, 87, 73, 70, 74, 80, 84, 49, 81, 119, 72, 104, 99, 78, 77, 84, 73, 119, 79, 68, 65, 52, 77, 68, 77, 119, 78, 122, 65, 120, 87, 104, 99, 78, 77, 106, 107, 120, 77, 106, 77, 120, 77, 68, 77, 119, 78, 122, 65, 120, 87, 106, 66, 87, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 68, 84, 106, 69, 119, 10, 77, 67, 52, 71, 65, 49, 85, 69, 67, 103, 119, 110, 81, 50, 104, 112, 98, 109, 69, 103, 82, 109, 108, 117, 89, 87, 53, 106, 97, 87, 70, 115, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 82, 85, 119, 69, 119, 89, 68, 86, 81, 81, 68, 10, 68, 65, 120, 68, 82, 107, 78, 66, 73, 69, 86, 87, 73, 70, 74, 80, 84, 49, 81, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 68, 88, 88, 87, 118, 78, 69, 68, 56, 102, 66, 86, 110, 86, 10, 66, 85, 48, 51, 115, 81, 55, 115, 109, 67, 117, 79, 70, 82, 51, 54, 107, 48, 115, 88, 103, 105, 70, 120, 69, 70, 76, 88, 85, 87, 82, 119, 70, 115, 74, 86, 97, 85, 50, 79, 70, 87, 50, 102, 118, 119, 119, 98, 119, 117, 67, 106, 90, 57, 89, 77, 114, 77, 56, 105, 114, 113, 57, 51, 86, 67, 112, 76, 84, 73, 112, 84, 85, 110, 114, 68, 10, 55, 105, 55, 101, 115, 51, 69, 108, 119, 101, 108, 100, 80, 101, 54, 104, 76, 54, 80, 51, 75, 106, 122, 74, 73, 120, 49, 113, 113, 120, 50, 104, 112, 47, 72, 122, 55, 75, 68, 86, 82, 77, 56, 86, 122, 51, 73, 118, 72, 87, 79, 88, 54, 74, 110, 53, 47, 90, 79, 107, 86, 73, 66, 77, 85, 116, 82, 83, 113, 121, 53, 74, 51, 53, 68, 78, 10, 117, 70, 43, 43, 80, 57, 54, 104, 121, 107, 48, 103, 49, 67, 88, 111, 104, 67, 108, 84, 116, 55, 71, 73, 72, 47, 47, 54, 50, 112, 67, 102, 67, 113, 107, 116, 81, 84, 43, 120, 56, 82, 103, 112, 55, 104, 90, 90, 76, 68, 82, 74, 71, 113, 103, 71, 49, 54, 105, 73, 48, 103, 78, 121, 101, 106, 76, 105, 54, 109, 104, 78, 98, 105, 121, 87, 10, 90, 88, 118, 75, 87, 102, 114, 121, 52, 116, 51, 117, 77, 67, 122, 55, 122, 69, 97, 115, 120, 71, 80, 114, 98, 51, 56, 50, 75, 122, 82, 122, 69, 112, 82, 47, 51, 56, 119, 109, 110, 118, 70, 121, 88, 86, 66, 108, 87, 89, 57, 112, 115, 52, 100, 101, 77, 109, 47, 68, 71, 73, 113, 49, 108, 89, 43, 119, 101, 106, 102, 101, 87, 107, 85, 55, 10, 120, 122, 98, 104, 55, 50, 102, 82, 79, 100, 79, 88, 87, 51, 78, 105, 71, 85, 103, 116, 104, 120, 119, 71, 43, 51, 83, 89, 73, 69, 108, 122, 56, 65, 88, 83, 71, 55, 71, 103, 111, 55, 99, 98, 99, 78, 79, 73, 97, 98, 108, 97, 49, 106, 106, 48, 89, 116, 119, 108, 105, 51, 105, 47, 43, 79, 104, 43, 117, 70, 122, 74, 108, 85, 57, 102, 10, 112, 121, 50, 53, 73, 71, 118, 80, 97, 57, 51, 49, 68, 102, 83, 67, 116, 47, 83, 121, 90, 105, 52, 81, 75, 80, 97, 88, 87, 110, 117, 87, 70, 111, 56, 66, 71, 83, 49, 115, 98, 110, 56, 53, 87, 65, 90, 107, 103, 119, 71, 68, 103, 56, 78, 78, 107, 116, 48, 121, 120, 111, 101, 107, 78, 43, 107, 87, 122, 113, 111, 116, 97, 75, 56, 75, 10, 103, 87, 85, 54, 99, 77, 71, 98, 114, 85, 49, 116, 86, 77, 111, 113, 76, 85, 117, 70, 71, 55, 79, 65, 53, 110, 66, 70, 68, 87, 116, 101, 78, 102, 66, 47, 79, 55, 105, 99, 53, 65, 82, 119, 105, 82, 73, 108, 107, 57, 111, 75, 109, 83, 74, 103, 97, 109, 78, 103, 84, 110, 89, 71, 109, 69, 54, 57, 103, 54, 48, 100, 87, 73, 111, 108, 10, 104, 100, 76, 72, 90, 82, 52, 116, 106, 115, 98, 102, 116, 115, 98, 104, 102, 52, 111, 69, 73, 82, 85, 112, 100, 80, 65, 43, 110, 74, 67, 100, 68, 67, 55, 120, 105, 106, 53, 97, 113, 103, 119, 74, 72, 115, 102, 86, 80, 75, 80, 116, 108, 56, 77, 101, 78, 80, 111, 52, 43, 81, 103, 79, 52, 56, 66, 100, 75, 52, 80, 82, 86, 109, 114, 74, 10, 116, 113, 104, 85, 85, 121, 53, 52, 77, 109, 99, 57, 103, 110, 57, 48, 48, 80, 118, 104, 116, 103, 86, 103, 117, 88, 68, 98, 106, 103, 118, 53, 69, 49, 104, 118, 99, 87, 65, 81, 85, 104, 67, 53, 119, 85, 69, 74, 55, 51, 73, 102, 90, 122, 70, 52, 47, 53, 89, 70, 106, 81, 73, 68, 65, 81, 65, 66, 111, 50, 77, 119, 89, 84, 65, 102, 10, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 84, 106, 47, 105, 51, 57, 75, 78, 65, 76, 116, 98, 113, 50, 111, 115, 83, 47, 66, 113, 111, 70, 106, 74, 80, 55, 76, 122, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 10, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 52, 47, 52, 116, 47, 83, 106, 81, 67, 55, 87, 54, 116, 113, 76, 69, 118, 119, 97, 113, 66, 89, 121, 84, 43, 121, 56, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 73, 66, 10, 65, 67, 88, 71, 117, 109, 118, 114, 104, 56, 118, 101, 103, 106, 109, 87, 80, 102, 66, 69, 112, 50, 117, 69, 99, 119, 80, 101, 110, 83, 116, 80, 117, 105, 66, 47, 118, 72, 105, 121, 122, 53, 101, 119, 71, 53, 122, 122, 49, 51, 107, 117, 57, 85, 105, 50, 48, 118, 115, 88, 105, 79, 98, 84, 101, 106, 47, 116, 85, 120, 80, 81, 52, 105, 57, 113, 10, 101, 99, 115, 65, 73, 121, 106, 109, 72, 106, 100, 88, 78, 89, 109, 69, 119, 110, 90, 80, 78, 68, 97, 116, 90, 56, 80, 79, 81, 81, 97, 73, 120, 102, 102, 117, 50, 66, 113, 52, 49, 103, 116, 47, 85, 80, 43, 84, 113, 104, 100, 76, 106, 79, 122, 116, 85, 109, 67, 121, 112, 65, 98, 113, 84, 117, 118, 48, 97, 120, 110, 57, 54, 47, 85, 97, 10, 52, 67, 85, 113, 109, 116, 122, 72, 81, 84, 98, 51, 121, 72, 81, 70, 104, 68, 109, 86, 79, 100, 89, 76, 79, 54, 81, 110, 43, 103, 106, 89, 88, 66, 55, 52, 66, 71, 66, 83, 69, 83, 103, 111, 65, 47, 47, 118, 85, 50, 89, 65, 112, 85, 111, 48, 70, 109, 90, 56, 47, 81, 109, 107, 114, 112, 53, 110, 71, 109, 57, 66, 67, 50, 115, 71, 10, 69, 53, 117, 80, 104, 110, 69, 70, 116, 67, 43, 78, 105, 87, 89, 122, 75, 88, 90, 85, 109, 104, 72, 52, 74, 47, 113, 121, 80, 53, 72, 103, 122, 103, 48, 98, 56, 122, 65, 97, 114, 98, 56, 105, 88, 82, 118, 84, 118, 121, 85, 70, 84, 101, 71, 83, 71, 110, 43, 90, 110, 122, 120, 69, 107, 56, 114, 85, 81, 69, 108, 115, 103, 73, 102, 88, 10, 66, 68, 114, 68, 77, 108, 73, 49, 68, 108, 98, 52, 112, 100, 49, 57, 120, 73, 115, 78, 69, 82, 57, 84, 121, 120, 54, 121, 70, 55, 90, 111, 100, 49, 114, 103, 49, 77, 118, 73, 66, 54, 55, 49, 79, 105, 54, 79, 78, 55, 102, 81, 65, 85, 116, 68, 75, 88, 101, 77, 79, 90, 101, 80, 103, 108, 114, 52, 85, 101, 87, 74, 111, 66, 106, 110, 10, 97, 72, 57, 100, 67, 105, 55, 55, 111, 48, 99, 79, 80, 97, 89, 106, 101, 115, 89, 66, 120, 52, 47, 73, 88, 114, 57, 116, 103, 70, 97, 43, 105, 105, 83, 54, 77, 43, 113, 102, 52, 84, 73, 82, 110, 118, 72, 83, 84, 52, 68, 50, 71, 48, 67, 118, 79, 74, 52, 82, 85, 72, 108, 122, 69, 104, 76, 78, 53, 109, 121, 100, 76, 73, 104, 121, 10, 80, 68, 67, 66, 66, 112, 69, 105, 54, 108, 109, 116, 50, 104, 107, 117, 73, 115, 75, 78, 117, 89, 121, 72, 52, 71, 97, 56, 99, 121, 78, 102, 73, 87, 82, 106, 103, 69, 106, 49, 111, 68, 119, 89, 80, 90, 84, 73, 83, 69, 69, 100, 81, 76, 112, 101, 47, 118, 53, 87, 79, 97, 72, 73, 122, 49, 54, 101, 71, 87, 82, 71, 69, 78, 111, 88, 10, 107, 98, 99, 70, 103, 75, 121, 76, 109, 90, 74, 57, 53, 54, 76, 89, 66, 119, 115, 50, 74, 43, 100, 73, 101, 87, 67, 75, 119, 57, 99, 84, 88, 80, 104, 121, 81, 78, 57, 75, 121, 56, 43, 90, 65, 65, 111, 65, 67, 120, 71, 86, 50, 108, 90, 70, 65, 52, 103, 75, 110, 50, 102, 81, 49, 88, 109, 120, 113, 73, 49, 65, 98, 81, 51, 67, 10, 101, 107, 68, 54, 56, 49, 57, 107, 82, 53, 76, 76, 85, 55, 109, 55, 87, 99, 53, 80, 47, 100, 65, 86, 85, 119, 72, 89, 51, 43, 118, 90, 53, 110, 98, 118, 48, 67, 79, 55, 79, 54, 108, 53, 115, 57, 85, 67, 75, 99, 50, 74, 111, 53, 89, 80, 83, 106, 88, 110, 84, 107, 76, 65, 100, 99, 48, 72, 122, 43, 89, 115, 54, 51, 115, 117, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 84, 195, 156, 82, 75, 84, 82, 85, 83, 84, 32, 69, 108, 101, 107, 116, 114, 111, 110, 105, 107, 32, 83, 101, 114, 116, 105, 102, 105, 107, 97, 32, 72, 105, 122, 109, 101, 116, 32, 83, 97, 196, 159, 108, 97, 121, 196, 177, 99, 196, 177, 115, 196, 177, 32, 72, 53, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 74, 122, 67, 67, 65, 119, 43, 103, 65, 119, 73, 66, 65, 103, 73, 72, 65, 73, 52, 88, 47, 105, 81, 103, 103, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 66, 115, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 70, 73, 120, 68, 122, 65, 78, 10, 66, 103, 78, 86, 66, 65, 99, 77, 66, 107, 70, 117, 97, 50, 70, 121, 89, 84, 70, 78, 77, 69, 115, 71, 65, 49, 85, 69, 67, 103, 120, 69, 86, 77, 79, 99, 85, 107, 116, 85, 85, 108, 86, 84, 86, 67, 66, 67, 97, 87, 120, 110, 97, 83, 68, 69, 115, 71, 120, 108, 100, 71, 110, 70, 110, 50, 108, 116, 73, 72, 90, 108, 73, 69, 74, 112, 10, 98, 71, 110, 70, 110, 50, 108, 116, 73, 69, 102, 68, 118, 72, 90, 108, 98, 109, 120, 112, 120, 74, 57, 112, 73, 69, 104, 112, 101, 109, 49, 108, 100, 71, 120, 108, 99, 109, 107, 103, 81, 83, 55, 70, 110, 105, 52, 120, 81, 106, 66, 65, 66, 103, 78, 86, 66, 65, 77, 77, 79, 86, 84, 68, 110, 70, 74, 76, 86, 70, 74, 86, 85, 49, 81, 103, 10, 82, 87, 120, 108, 97, 51, 82, 121, 98, 50, 53, 112, 97, 121, 66, 84, 90, 88, 74, 48, 97, 87, 90, 112, 97, 50, 69, 103, 83, 71, 108, 54, 98, 87, 86, 48, 73, 70, 78, 104, 120, 74, 57, 115, 89, 88, 110, 69, 115, 87, 80, 69, 115, 88, 80, 69, 115, 83, 66, 73, 78, 84, 65, 101, 70, 119, 48, 120, 77, 122, 65, 48, 77, 122, 65, 119, 10, 79, 68, 65, 51, 77, 68, 70, 97, 70, 119, 48, 121, 77, 122, 65, 48, 77, 106, 103, 119, 79, 68, 65, 51, 77, 68, 70, 97, 77, 73, 71, 120, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 85, 85, 106, 69, 80, 77, 65, 48, 71, 65, 49, 85, 69, 66, 119, 119, 71, 81, 87, 53, 114, 89, 88, 74, 104, 77, 85, 48, 119, 10, 83, 119, 89, 68, 86, 81, 81, 75, 68, 69, 82, 85, 119, 53, 120, 83, 83, 49, 82, 83, 86, 86, 78, 85, 73, 69, 74, 112, 98, 71, 100, 112, 73, 77, 83, 119, 98, 71, 86, 48, 97, 99, 87, 102, 97, 87, 48, 103, 100, 109, 85, 103, 81, 109, 108, 115, 97, 99, 87, 102, 97, 87, 48, 103, 82, 56, 79, 56, 100, 109, 86, 117, 98, 71, 110, 69, 10, 110, 50, 107, 103, 83, 71, 108, 54, 98, 87, 86, 48, 98, 71, 86, 121, 97, 83, 66, 66, 76, 115, 87, 101, 76, 106, 70, 67, 77, 69, 65, 71, 65, 49, 85, 69, 65, 119, 119, 53, 86, 77, 79, 99, 85, 107, 116, 85, 85, 108, 86, 84, 86, 67, 66, 70, 98, 71, 86, 114, 100, 72, 74, 118, 98, 109, 108, 114, 73, 70, 78, 108, 99, 110, 82, 112, 10, 90, 109, 108, 114, 89, 83, 66, 73, 97, 88, 112, 116, 90, 88, 81, 103, 85, 50, 72, 69, 110, 50, 120, 104, 101, 99, 83, 120, 89, 56, 83, 120, 99, 56, 83, 120, 73, 69, 103, 49, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 10, 67, 103, 75, 67, 65, 81, 69, 65, 112, 67, 85, 90, 52, 87, 87, 101, 54, 48, 103, 104, 85, 69, 111, 73, 53, 82, 72, 119, 87, 114, 111, 109, 47, 52, 78, 90, 122, 107, 81, 113, 76, 47, 55, 104, 122, 109, 65, 68, 47, 73, 48, 68, 112, 101, 51, 47, 97, 54, 105, 54, 122, 68, 81, 71, 110, 49, 107, 49, 57, 117, 119, 115, 117, 53, 51, 55, 10, 106, 86, 74, 112, 52, 53, 119, 110, 69, 70, 80, 122, 112, 65, 76, 70, 112, 47, 107, 82, 71, 109, 108, 49, 98, 115, 77, 100, 105, 57, 71, 89, 106, 90, 79, 72, 112, 51, 71, 88, 68, 83, 72, 72, 109, 102, 108, 83, 48, 121, 120, 106, 88, 86, 87, 56, 54, 66, 56, 66, 83, 76, 108, 103, 47, 107, 74, 75, 57, 115, 105, 65, 114, 115, 49, 109, 10, 101, 112, 53, 70, 105, 109, 104, 51, 52, 107, 104, 111, 110, 54, 76, 97, 56, 101, 72, 66, 69, 74, 47, 114, 80, 67, 109, 66, 112, 43, 69, 121, 67, 78, 83, 103, 66, 98, 71, 77, 43, 52, 50, 87, 65, 65, 52, 43, 74, 100, 57, 84, 104, 105, 73, 55, 47, 80, 83, 57, 56, 119, 108, 43, 100, 43, 121, 71, 54, 119, 56, 122, 53, 85, 78, 80, 10, 57, 70, 82, 49, 98, 83, 109, 90, 76, 109, 90, 97, 81, 57, 47, 76, 88, 77, 114, 73, 53, 84, 106, 120, 102, 106, 115, 49, 110, 81, 47, 48, 120, 86, 113, 104, 122, 80, 77, 103, 103, 67, 84, 84, 86, 43, 119, 86, 117, 110, 85, 108, 109, 43, 104, 107, 83, 55, 77, 48, 104, 79, 56, 69, 117, 80, 98, 74, 98, 75, 111, 67, 80, 114, 90, 86, 10, 52, 106, 73, 51, 88, 47, 120, 109, 108, 49, 47, 78, 49, 112, 55, 72, 73, 76, 57, 78, 120, 113, 119, 47, 100, 86, 56, 99, 55, 84, 75, 99, 102, 71, 107, 65, 97, 90, 72, 106, 73, 120, 104, 84, 54, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 86, 112, 107, 72, 10, 72, 116, 79, 115, 68, 71, 108, 107, 116, 65, 120, 81, 82, 57, 53, 68, 76, 76, 52, 103, 119, 80, 115, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 69, 66, 65, 74, 53, 70, 100, 110, 115, 88, 83, 68, 76, 121, 79, 73, 115, 112, 118, 101, 54, 87, 83, 107, 54, 66, 71, 76, 70, 82, 82, 121, 68, 78, 48, 71, 83, 120, 68, 115, 110, 90, 65, 100, 107, 74, 122, 115, 105, 90, 51, 71, 103, 108, 69, 57, 82, 99, 56, 113, 80, 111, 10, 66, 80, 53, 121, 67, 99, 99, 76, 113, 104, 48, 108, 86, 88, 54, 87, 109, 108, 101, 51, 117, 115, 85, 82, 101, 104, 110, 109, 112, 51, 52, 57, 104, 81, 55, 49, 43, 83, 52, 112, 76, 43, 102, 53, 98, 70, 103, 87, 86, 49, 65, 108, 57, 106, 52, 117, 80, 113, 114, 116, 100, 51, 71, 113, 113, 112, 109, 87, 82, 103, 113, 117, 106, 117, 119, 113, 10, 85, 82, 97, 119, 88, 115, 51, 113, 90, 119, 81, 99, 87, 68, 68, 49, 89, 73, 113, 57, 112, 114, 49, 78, 53, 90, 97, 48, 47, 69, 75, 74, 65, 87, 118, 50, 99, 77, 104, 81, 79, 81, 119, 116, 49, 87, 98, 90, 121, 78, 75, 122, 77, 114, 99, 98, 71, 87, 51, 76, 77, 47, 110, 102, 112, 101, 89, 86, 104, 68, 102, 119, 119, 118, 74, 108, 10, 108, 112, 75, 81, 100, 47, 67, 116, 57, 74, 68, 112, 69, 88, 106, 88, 107, 52, 110, 65, 80, 81, 117, 54, 75, 102, 84, 111, 109, 90, 49, 121, 106, 117, 50, 100, 76, 43, 54, 83, 102, 97, 72, 120, 47, 49, 50, 54, 77, 50, 67, 70, 89, 118, 52, 72, 65, 113, 71, 69, 86, 107, 97, 43, 108, 103, 113, 97, 69, 57, 99, 104, 84, 76, 100, 56, 10, 66, 53, 57, 79, 84, 106, 43, 82, 100, 80, 115, 110, 110, 82, 72, 77, 51, 101, 97, 120, 121, 110, 70, 78, 69, 120, 99, 53, 74, 115, 85, 112, 73, 83, 117, 84, 75, 87, 113, 87, 43, 113, 116, 66, 52, 85, 117, 50, 78, 81, 118, 65, 109, 120, 85, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 101, 114, 116, 105, 110, 111, 109, 105, 115, 32, 45, 32, 82, 111, 111, 116, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 107, 106, 67, 67, 65, 51, 113, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 97, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 71, 85, 106, 69, 84, 77, 66, 69, 71, 65, 49, 85, 69, 67, 104, 77, 75, 10, 81, 50, 86, 121, 100, 71, 108, 117, 98, 50, 49, 112, 99, 122, 69, 88, 77, 66, 85, 71, 65, 49, 85, 69, 67, 120, 77, 79, 77, 68, 65, 119, 77, 105, 65, 48, 77, 122, 77, 53, 79, 84, 103, 53, 77, 68, 77, 120, 72, 84, 65, 98, 66, 103, 78, 86, 66, 65, 77, 84, 70, 69, 78, 108, 99, 110, 82, 112, 98, 109, 57, 116, 97, 88, 77, 103, 10, 76, 83, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 66, 52, 88, 68, 84, 69, 122, 77, 84, 65, 121, 77, 84, 65, 53, 77, 84, 99, 120, 79, 70, 111, 88, 68, 84, 77, 122, 77, 84, 65, 121, 77, 84, 65, 53, 77, 84, 99, 120, 79, 70, 111, 119, 87, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 108, 73, 120, 10, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 111, 84, 67, 107, 78, 108, 99, 110, 82, 112, 98, 109, 57, 116, 97, 88, 77, 120, 70, 122, 65, 86, 66, 103, 78, 86, 66, 65, 115, 84, 68, 106, 65, 119, 77, 68, 73, 103, 78, 68, 77, 122, 79, 84, 107, 52, 79, 84, 65, 122, 77, 82, 48, 119, 71, 119, 89, 68, 86, 81, 81, 68, 69, 120, 82, 68, 10, 90, 88, 74, 48, 97, 87, 53, 118, 98, 87, 108, 122, 73, 67, 48, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 84, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 78, 84, 77, 67, 81, 111, 115, 10, 80, 53, 76, 50, 102, 120, 83, 101, 67, 53, 121, 97, 97, 104, 49, 65, 77, 71, 84, 57, 113, 116, 56, 79, 72, 103, 90, 98, 110, 49, 67, 70, 54, 115, 50, 78, 113, 48, 78, 110, 51, 114, 68, 54, 102, 111, 67, 87, 110, 111, 82, 52, 107, 107, 106, 87, 52, 122, 110, 117, 122, 117, 82, 90, 87, 74, 102, 108, 76, 105, 101, 89, 54, 112, 79, 111, 10, 100, 53, 116, 75, 56, 79, 57, 48, 103, 67, 51, 114, 77, 66, 43, 49, 50, 99, 101, 65, 110, 71, 73, 110, 107, 89, 106, 119, 83, 111, 110, 100, 51, 73, 106, 109, 70, 80, 110, 86, 65, 121, 47, 47, 108, 100, 117, 57, 110, 43, 119, 115, 43, 104, 81, 86, 87, 90, 85, 75, 120, 107, 100, 56, 97, 82, 105, 53, 112, 119, 80, 53, 121, 110, 97, 112, 10, 122, 56, 100, 118, 116, 70, 52, 70, 47, 117, 55, 66, 85, 114, 74, 49, 77, 111, 102, 115, 55, 83, 108, 109, 79, 47, 78, 75, 70, 111, 76, 50, 49, 112, 114, 98, 99, 112, 106, 112, 51, 118, 68, 70, 84, 75, 87, 114, 116, 101, 111, 66, 52, 111, 119, 117, 90, 72, 57, 107, 98, 47, 50, 106, 74, 90, 79, 76, 121, 75, 73, 79, 83, 89, 48, 48, 10, 56, 66, 47, 115, 87, 69, 85, 117, 78, 75, 113, 69, 85, 76, 51, 110, 115, 107, 111, 84, 117, 76, 65, 80, 114, 106, 104, 100, 115, 75, 107, 98, 53, 110, 80, 74, 87, 113, 72, 90, 90, 107, 67, 113, 113, 85, 50, 109, 78, 65, 75, 116, 104, 72, 54, 121, 73, 56, 72, 55, 75, 115, 90, 110, 57, 68, 83, 50, 115, 74, 86, 113, 77, 48, 57, 120, 10, 82, 76, 87, 116, 119, 72, 107, 122, 105, 79, 67, 47, 55, 97, 79, 103, 70, 76, 83, 99, 67, 98, 65, 75, 52, 50, 67, 43, 43, 80, 104, 109, 105, 77, 49, 98, 56, 88, 99, 70, 52, 76, 86, 122, 98, 115, 70, 57, 82, 105, 54, 79, 83, 121, 101, 109, 122, 84, 85, 75, 47, 101, 86, 78, 102, 97, 111, 113, 111, 121, 110, 72, 87, 109, 103, 69, 10, 54, 79, 88, 87, 107, 54, 82, 105, 119, 115, 88, 109, 57, 69, 47, 71, 43, 90, 56, 97, 106, 89, 74, 74, 71, 89, 114, 75, 87, 85, 77, 54, 54, 65, 48, 121, 119, 102, 82, 77, 69, 119, 78, 118, 98, 113, 89, 47, 107, 88, 80, 76, 121, 110, 78, 118, 69, 105, 67, 76, 55, 115, 67, 67, 101, 78, 53, 76, 76, 115, 74, 74, 119, 120, 51, 116, 10, 70, 118, 89, 107, 57, 67, 99, 98, 88, 70, 99, 120, 51, 70, 88, 117, 113, 66, 53, 118, 98, 75, 122, 105, 82, 99, 120, 88, 86, 52, 112, 49, 86, 120, 110, 103, 116, 86, 105, 90, 83, 84, 89, 120, 80, 68, 77, 66, 98, 82, 90, 75, 122, 98, 103, 113, 103, 52, 83, 71, 109, 47, 108, 103, 48, 104, 57, 116, 107, 81, 80, 84, 89, 75, 98, 86, 10, 80, 90, 114, 100, 100, 53, 65, 57, 78, 97, 83, 102, 68, 49, 55, 49, 85, 107, 82, 112, 117, 99, 67, 54, 51, 77, 57, 57, 51, 51, 122, 90, 120, 75, 121, 71, 73, 106, 75, 56, 101, 50, 117, 82, 55, 51, 114, 52, 70, 50, 105, 119, 52, 108, 78, 86, 89, 67, 50, 118, 80, 115, 75, 68, 50, 78, 107, 74, 75, 47, 68, 65, 90, 78, 117, 72, 10, 105, 53, 72, 77, 107, 101, 115, 69, 47, 88, 97, 48, 108, 90, 114, 109, 70, 65, 89, 98, 49, 84, 81, 100, 118, 116, 106, 47, 100, 66, 120, 84, 104, 90, 110, 103, 87, 86, 74, 75, 89, 101, 50, 73, 110, 109, 116, 74, 105, 85, 90, 43, 73, 70, 114, 90, 53, 48, 114, 108, 97, 117, 55, 83, 90, 82, 70, 68, 65, 103, 77, 66, 65, 65, 71, 106, 10, 89, 122, 66, 104, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 84, 118, 107, 85, 122, 49, 112, 99, 77, 119, 54, 67, 56, 73, 10, 54, 116, 78, 120, 73, 113, 83, 83, 97, 72, 104, 48, 50, 84, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 84, 118, 107, 85, 122, 49, 112, 99, 77, 119, 54, 67, 56, 73, 54, 116, 78, 120, 73, 113, 83, 83, 97, 72, 104, 48, 50, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 10, 65, 65, 79, 67, 65, 103, 69, 65, 102, 106, 49, 85, 50, 105, 74, 100, 71, 108, 103, 43, 79, 49, 81, 110, 117, 114, 114, 77, 121, 79, 77, 97, 97, 117, 111, 43, 43, 82, 76, 114, 86, 108, 56, 57, 85, 77, 55, 103, 54, 107, 103, 109, 74, 115, 57, 53, 86, 110, 54, 82, 72, 74, 107, 47, 48, 75, 71, 82, 72, 67, 119, 80, 84, 53, 105, 86, 10, 87, 86, 79, 57, 48, 67, 76, 89, 105, 70, 50, 99, 78, 47, 122, 55, 90, 77, 70, 52, 106, 73, 117, 97, 89, 65, 110, 113, 49, 102, 111, 104, 88, 57, 66, 48, 90, 101, 100, 81, 120, 98, 56, 117, 117, 81, 115, 76, 114, 98, 87, 119, 70, 54, 89, 83, 106, 78, 82, 105, 101, 79, 112, 87, 97, 117, 119, 75, 48, 107, 68, 68, 80, 65, 85, 119, 10, 80, 107, 50, 85, 116, 53, 57, 75, 65, 57, 78, 57, 74, 48, 117, 50, 47, 107, 84, 79, 43, 104, 107, 122, 71, 109, 50, 107, 81, 116, 72, 100, 122, 77, 106, 73, 49, 120, 90, 83, 103, 48, 56, 49, 108, 76, 77, 83, 86, 88, 51, 108, 52, 107, 76, 114, 53, 74, 121, 84, 67, 99, 66, 77, 87, 119, 101, 114, 120, 50, 48, 82, 111, 70, 65, 88, 10, 108, 67, 79, 111, 116, 81, 113, 83, 68, 55, 74, 54, 119, 87, 65, 115, 79, 77, 119, 97, 112, 108, 118, 47, 56, 103, 122, 106, 113, 104, 56, 99, 51, 76, 105, 103, 107, 121, 102, 101, 89, 43, 78, 47, 73, 90, 56, 54, 53, 90, 55, 54, 52, 66, 78, 113, 100, 101, 117, 87, 88, 71, 75, 82, 108, 73, 53, 110, 85, 55, 97, 74, 43, 66, 73, 74, 10, 121, 50, 57, 83, 87, 119, 78, 121, 104, 108, 67, 86, 67, 78, 83, 78, 104, 52, 89, 86, 72, 53, 85, 107, 50, 75, 82, 118, 109, 115, 54, 107, 110, 90, 116, 116, 48, 114, 74, 50, 66, 111, 98, 71, 86, 103, 106, 70, 54, 119, 110, 97, 78, 115, 73, 98, 87, 48, 71, 43, 89, 83, 114, 106, 99, 79, 97, 52, 112, 118, 105, 50, 87, 115, 83, 57, 10, 73, 102, 102, 47, 113, 108, 43, 104, 98, 72, 89, 53, 90, 116, 98, 113, 84, 70, 88, 104, 65, 68, 79, 98, 69, 53, 104, 106, 121, 87, 47, 81, 65, 83, 65, 74, 78, 49, 76, 110, 68, 69, 56, 43, 122, 98, 122, 49, 88, 53, 89, 110, 112, 121, 65, 67, 108, 101, 65, 117, 54, 65, 100, 66, 66, 82, 56, 86, 98, 116, 97, 119, 53, 66, 110, 103, 10, 68, 119, 75, 84, 65, 67, 100, 121, 120, 89, 118, 82, 86, 66, 57, 100, 83, 115, 78, 65, 108, 51, 53, 86, 112, 110, 122, 66, 77, 119, 81, 85, 65, 82, 49, 74, 73, 71, 107, 76, 71, 90, 79, 100, 98, 108, 103, 105, 57, 48, 65, 77, 82, 103, 119, 106, 89, 47, 77, 53, 48, 110, 57, 50, 85, 97, 102, 48, 121, 75, 72, 120, 68, 72, 89, 105, 10, 73, 48, 90, 83, 75, 83, 51, 105, 111, 48, 69, 72, 86, 109, 109, 89, 48, 103, 85, 74, 118, 71, 110, 72, 87, 109, 72, 78, 106, 52, 70, 103, 70, 85, 50, 65, 51, 90, 68, 105, 102, 99, 82, 81, 56, 111, 119, 55, 98, 107, 114, 72, 120, 117, 97, 65, 75, 122, 121, 66, 118, 66, 71, 65, 70, 104, 65, 110, 49, 47, 68, 78, 80, 51, 110, 77, 10, 99, 121, 114, 68, 102, 108, 79, 82, 49, 109, 55, 52, 57, 102, 80, 72, 48, 70, 70, 78, 106, 107, 117, 108, 87, 43, 89, 90, 70, 122, 118, 87, 103, 81, 110, 99, 73, 116, 122, 117, 106, 114, 110, 69, 106, 49, 80, 104, 90, 55, 115, 122, 117, 73, 103, 86, 82, 115, 47, 116, 97, 84, 88, 47, 100, 81, 49, 71, 56, 56, 53, 120, 52, 99, 86, 114, 10, 104, 107, 73, 71, 117, 85, 69, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 79, 73, 83, 84, 69, 32, 87, 73, 83, 101, 75, 101, 121, 32, 71, 108, 111, 98, 97, 108, 32, 82, 111, 111, 116, 32, 71, 66, 32, 67, 65, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 116, 84, 67, 67, 65, 112, 50, 103, 65, 119, 73, 66, 65, 103, 73, 81, 100, 114, 69, 103, 85, 110, 84, 119, 104, 89, 100, 71, 115, 47, 103, 106, 71, 118, 98, 67, 119, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 116, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 68, 83, 68, 69, 81, 77, 65, 52, 71, 65, 49, 85, 69, 67, 104, 77, 72, 86, 48, 108, 84, 90, 85, 116, 108, 101, 84, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 67, 120, 77, 90, 84, 48, 108, 84, 86, 69, 85, 103, 82, 109, 57, 49, 98, 109, 82, 104, 100, 71, 108, 118, 98, 105, 66, 70, 98, 109, 82, 118, 99, 110, 78, 108, 10, 90, 68, 69, 111, 77, 67, 89, 71, 65, 49, 85, 69, 65, 120, 77, 102, 84, 48, 108, 84, 86, 69, 85, 103, 86, 48, 108, 84, 90, 85, 116, 108, 101, 83, 66, 72, 98, 71, 57, 105, 89, 87, 119, 103, 85, 109, 57, 118, 100, 67, 66, 72, 81, 105, 66, 68, 81, 84, 65, 101, 70, 119, 48, 120, 78, 68, 69, 121, 77, 68, 69, 120, 78, 84, 65, 119, 10, 77, 122, 74, 97, 70, 119, 48, 122, 79, 84, 69, 121, 77, 68, 69, 120, 78, 84, 69, 119, 77, 122, 70, 97, 77, 71, 48, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 78, 73, 77, 82, 65, 119, 68, 103, 89, 68, 86, 81, 81, 75, 69, 119, 100, 88, 83, 86, 78, 108, 83, 50, 86, 53, 77, 83, 73, 119, 73, 65, 89, 68, 10, 86, 81, 81, 76, 69, 120, 108, 80, 83, 86, 78, 85, 82, 83, 66, 71, 98, 51, 86, 117, 90, 71, 70, 48, 97, 87, 57, 117, 73, 69, 86, 117, 90, 71, 57, 121, 99, 50, 86, 107, 77, 83, 103, 119, 74, 103, 89, 68, 86, 81, 81, 68, 69, 120, 57, 80, 83, 86, 78, 85, 82, 83, 66, 88, 83, 86, 78, 108, 83, 50, 86, 53, 73, 69, 100, 115, 10, 98, 50, 74, 104, 98, 67, 66, 83, 98, 50, 57, 48, 73, 69, 100, 67, 73, 69, 78, 66, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 50, 66, 101, 51, 72, 69, 111, 107, 75, 116, 97, 88, 10, 115, 99, 114, 105, 72, 118, 116, 57, 79, 79, 43, 89, 57, 98, 73, 53, 109, 69, 52, 110, 117, 66, 70, 100, 101, 57, 73, 108, 108, 73, 105, 67, 70, 83, 90, 113, 71, 122, 71, 55, 113, 70, 115, 104, 73, 83, 118, 89, 68, 48, 54, 102, 87, 118, 71, 120, 87, 117, 82, 53, 49, 106, 73, 106, 75, 43, 70, 84, 122, 74, 108, 70, 88, 72, 116, 80, 10, 114, 98, 121, 47, 104, 48, 111, 76, 83, 53, 100, 97, 113, 80, 90, 73, 55, 72, 49, 55, 68, 99, 48, 104, 66, 116, 43, 101, 70, 102, 49, 66, 105, 107, 105, 51, 73, 80, 83, 104, 101, 104, 116, 88, 49, 70, 49, 81, 47, 55, 112, 110, 50, 67, 79, 90, 72, 56, 103, 47, 52, 57, 55, 47, 98, 49, 116, 51, 115, 87, 116, 117, 117, 77, 108, 107, 10, 57, 43, 72, 75, 81, 85, 89, 79, 75, 88, 72, 81, 117, 83, 80, 56, 121, 89, 70, 102, 84, 118, 100, 118, 51, 55, 43, 69, 114, 88, 78, 107, 117, 55, 100, 67, 106, 109, 110, 50, 49, 72, 89, 100, 102, 112, 50, 110, 117, 70, 101, 75, 85, 87, 100, 121, 49, 57, 83, 111, 117, 74, 86, 85, 81, 72, 77, 68, 57, 117, 114, 48, 54, 47, 52, 111, 10, 81, 110, 99, 47, 110, 83, 77, 98, 115, 114, 89, 57, 103, 66, 81, 72, 84, 67, 53, 80, 57, 57, 85, 75, 70, 103, 50, 57, 90, 107, 77, 51, 102, 105, 78, 68, 101, 99, 78, 65, 104, 118, 86, 77, 75, 100, 113, 79, 109, 113, 48, 78, 112, 81, 83, 72, 105, 66, 54, 70, 52, 43, 108, 84, 49, 90, 118, 73, 105, 119, 78, 106, 101, 79, 118, 103, 10, 71, 85, 112, 117, 117, 121, 57, 114, 77, 50, 82, 89, 107, 54, 49, 112, 118, 52, 56, 98, 55, 52, 74, 73, 120, 119, 73, 68, 65, 81, 65, 66, 111, 49, 69, 119, 84, 122, 65, 76, 66, 103, 78, 86, 72, 81, 56, 69, 66, 65, 77, 67, 65, 89, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 10, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 78, 81, 47, 73, 78, 109, 78, 101, 52, 113, 80, 115, 43, 84, 116, 109, 70, 99, 53, 82, 85, 117, 79, 82, 109, 106, 48, 119, 69, 65, 89, 74, 75, 119, 89, 66, 66, 65, 71, 67, 78, 120, 85, 66, 66, 65, 77, 67, 65, 81, 65, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 69, 66, 65, 69, 66, 77, 43, 52, 101, 121, 109, 89, 71, 81, 102, 112, 51, 70, 115, 76, 65, 109, 122, 89, 104, 55, 75, 122, 75, 78, 98, 114, 103, 104, 99, 86, 105, 88, 102, 97, 52, 51, 70, 75, 56, 43, 53, 47, 101, 97, 52, 110, 51, 50, 99, 90, 105, 90, 66, 75, 112, 68, 10, 100, 72, 105, 106, 52, 48, 108, 104, 80, 110, 79, 77, 84, 90, 84, 103, 43, 88, 72, 69, 116, 104, 89, 79, 85, 51, 103, 102, 49, 113, 75, 72, 76, 119, 73, 53, 103, 83, 107, 56, 114, 120, 87, 89, 73, 84, 68, 43, 75, 74, 65, 65, 106, 78, 72, 104, 121, 47, 112, 101, 121, 80, 51, 52, 69, 69, 89, 55, 111, 110, 104, 67, 107, 82, 100, 48, 10, 86, 81, 114, 101, 85, 71, 100, 78, 90, 116, 71, 110, 47, 47, 51, 90, 119, 76, 87, 111, 111, 52, 114, 79, 90, 118, 85, 80, 81, 56, 50, 110, 75, 49, 100, 55, 89, 48, 90, 113, 113, 105, 53, 83, 50, 80, 84, 116, 52, 87, 50, 116, 75, 90, 66, 52, 83, 76, 114, 104, 73, 54, 113, 106, 105, 101, 121, 49, 113, 53, 98, 65, 116, 69, 117, 105, 10, 72, 90, 101, 101, 101, 118, 74, 117, 81, 72, 72, 102, 97, 80, 70, 108, 84, 99, 53, 56, 66, 100, 57, 84, 90, 97, 109, 108, 56, 76, 71, 88, 66, 72, 65, 86, 82, 103, 79, 89, 49, 78, 75, 47, 86, 76, 83, 103, 87, 72, 49, 83, 98, 57, 112, 87, 74, 109, 76, 85, 50, 78, 117, 74, 77, 87, 56, 99, 56, 67, 76, 67, 48, 50, 73, 99, 10, 78, 99, 49, 77, 97, 82, 86, 85, 71, 112, 67, 89, 51, 117, 115, 101, 88, 56, 112, 51, 120, 56, 117, 79, 80, 85, 78, 112, 110, 74, 112, 89, 48, 67, 81, 55, 51, 120, 116, 65, 108, 110, 52, 49, 114, 89, 72, 72, 84, 110, 71, 54, 105, 66, 77, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 111, 102, 32, 87, 111, 83, 105, 103, 110, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 102, 68, 67, 67, 65, 109, 83, 103, 65, 119, 73, 66, 65, 103, 73, 81, 97, 121, 88, 97, 105, 111, 105, 100, 102, 76, 119, 80, 66, 98, 79, 120, 101, 109, 70, 70, 82, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 66, 89, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 68, 84, 106, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 104, 77, 82, 86, 50, 57, 84, 97, 87, 100, 117, 73, 69, 78, 66, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 76, 84, 65, 114, 66, 103, 78, 86, 66, 65, 77, 84, 74, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 10, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 73, 71, 57, 109, 73, 70, 100, 118, 85, 50, 108, 110, 98, 105, 66, 72, 77, 106, 65, 101, 70, 119, 48, 120, 78, 68, 69, 120, 77, 68, 103, 119, 77, 68, 85, 52, 78, 84, 104, 97, 70, 119, 48, 48, 78, 68, 69, 120, 77, 68, 103, 119, 77, 68, 85, 52, 78, 84, 104, 97, 77, 70, 103, 120, 10, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 78, 79, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 69, 120, 70, 88, 98, 49, 78, 112, 90, 50, 52, 103, 81, 48, 69, 103, 84, 71, 108, 116, 97, 88, 82, 108, 90, 68, 69, 116, 77, 67, 115, 71, 65, 49, 85, 69, 65, 120, 77, 107, 81, 50, 86, 121, 100, 71, 108, 109, 10, 97, 87, 78, 104, 100, 71, 108, 118, 98, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 103, 98, 50, 89, 103, 86, 50, 57, 84, 97, 87, 100, 117, 73, 69, 99, 121, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 10, 67, 103, 75, 67, 65, 81, 69, 65, 118, 115, 88, 69, 111, 67, 75, 65, 83, 85, 43, 47, 50, 89, 99, 82, 120, 108, 80, 104, 117, 119, 43, 57, 89, 72, 43, 118, 57, 111, 73, 79, 72, 57, 121, 119, 106, 106, 50, 88, 52, 70, 65, 56, 106, 122, 114, 118, 90, 106, 116, 70, 66, 53, 115, 103, 43, 79, 80, 88, 74, 89, 89, 49, 107, 66, 97, 105, 10, 88, 87, 56, 119, 71, 81, 105, 72, 67, 51, 56, 71, 115, 112, 49, 105, 106, 57, 54, 118, 107, 113, 86, 103, 49, 67, 117, 65, 109, 108, 73, 47, 57, 90, 113, 68, 54, 84, 82, 97, 121, 57, 110, 86, 89, 108, 122, 109, 68, 117, 68, 102, 66, 112, 103, 79, 103, 72, 122, 75, 116, 66, 48, 84, 105, 71, 115, 79, 113, 67, 82, 51, 65, 57, 68, 117, 10, 87, 47, 80, 75, 97, 90, 69, 49, 79, 86, 98, 70, 98, 101, 80, 51, 80, 85, 57, 101, 107, 122, 103, 107, 121, 104, 106, 112, 74, 77, 117, 83, 65, 57, 51, 77, 72, 68, 48, 74, 99, 79, 81, 103, 53, 80, 71, 117, 114, 76, 116, 122, 97, 97, 78, 106, 79, 103, 57, 70, 68, 54, 70, 75, 109, 115, 76, 82, 89, 54, 122, 76, 69, 80, 103, 57, 10, 53, 107, 52, 111, 116, 43, 118, 69, 108, 98, 71, 115, 47, 86, 54, 114, 43, 107, 72, 76, 88, 90, 49, 76, 51, 80, 82, 56, 100, 117, 57, 110, 102, 119, 66, 54, 106, 100, 75, 103, 71, 108, 120, 78, 73, 117, 71, 49, 50, 116, 49, 50, 115, 57, 82, 50, 51, 49, 54, 52, 105, 53, 106, 73, 70, 70, 84, 77, 97, 120, 101, 83, 116, 43, 66, 75, 10, 118, 48, 109, 85, 89, 81, 115, 52, 107, 73, 57, 100, 74, 71, 119, 108, 101, 122, 116, 53, 50, 101, 74, 43, 110, 97, 50, 102, 109, 75, 69, 71, 47, 72, 103, 85, 89, 70, 102, 52, 55, 111, 66, 51, 115, 81, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 10, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 43, 109, 67, 112, 54, 50, 88, 70, 51, 82, 89, 85, 67, 69, 52, 77, 68, 52, 50, 98, 52, 80, 100, 107, 114, 50, 99, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 69, 66, 65, 70, 102, 68, 101, 106, 97, 67, 110, 73, 50, 89, 52, 113, 116, 65, 113, 107, 101, 80, 120, 54, 100, 98, 55, 88, 122, 110, 80, 87, 90, 97, 79, 122, 71, 55, 51, 47, 77, 87, 77, 53, 72, 56, 102, 72, 117, 108, 119, 113, 90, 109, 52, 54, 113, 119, 116, 121, 101, 89, 10, 80, 48, 110, 88, 89, 71, 100, 110, 80, 122, 90, 80, 83, 115, 118, 120, 70, 80, 112, 97, 104, 121, 103, 99, 55, 89, 57, 66, 77, 115, 97, 86, 43, 88, 51, 97, 118, 88, 116, 98, 119, 114, 65, 104, 52, 52, 57, 71, 51, 67, 69, 52, 81, 51, 82, 77, 43, 122, 68, 52, 70, 51, 76, 66, 77, 118, 122, 73, 107, 82, 102, 69, 122, 70, 103, 51, 10, 84, 103, 118, 77, 87, 118, 99, 104, 78, 83, 105, 68, 98, 71, 65, 116, 82, 79, 116, 83, 106, 70, 65, 57, 116, 87, 119, 83, 49, 47, 111, 74, 117, 50, 121, 121, 83, 114, 72, 70, 105, 101, 84, 56, 48, 49, 76, 89, 89, 82, 102, 43, 101, 112, 83, 69, 106, 51, 109, 50, 77, 49, 109, 54, 68, 56, 81, 76, 52, 110, 67, 103, 83, 51, 103, 117, 10, 43, 115, 105, 102, 47, 97, 43, 82, 90, 81, 112, 52, 79, 66, 88, 108, 108, 120, 99, 85, 51, 102, 110, 103, 76, 68, 84, 52, 79, 78, 67, 69, 73, 103, 68, 65, 70, 70, 69, 89, 75, 119, 76, 99, 77, 70, 114, 119, 54, 65, 70, 56, 78, 84, 111, 106, 114, 119, 106, 107, 114, 54, 113, 79, 75, 69, 74, 74, 76, 118, 68, 49, 109, 84, 83, 43, 10, 55, 81, 57, 76, 71, 79, 72, 83, 74, 68, 121, 55, 88, 85, 101, 51, 73, 102, 75, 78, 48, 81, 113, 90, 106, 117, 78, 117, 80, 113, 49, 119, 52, 73, 43, 53, 121, 115, 120, 117, 103, 84, 72, 50, 101, 53, 120, 54, 101, 101, 82, 110, 99, 82, 103, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 65, 32, 87, 111, 83, 105, 103, 110, 32, 69, 67, 67, 32, 82, 111, 111, 116, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 67, 84, 67, 67, 65, 89, 43, 103, 65, 119, 73, 66, 65, 103, 73, 81, 97, 69, 112, 89, 99, 73, 66, 114, 56, 73, 56, 67, 43, 118, 98, 101, 54, 76, 67, 81, 107, 68, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 122, 66, 71, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 68, 10, 84, 106, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 104, 77, 82, 86, 50, 57, 84, 97, 87, 100, 117, 73, 69, 78, 66, 73, 69, 120, 112, 98, 87, 108, 48, 90, 87, 81, 120, 71, 122, 65, 90, 66, 103, 78, 86, 66, 65, 77, 84, 69, 107, 78, 66, 73, 70, 100, 118, 85, 50, 108, 110, 98, 105, 66, 70, 81, 48, 77, 103, 85, 109, 57, 118, 10, 100, 68, 65, 101, 70, 119, 48, 120, 78, 68, 69, 120, 77, 68, 103, 119, 77, 68, 85, 52, 78, 84, 104, 97, 70, 119, 48, 48, 78, 68, 69, 120, 77, 68, 103, 119, 77, 68, 85, 52, 78, 84, 104, 97, 77, 69, 89, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 78, 79, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 10, 69, 120, 70, 88, 98, 49, 78, 112, 90, 50, 52, 103, 81, 48, 69, 103, 84, 71, 108, 116, 97, 88, 82, 108, 90, 68, 69, 98, 77, 66, 107, 71, 65, 49, 85, 69, 65, 120, 77, 83, 81, 48, 69, 103, 86, 50, 57, 84, 97, 87, 100, 117, 73, 69, 86, 68, 81, 121, 66, 83, 98, 50, 57, 48, 77, 72, 89, 119, 69, 65, 89, 72, 75, 111, 90, 73, 10, 122, 106, 48, 67, 65, 81, 89, 70, 75, 52, 69, 69, 65, 67, 73, 68, 89, 103, 65, 69, 52, 102, 50, 79, 117, 69, 77, 107, 113, 53, 90, 55, 104, 99, 75, 54, 67, 54, 50, 78, 52, 68, 114, 106, 74, 76, 110, 83, 115, 98, 54, 73, 79, 115, 113, 47, 83, 114, 106, 53, 55, 121, 119, 118, 114, 49, 70, 81, 80, 69, 100, 49, 98, 80, 105, 85, 10, 116, 53, 118, 56, 75, 66, 55, 70, 86, 77, 120, 106, 110, 82, 90, 76, 85, 56, 72, 110, 73, 75, 118, 78, 114, 67, 88, 83, 102, 52, 47, 67, 119, 86, 113, 67, 88, 106, 67, 76, 101, 108, 84, 79, 65, 55, 87, 82, 102, 54, 113, 85, 48, 78, 71, 75, 83, 77, 121, 67, 66, 83, 97, 104, 49, 86, 69, 83, 49, 110, 115, 50, 111, 48, 73, 119, 10, 81, 68, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 113, 118, 51, 86, 87, 113, 80, 50, 104, 52, 115, 121, 104, 102, 51, 82, 10, 77, 108, 117, 65, 82, 90, 80, 122, 65, 55, 103, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 77, 68, 97, 65, 65, 119, 90, 81, 73, 120, 65, 79, 83, 107, 104, 76, 67, 66, 49, 84, 50, 119, 100, 75, 121, 85, 112, 79, 103, 79, 80, 81, 66, 48, 84, 75, 71, 88, 97, 47, 107, 78, 85, 84, 121, 104, 50, 84, 118, 48, 10, 68, 97, 117, 112, 110, 55, 53, 79, 99, 115, 113, 70, 49, 78, 110, 115, 116, 84, 74, 70, 71, 71, 43, 114, 114, 81, 73, 119, 102, 99, 102, 51, 97, 87, 77, 118, 111, 101, 71, 89, 55, 120, 77, 81, 48, 88, 107, 47, 48, 102, 55, 113, 79, 51, 47, 101, 86, 118, 83, 81, 115, 82, 85, 82, 50, 76, 73, 105, 70, 100, 65, 118, 119, 121, 89, 117, 10, 97, 47, 71, 82, 115, 112, 66, 108, 57, 74, 114, 109, 107, 79, 53, 75, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 83, 90, 65, 70, 73, 82, 32, 82, 79, 79, 84, 32, 67, 65, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 99, 106, 67, 67, 65, 108, 113, 103, 65, 119, 73, 66, 65, 103, 73, 85, 80, 111, 112, 100, 66, 43, 120, 86, 48, 106, 76, 86, 116, 43, 79, 50, 88, 119, 72, 114, 76, 100, 122, 107, 49, 117, 81, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 85, 84, 69, 76, 77, 65, 107, 71, 10, 65, 49, 85, 69, 66, 104, 77, 67, 85, 69, 119, 120, 75, 68, 65, 109, 66, 103, 78, 86, 66, 65, 111, 77, 72, 48, 116, 121, 89, 87, 112, 118, 100, 50, 69, 103, 83, 88, 112, 105, 89, 83, 66, 83, 98, 51, 112, 115, 97, 87, 78, 54, 90, 87, 53, 112, 98, 51, 100, 104, 73, 70, 77, 117, 81, 83, 52, 120, 71, 68, 65, 87, 66, 103, 78, 86, 10, 66, 65, 77, 77, 68, 49, 78, 97, 81, 85, 90, 74, 85, 105, 66, 83, 84, 48, 57, 85, 73, 69, 78, 66, 77, 106, 65, 101, 70, 119, 48, 120, 78, 84, 69, 119, 77, 84, 107, 119, 78, 122, 81, 122, 77, 122, 66, 97, 70, 119, 48, 122, 78, 84, 69, 119, 77, 84, 107, 119, 78, 122, 81, 122, 77, 122, 66, 97, 77, 70, 69, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 66, 77, 77, 83, 103, 119, 74, 103, 89, 68, 86, 81, 81, 75, 68, 66, 57, 76, 99, 109, 70, 113, 98, 51, 100, 104, 73, 69, 108, 54, 89, 109, 69, 103, 85, 109, 57, 54, 98, 71, 108, 106, 101, 109, 86, 117, 97, 87, 57, 51, 89, 83, 66, 84, 76, 107, 69, 117, 77, 82, 103, 119, 70, 103, 89, 68, 10, 86, 81, 81, 68, 68, 65, 57, 84, 87, 107, 70, 71, 83, 86, 73, 103, 85, 107, 57, 80, 86, 67, 66, 68, 81, 84, 73, 119, 103, 103, 69, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 66, 68, 119, 65, 119, 103, 103, 69, 75, 65, 111, 73, 66, 65, 81, 67, 51, 118, 68, 53, 81, 10, 113, 69, 118, 78, 81, 76, 88, 79, 89, 101, 101, 87, 121, 114, 83, 104, 50, 103, 119, 105, 115, 80, 113, 49, 101, 51, 89, 65, 100, 52, 119, 76, 122, 51, 50, 111, 104, 115, 119, 109, 85, 101, 81, 103, 80, 89, 85, 77, 49, 108, 106, 106, 53, 47, 81, 113, 71, 74, 51, 97, 48, 97, 52, 109, 55, 117, 116, 84, 51, 80, 83, 81, 49, 104, 78, 75, 10, 68, 74, 65, 56, 119, 47, 84, 97, 48, 111, 52, 78, 107, 106, 114, 99, 115, 98, 72, 47, 79, 78, 55, 68, 117, 105, 49, 102, 103, 76, 107, 67, 118, 85, 113, 100, 71, 119, 43, 48, 119, 56, 76, 66, 90, 119, 80, 100, 51, 66, 117, 99, 80, 98, 79, 119, 51, 103, 65, 101, 113, 68, 82, 72, 117, 53, 114, 114, 47, 103, 115, 85, 118, 84, 97, 69, 10, 50, 103, 48, 103, 118, 47, 112, 98, 121, 54, 107, 87, 73, 75, 48, 53, 89, 79, 52, 118, 100, 98, 98, 110, 108, 53, 122, 53, 80, 118, 49, 43, 84, 87, 57, 78, 76, 43, 43, 73, 68, 87, 114, 54, 51, 102, 69, 57, 98, 105, 67, 108, 111, 66, 75, 48, 84, 88, 67, 53, 122, 116, 100, 121, 79, 52, 109, 84, 112, 52, 67, 69, 72, 67, 100, 74, 10, 99, 107, 109, 49, 47, 122, 117, 86, 110, 115, 72, 77, 121, 65, 72, 115, 54, 65, 54, 75, 67, 112, 98, 110, 115, 54, 97, 72, 53, 100, 98, 53, 66, 83, 115, 78, 108, 48, 66, 119, 80, 76, 113, 115, 100, 86, 113, 99, 49, 85, 50, 100, 65, 103, 114, 83, 83, 53, 116, 109, 83, 48, 89, 72, 70, 50, 87, 116, 110, 50, 121, 73, 65, 78, 119, 105, 10, 105, 101, 68, 104, 90, 78, 82, 110, 118, 68, 70, 53, 89, 84, 121, 55, 121, 107, 72, 78, 88, 71, 111, 65, 121, 68, 119, 52, 106, 108, 105, 118, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 10, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 81, 117, 70, 113, 108, 75, 71, 76, 88, 76, 122, 80, 86, 118, 85, 80, 77, 106, 88, 47, 104, 100, 53, 54, 122, 119, 121, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, 67, 10, 65, 81, 69, 65, 116, 88, 80, 52, 65, 57, 120, 90, 87, 120, 49, 50, 54, 97, 77, 113, 101, 53, 65, 111, 115, 107, 51, 65, 77, 48, 43, 113, 109, 114, 72, 85, 117, 79, 81, 110, 47, 54, 109, 87, 109, 99, 53, 71, 52, 71, 49, 56, 84, 75, 73, 52, 112, 65, 90, 119, 56, 80, 82, 66, 69, 101, 119, 47, 82, 52, 48, 47, 99, 111, 102, 53, 10, 79, 47, 50, 107, 98, 121, 116, 84, 65, 79, 68, 47, 79, 98, 108, 113, 66, 119, 55, 114, 72, 82, 122, 50, 111, 110, 75, 81, 121, 52, 73, 57, 69, 89, 75, 76, 48, 114, 117, 102, 75, 113, 56, 104, 53, 109, 79, 71, 110, 88, 107, 90, 55, 47, 101, 55, 68, 68, 87, 81, 119, 52, 114, 116, 84, 119, 47, 49, 122, 66, 76, 90, 112, 68, 54, 55, 10, 111, 80, 119, 103, 108, 86, 57, 80, 74, 105, 56, 82, 73, 52, 78, 79, 100, 81, 99, 80, 118, 53, 118, 82, 116, 66, 51, 112, 69, 65, 84, 43, 121, 109, 67, 80, 111, 107, 121, 52, 114, 99, 47, 104, 107, 65, 47, 78, 114, 103, 114, 72, 88, 88, 117, 51, 85, 78, 76, 85, 89, 102, 114, 86, 70, 100, 118, 88, 110, 52, 100, 82, 86, 79, 117, 108, 10, 52, 43, 118, 74, 104, 97, 65, 108, 73, 68, 102, 55, 106, 115, 52, 77, 78, 73, 84, 104, 80, 73, 71, 121, 100, 48, 53, 68, 112, 89, 104, 102, 104, 109, 101, 104, 80, 101, 97, 48, 88, 71, 71, 50, 80, 116, 118, 43, 116, 121, 106, 70, 111, 103, 101, 117, 116, 99, 114, 75, 106, 83, 111, 83, 55, 53, 102, 116, 119, 106, 67, 107, 121, 83, 112, 54, 10, 43, 47, 78, 78, 73, 120, 117, 90, 77, 122, 83, 103, 76, 118, 87, 112, 67, 122, 47, 85, 88, 101, 72, 80, 104, 74, 47, 105, 71, 99, 74, 102, 105, 116, 89, 103, 72, 117, 78, 122, 116, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 101, 114, 116, 117, 109, 32, 84, 114, 117, 115, 116, 101, 100, 32, 78, 101, 116, 119, 111, 114, 107, 32, 67, 65, 32, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 48, 106, 67, 67, 65, 55, 113, 103, 65, 119, 73, 66, 65, 103, 73, 81, 73, 100, 98, 81, 83, 107, 56, 108, 68, 56, 107, 121, 78, 47, 121, 113, 88, 104, 75, 78, 54, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 48, 70, 65, 68, 67, 66, 103, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 85, 69, 119, 120, 73, 106, 65, 103, 66, 103, 78, 86, 66, 65, 111, 84, 71, 86, 86, 117, 97, 88, 112, 108, 100, 71, 56, 103, 86, 71, 86, 106, 97, 71, 53, 118, 98, 71, 57, 110, 97, 87, 86, 122, 73, 70, 77, 117, 81, 83, 52, 120, 74, 122, 65, 108, 66, 103, 78, 86, 66, 65, 115, 84, 72, 107, 78, 108, 99, 110, 82, 49, 10, 98, 83, 66, 68, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 73, 69, 70, 49, 100, 71, 104, 118, 99, 109, 108, 48, 101, 84, 69, 107, 77, 67, 73, 71, 65, 49, 85, 69, 65, 120, 77, 98, 81, 50, 86, 121, 100, 72, 86, 116, 73, 70, 82, 121, 100, 88, 78, 48, 90, 87, 81, 103, 84, 109, 86, 48, 100, 50, 57, 121, 10, 97, 121, 66, 68, 81, 83, 65, 121, 77, 67, 73, 89, 68, 122, 73, 119, 77, 84, 69, 120, 77, 68, 65, 50, 77, 68, 103, 122, 79, 84, 85, 50, 87, 104, 103, 80, 77, 106, 65, 48, 78, 106, 69, 119, 77, 68, 89, 119, 79, 68, 77, 53, 78, 84, 90, 97, 77, 73, 71, 65, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 81, 10, 84, 68, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 67, 104, 77, 90, 86, 87, 53, 112, 101, 109, 86, 48, 98, 121, 66, 85, 90, 87, 78, 111, 98, 109, 57, 115, 98, 50, 100, 112, 90, 88, 77, 103, 85, 121, 53, 66, 76, 106, 69, 110, 77, 67, 85, 71, 65, 49, 85, 69, 67, 120, 77, 101, 81, 50, 86, 121, 100, 72, 86, 116, 73, 69, 78, 108, 10, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 112, 98, 50, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 83, 81, 119, 73, 103, 89, 68, 86, 81, 81, 68, 69, 120, 116, 68, 90, 88, 74, 48, 100, 87, 48, 103, 86, 72, 74, 49, 99, 51, 82, 108, 90, 67, 66, 79, 90, 88, 82, 51, 98, 51, 74, 114, 73, 69, 78, 66, 10, 73, 68, 73, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, 57, 43, 88, 106, 52, 53, 116, 87, 65, 68, 71, 83, 100, 104, 104, 117, 87, 90, 71, 99, 47, 73, 106, 111, 101, 100, 81, 70, 57, 10, 55, 47, 116, 99, 90, 52, 122, 74, 122, 70, 120, 114, 113, 90, 72, 109, 117, 85, 76, 108, 73, 69, 117, 98, 50, 112, 116, 55, 117, 90, 108, 100, 50, 90, 117, 65, 83, 57, 101, 69, 81, 67, 115, 110, 48, 43, 105, 54, 77, 76, 115, 43, 67, 82, 113, 110, 83, 90, 88, 118, 75, 48, 65, 107, 119, 112, 102, 72, 112, 43, 54, 98, 74, 101, 43, 111, 10, 67, 103, 67, 88, 104, 86, 113, 113, 110, 100, 119, 112, 121, 101, 73, 49, 66, 43, 116, 119, 84, 85, 114, 87, 119, 98, 78, 87, 117, 75, 70, 66, 79, 74, 118, 82, 43, 122, 70, 47, 106, 43, 66, 102, 52, 98, 69, 47, 68, 52, 52, 87, 83, 87, 68, 88, 66, 111, 48, 89, 43, 97, 111, 109, 69, 75, 115, 113, 48, 57, 68, 82, 90, 52, 48, 98, 10, 82, 114, 53, 72, 77, 78, 85, 117, 99, 116, 72, 70, 89, 57, 114, 110, 89, 51, 108, 69, 102, 107, 116, 106, 74, 73, 109, 71, 76, 106, 81, 47, 75, 85, 120, 83, 105, 121, 113, 110, 119, 79, 75, 82, 75, 73, 109, 53, 119, 70, 118, 53, 72, 100, 110, 110, 74, 54, 51, 47, 109, 103, 75, 88, 119, 99, 90, 81, 107, 112, 115, 67, 76, 76, 50, 112, 10, 117, 84, 82, 90, 67, 114, 43, 69, 83, 118, 47, 102, 47, 114, 79, 102, 54, 57, 109, 101, 52, 74, 103, 106, 55, 75, 90, 114, 100, 120, 89, 113, 50, 56, 121, 116, 79, 120, 121, 107, 104, 57, 120, 71, 99, 49, 52, 90, 89, 109, 104, 70, 86, 43, 83, 81, 103, 107, 75, 55, 81, 116, 98, 119, 89, 101, 68, 66, 111, 122, 49, 109, 111, 49, 51, 48, 10, 71, 79, 54, 73, 121, 89, 48, 88, 82, 83, 109, 90, 77, 110, 85, 67, 77, 101, 52, 112, 74, 115, 104, 114, 65, 117, 97, 49, 89, 107, 86, 47, 78, 120, 86, 97, 73, 50, 105, 74, 49, 68, 55, 101, 84, 105, 101, 119, 56, 69, 65, 77, 118, 69, 48, 88, 121, 48, 50, 105, 115, 120, 55, 81, 66, 108, 114, 100, 57, 112, 80, 80, 86, 51, 87, 90, 10, 57, 102, 113, 71, 71, 109, 100, 52, 115, 55, 43, 87, 47, 106, 84, 99, 118, 101, 100, 83, 86, 117, 87, 122, 53, 88, 86, 55, 49, 48, 71, 82, 66, 100, 120, 100, 97, 101, 79, 86, 68, 85, 79, 53, 47, 73, 79, 87, 79, 90, 86, 55, 98, 73, 66, 97, 84, 120, 78, 121, 120, 116, 100, 57, 75, 88, 112, 69, 117, 108, 75, 107, 75, 116, 86, 66, 10, 82, 103, 107, 103, 47, 105, 75, 103, 116, 108, 115, 119, 106, 98, 121, 74, 68, 78, 88, 88, 99, 80, 105, 72, 85, 118, 51, 97, 55, 54, 120, 82, 76, 103, 101, 122, 84, 118, 55, 81, 67, 100, 112, 119, 55, 53, 106, 54, 86, 117, 90, 116, 50, 55, 86, 88, 83, 57, 122, 108, 76, 67, 85, 86, 121, 74, 52, 117, 101, 69, 55, 52, 50, 112, 121, 101, 10, 104, 105, 122, 75, 86, 47, 77, 97, 53, 99, 105, 83, 105, 120, 113, 67, 108, 110, 114, 68, 118, 70, 65, 83, 97, 100, 103, 79, 87, 107, 97, 76, 79, 117, 115, 109, 43, 105, 80, 74, 116, 114, 67, 66, 118, 107, 73, 65, 112, 80, 106, 87, 47, 106, 65, 117, 120, 57, 74, 71, 57, 117, 87, 79, 100, 102, 51, 121, 122, 76, 110, 81, 104, 49, 118, 77, 10, 66, 104, 66, 103, 117, 52, 77, 49, 116, 49, 53, 110, 51, 107, 102, 115, 109, 85, 106, 120, 112, 75, 69, 86, 47, 113, 50, 77, 89, 111, 52, 53, 86, 85, 56, 53, 70, 114, 109, 120, 89, 53, 51, 47, 116, 119, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 10, 65, 81, 72, 47, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 83, 50, 111, 86, 81, 53, 65, 115, 79, 103, 80, 52, 54, 75, 118, 80, 114, 85, 43, 66, 121, 109, 48, 84, 111, 79, 47, 84, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 78, 66, 81, 65, 68, 103, 103, 73, 66, 65, 72, 71, 108, 68, 115, 55, 107, 54, 98, 56, 47, 79, 78, 87, 74, 87, 115, 81, 67, 89, 102, 116, 77, 120, 82, 81, 88, 76, 89, 116, 80, 85, 50, 115, 81, 70, 47, 120, 108, 104, 77, 99, 81, 83, 90, 68, 101, 50, 56, 99, 109, 107, 52, 103, 109, 98, 51, 68, 87, 10, 65, 108, 52, 53, 111, 80, 101, 80, 113, 53, 97, 49, 112, 82, 78, 99, 103, 82, 82, 116, 68, 111, 71, 67, 69, 82, 117, 75, 84, 115, 90, 80, 112, 100, 49, 105, 72, 107, 84, 102, 67, 86, 110, 48, 87, 51, 99, 76, 78, 43, 109, 76, 73, 77, 98, 52, 67, 107, 52, 117, 87, 66, 122, 114, 77, 57, 68, 80, 104, 109, 68, 74, 50, 118, 117, 65, 10, 76, 53, 53, 77, 89, 73, 82, 52, 80, 83, 70, 107, 49, 118, 116, 66, 72, 120, 103, 80, 53, 56, 108, 49, 99, 98, 50, 57, 88, 78, 52, 48, 104, 122, 53, 66, 115, 65, 55, 50, 117, 100, 89, 47, 67, 82, 79, 87, 70, 67, 47, 101, 109, 104, 49, 97, 117, 86, 98, 79, 78, 84, 113, 119, 88, 51, 66, 78, 88, 117, 77, 112, 56, 83, 77, 111, 10, 99, 108, 109, 50, 113, 56, 75, 77, 90, 105, 89, 99, 100, 121, 119, 109, 100, 106, 87, 76, 75, 75, 100, 112, 111, 80, 107, 55, 57, 83, 80, 100, 104, 82, 66, 48, 121, 90, 65, 68, 86, 112, 72, 110, 114, 55, 112, 72, 49, 66, 75, 88, 69, 83, 76, 106, 111, 107, 109, 85, 98, 79, 101, 51, 108, 69, 117, 54, 76, 97, 84, 97, 77, 52, 116, 77, 10, 112, 107, 84, 47, 87, 106, 122, 71, 72, 87, 84, 89, 116, 84, 72, 107, 112, 106, 120, 54, 113, 70, 99, 76, 50, 43, 49, 104, 71, 115, 118, 120, 122, 110, 78, 51, 89, 54, 83, 72, 98, 48, 120, 82, 79, 78, 98, 107, 88, 56, 101, 102, 116, 111, 69, 113, 53, 73, 86, 73, 101, 86, 104, 101, 79, 47, 106, 98, 65, 111, 74, 110, 119, 84, 110, 98, 10, 119, 51, 82, 76, 80, 84, 89, 101, 43, 83, 109, 84, 105, 71, 104, 98, 113, 69, 81, 90, 73, 102, 67, 110, 54, 73, 69, 78, 76, 79, 105, 84, 78, 114, 81, 51, 115, 115, 113, 119, 71, 121, 90, 54, 109, 105, 85, 102, 109, 112, 113, 65, 110, 107, 115, 113, 80, 47, 117, 106, 109, 118, 53, 122, 77, 110, 72, 67, 110, 115, 90, 121, 52, 89, 112, 111, 10, 74, 47, 72, 107, 68, 55, 84, 69, 84, 75, 86, 104, 107, 47, 105, 88, 69, 65, 99, 113, 77, 67, 87, 112, 117, 99, 104, 120, 117, 79, 57, 111, 122, 67, 49, 43, 57, 101, 66, 43, 68, 52, 75, 111, 98, 55, 97, 54, 98, 73, 78, 68, 100, 56, 50, 75, 107, 104, 101, 104, 110, 108, 116, 52, 70, 106, 49, 70, 52, 106, 78, 121, 51, 101, 70, 109, 10, 121, 112, 110, 84, 121, 99, 85, 109, 47, 81, 49, 111, 66, 69, 97, 117, 116, 116, 109, 98, 106, 76, 52, 90, 118, 114, 72, 71, 56, 104, 110, 106, 88, 65, 76, 75, 76, 78, 104, 118, 83, 103, 102, 90, 121, 84, 88, 97, 81, 72, 88, 121, 120, 75, 99, 90, 98, 53, 53, 67, 69, 74, 104, 49, 53, 112, 87, 76, 89, 76, 122, 116, 120, 82, 76, 88, 10, 105, 115, 55, 86, 109, 70, 120, 87, 108, 103, 80, 70, 55, 110, 99, 71, 78, 102, 47, 80, 53, 79, 52, 47, 69, 50, 72, 117, 50, 57, 111, 116, 104, 102, 68, 78, 114, 112, 50, 121, 71, 65, 108, 70, 119, 53, 75, 104, 99, 104, 102, 56, 82, 55, 97, 103, 67, 121, 122, 120, 120, 78, 53, 68, 97, 65, 104, 113, 88, 122, 118, 119, 100, 109, 80, 55, 10, 122, 65, 89, 115, 112, 115, 98, 105, 68, 114, 87, 53, 118, 105, 83, 80, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 72, 101, 108, 108, 101, 110, 105, 99, 32, 65, 99, 97, 100, 101, 109, 105, 99, 32, 97, 110, 100, 32, 82, 101, 115, 101, 97, 114, 99, 104, 32, 73, 110, 115, 116, 105, 116, 117, 116, 105, 111, 110, 115, 32, 82, 111, 111, 116, 67, 65, 32, 50, 48, 49, 53, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 71, 67, 122, 67, 67, 65, 47, 79, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 66, 112, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 49, 73, 120, 68, 122, 65, 78, 66, 103, 78, 86, 66, 65, 99, 84, 10, 66, 107, 70, 48, 97, 71, 86, 117, 99, 122, 70, 69, 77, 69, 73, 71, 65, 49, 85, 69, 67, 104, 77, 55, 83, 71, 86, 115, 98, 71, 86, 117, 97, 87, 77, 103, 81, 87, 78, 104, 90, 71, 86, 116, 97, 87, 77, 103, 89, 87, 53, 107, 73, 70, 74, 108, 99, 50, 86, 104, 99, 109, 78, 111, 73, 69, 108, 117, 99, 51, 82, 112, 100, 72, 86, 48, 10, 97, 87, 57, 117, 99, 121, 66, 68, 90, 88, 74, 48, 76, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 120, 81, 68, 65, 43, 66, 103, 78, 86, 66, 65, 77, 84, 78, 48, 104, 108, 98, 71, 120, 108, 98, 109, 108, 106, 73, 69, 70, 106, 89, 87, 82, 108, 98, 87, 108, 106, 73, 71, 70, 117, 90, 67, 66, 83, 90, 88, 78, 108, 10, 89, 88, 74, 106, 97, 67, 66, 74, 98, 110, 78, 48, 97, 88, 82, 49, 100, 71, 108, 118, 98, 110, 77, 103, 85, 109, 57, 118, 100, 69, 78, 66, 73, 68, 73, 119, 77, 84, 85, 119, 72, 104, 99, 78, 77, 84, 85, 119, 78, 122, 65, 51, 77, 84, 65, 120, 77, 84, 73, 120, 87, 104, 99, 78, 78, 68, 65, 119, 78, 106, 77, 119, 77, 84, 65, 120, 10, 77, 84, 73, 120, 87, 106, 67, 66, 112, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 49, 73, 120, 68, 122, 65, 78, 66, 103, 78, 86, 66, 65, 99, 84, 66, 107, 70, 48, 97, 71, 86, 117, 99, 122, 70, 69, 77, 69, 73, 71, 65, 49, 85, 69, 67, 104, 77, 55, 83, 71, 86, 115, 98, 71, 86, 117, 97, 87, 77, 103, 10, 81, 87, 78, 104, 90, 71, 86, 116, 97, 87, 77, 103, 89, 87, 53, 107, 73, 70, 74, 108, 99, 50, 86, 104, 99, 109, 78, 111, 73, 69, 108, 117, 99, 51, 82, 112, 100, 72, 86, 48, 97, 87, 57, 117, 99, 121, 66, 68, 90, 88, 74, 48, 76, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 120, 81, 68, 65, 43, 66, 103, 78, 86, 10, 66, 65, 77, 84, 78, 48, 104, 108, 98, 71, 120, 108, 98, 109, 108, 106, 73, 69, 70, 106, 89, 87, 82, 108, 98, 87, 108, 106, 73, 71, 70, 117, 90, 67, 66, 83, 90, 88, 78, 108, 89, 88, 74, 106, 97, 67, 66, 74, 98, 110, 78, 48, 97, 88, 82, 49, 100, 71, 108, 118, 98, 110, 77, 103, 85, 109, 57, 118, 100, 69, 78, 66, 73, 68, 73, 119, 10, 77, 84, 85, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 68, 67, 43, 75, 107, 47, 71, 52, 110, 56, 80, 68, 119, 69, 88, 84, 50, 81, 78, 114, 67, 82, 79, 110, 107, 56, 90, 108, 114, 118, 10, 98, 84, 107, 66, 83, 82, 113, 48, 116, 56, 57, 47, 84, 83, 78, 84, 116, 53, 65, 65, 52, 120, 77, 113, 75, 75, 89, 120, 56, 90, 69, 65, 52, 121, 106, 115, 114, 105, 70, 66, 122, 104, 47, 97, 47, 88, 48, 83, 87, 119, 71, 68, 68, 55, 109, 119, 88, 53, 110, 104, 56, 104, 75, 68, 103, 69, 48, 71, 80, 116, 43, 115, 114, 43, 101, 104, 10, 105, 71, 115, 120, 114, 47, 67, 76, 48, 66, 103, 122, 117, 78, 116, 70, 97, 106, 84, 48, 65, 111, 65, 107, 75, 65, 111, 67, 70, 90, 86, 101, 100, 105, 111, 78, 109, 84, 111, 85, 87, 47, 98, 76, 121, 49, 79, 56, 69, 48, 48, 66, 105, 68, 101, 85, 74, 82, 116, 67, 118, 67, 76, 89, 106, 113, 79, 87, 88, 106, 114, 90, 77, 116, 115, 43, 10, 54, 80, 65, 81, 90, 101, 49, 48, 52, 83, 43, 110, 102, 75, 56, 110, 78, 76, 115, 112, 102, 90, 117, 50, 122, 119, 110, 73, 53, 100, 77, 75, 47, 73, 104, 108, 90, 88, 81, 75, 51, 72, 77, 99, 88, 77, 49, 65, 115, 82, 122, 85, 116, 111, 83, 77, 84, 70, 68, 80, 97, 73, 54, 111, 87, 97, 55, 67, 74, 48, 54, 67, 111, 106, 88, 100, 10, 70, 80, 81, 102, 47, 55, 74, 51, 49, 89, 99, 118, 113, 109, 53, 57, 74, 67, 102, 110, 120, 115, 115, 109, 53, 117, 88, 43, 90, 119, 100, 106, 50, 69, 85, 78, 51, 84, 112, 90, 90, 84, 108, 89, 101, 112, 75, 90, 99, 106, 50, 99, 104, 70, 54, 73, 73, 98, 106, 86, 57, 67, 122, 56, 50, 88, 66, 83, 84, 51, 105, 52, 118, 84, 119, 114, 10, 105, 53, 87, 89, 57, 98, 80, 82, 97, 77, 56, 103, 70, 72, 53, 77, 88, 70, 47, 110, 105, 43, 88, 49, 78, 89, 69, 90, 78, 57, 99, 82, 67, 76, 100, 109, 118, 116, 78, 75, 122, 111, 78, 88, 65, 68, 114, 68, 103, 102, 103, 88, 121, 53, 73, 50, 88, 100, 71, 106, 50, 72, 85, 98, 52, 89, 115, 110, 54, 110, 112, 73, 81, 102, 49, 70, 10, 71, 81, 97, 116, 74, 53, 108, 79, 119, 88, 66, 72, 51, 98, 87, 102, 103, 86, 77, 83, 53, 98, 71, 77, 83, 70, 48, 120, 81, 120, 102, 106, 106, 77, 90, 54, 89, 53, 90, 76, 75, 84, 66, 79, 104, 69, 53, 105, 71, 86, 52, 56, 122, 112, 101, 81, 112, 88, 56, 66, 54, 53, 51, 103, 43, 73, 117, 74, 51, 83, 87, 89, 80, 90, 75, 50, 10, 102, 117, 47, 90, 56, 86, 70, 82, 102, 83, 48, 109, 121, 71, 108, 90, 89, 101, 67, 115, 97, 114, 103, 113, 78, 104, 69, 69, 101, 108, 67, 57, 77, 111, 83, 43, 76, 57, 120, 121, 49, 100, 99, 100, 70, 107, 102, 107, 82, 50, 89, 103, 80, 47, 83, 87, 120, 97, 43, 79, 65, 88, 113, 108, 68, 51, 112, 107, 57, 81, 48, 89, 104, 57, 109, 117, 10, 105, 78, 88, 54, 104, 77, 69, 54, 119, 71, 107, 111, 76, 102, 73, 78, 97, 70, 71, 113, 52, 54, 86, 51, 120, 113, 83, 81, 68, 113, 69, 51, 105, 122, 69, 106, 82, 56, 69, 74, 67, 79, 116, 117, 57, 51, 105, 98, 49, 52, 76, 56, 104, 67, 67, 90, 83, 82, 109, 50, 69, 107, 97, 120, 43, 48, 86, 86, 70, 113, 109, 106, 90, 97, 121, 99, 10, 66, 119, 47, 113, 97, 57, 119, 102, 76, 103, 90, 121, 55, 73, 97, 73, 69, 117, 81, 116, 50, 49, 56, 70, 76, 43, 84, 119, 65, 57, 77, 109, 77, 43, 101, 65, 119, 115, 49, 67, 111, 82, 99, 48, 67, 119, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 10, 65, 81, 72, 47, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 99, 82, 86, 110, 121, 77, 106, 74, 118, 88, 86, 100, 99, 116, 65, 52, 71, 71, 113, 100, 56, 51, 69, 107, 86, 65, 115, 119, 68, 81, 89, 74, 75, 111, 90, 73, 10, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 73, 66, 65, 72, 87, 55, 98, 86, 82, 76, 113, 104, 66, 89, 82, 106, 84, 121, 89, 116, 99, 87, 78, 108, 48, 73, 88, 116, 86, 115, 121, 73, 101, 57, 116, 67, 53, 71, 56, 106, 72, 52, 102, 79, 112, 67, 116, 90, 77, 87, 86, 100, 121, 104, 68, 66, 75, 103, 50, 109, 70, 43, 10, 68, 49, 104, 89, 99, 50, 82, 121, 120, 43, 104, 70, 106, 116, 121, 112, 56, 105, 89, 47, 120, 110, 109, 77, 115, 86, 77, 73, 77, 52, 71, 119, 86, 104, 79, 43, 53, 108, 70, 99, 50, 74, 115, 75, 84, 48, 117, 99, 86, 108, 77, 67, 54, 85, 47, 50, 68, 87, 68, 113, 84, 85, 74, 86, 54, 72, 119, 98, 73, 83, 72, 84, 71, 122, 114, 77, 10, 100, 47, 75, 52, 107, 80, 70, 111, 120, 47, 108, 97, 47, 118, 111, 116, 57, 76, 47, 74, 57, 85, 85, 98, 122, 106, 103, 81, 75, 106, 101, 75, 101, 97, 79, 48, 52, 119, 108, 115, 104, 89, 97, 84, 47, 52, 109, 87, 74, 51, 105, 66, 106, 50, 102, 106, 82, 110, 82, 85, 106, 116, 107, 78, 97, 101, 74, 75, 57, 69, 49, 48, 65, 47, 43, 121, 10, 100, 43, 50, 86, 90, 53, 102, 107, 115, 99, 87, 114, 118, 50, 111, 106, 54, 78, 83, 85, 52, 107, 81, 111, 89, 115, 82, 76, 52, 118, 68, 89, 52, 105, 108, 114, 71, 110, 66, 43, 74, 71, 71, 84, 101, 48, 56, 68, 77, 105, 85, 78, 82, 83, 81, 114, 108, 114, 82, 71, 97, 114, 57, 75, 67, 47, 101, 97, 106, 56, 71, 115, 71, 115, 86, 110, 10, 56, 50, 56, 48, 48, 118, 112, 122, 89, 52, 122, 118, 70, 114, 67, 111, 112, 69, 89, 113, 43, 79, 115, 83, 55, 72, 75, 48, 55, 47, 103, 114, 102, 111, 120, 83, 119, 73, 117, 69, 86, 80, 107, 118, 80, 117, 78, 86, 113, 78, 120, 109, 115, 100, 110, 104, 88, 57, 105, 122, 106, 70, 107, 48, 87, 97, 83, 114, 84, 50, 121, 55, 72, 120, 106, 98, 10, 100, 97, 118, 89, 121, 53, 76, 78, 108, 68, 104, 104, 68, 103, 99, 71, 72, 48, 116, 71, 69, 80, 69, 86, 118, 111, 50, 70, 88, 68, 116, 75, 75, 52, 70, 53, 68, 55, 82, 112, 110, 48, 108, 81, 108, 48, 51, 51, 68, 108, 90, 100, 119, 74, 86, 113, 119, 106, 98, 68, 71, 50, 106, 74, 57, 83, 114, 99, 82, 53, 113, 43, 115, 115, 55, 70, 10, 74, 101, 106, 54, 65, 55, 110, 97, 43, 82, 90, 117, 107, 89, 84, 49, 72, 67, 106, 73, 47, 67, 98, 77, 49, 120, 121, 81, 86, 113, 100, 102, 98, 122, 111, 69, 118, 77, 49, 52, 105, 81, 117, 79, 68, 121, 43, 106, 113, 107, 43, 105, 71, 120, 73, 57, 70, 103, 104, 65, 68, 47, 70, 71, 84, 78, 101, 113, 101, 119, 106, 66, 67, 118, 86, 116, 10, 74, 57, 52, 67, 106, 56, 114, 68, 116, 83, 118, 75, 54, 101, 118, 73, 73, 86, 77, 52, 112, 99, 119, 55, 50, 72, 99, 51, 77, 75, 74, 80, 50, 87, 47, 82, 56, 107, 67, 116, 81, 88, 111, 88, 120, 100, 90, 75, 78, 89, 109, 51, 81, 100, 86, 56, 104, 110, 57, 86, 84, 89, 78, 75, 112, 88, 77, 103, 119, 68, 113, 118, 107, 80, 71, 97, 10, 74, 73, 55, 90, 106, 110, 72, 75, 101, 55, 105, 71, 50, 114, 75, 80, 109, 84, 52, 100, 69, 119, 48, 83, 69, 101, 55, 85, 113, 47, 68, 112, 70, 88, 89, 67, 53, 79, 68, 102, 113, 105, 65, 101, 87, 50, 71, 70, 90, 69, 67, 112, 107, 74, 99, 78, 114, 86, 80, 83, 87, 104, 50, 72, 97, 103, 67, 88, 90, 87, 75, 48, 118, 109, 57, 113, 10, 112, 47, 85, 115, 81, 117, 48, 121, 114, 98, 89, 104, 110, 114, 54, 56, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 72, 101, 108, 108, 101, 110, 105, 99, 32, 65, 99, 97, 100, 101, 109, 105, 99, 32, 97, 110, 100, 32, 82, 101, 115, 101, 97, 114, 99, 104, 32, 73, 110, 115, 116, 105, 116, 117, 116, 105, 111, 110, 115, 32, 69, 67, 67, 32, 82, 111, 111, 116, 67, 65, 32, 50, 48, 49, 53, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 119, 122, 67, 67, 65, 107, 113, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 68, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 106, 67, 66, 113, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 49, 73, 120, 68, 122, 65, 78, 66, 103, 78, 86, 66, 65, 99, 84, 66, 107, 70, 48, 10, 97, 71, 86, 117, 99, 122, 70, 69, 77, 69, 73, 71, 65, 49, 85, 69, 67, 104, 77, 55, 83, 71, 86, 115, 98, 71, 86, 117, 97, 87, 77, 103, 81, 87, 78, 104, 90, 71, 86, 116, 97, 87, 77, 103, 89, 87, 53, 107, 73, 70, 74, 108, 99, 50, 86, 104, 99, 109, 78, 111, 73, 69, 108, 117, 99, 51, 82, 112, 100, 72, 86, 48, 97, 87, 57, 117, 10, 99, 121, 66, 68, 90, 88, 74, 48, 76, 105, 66, 66, 100, 88, 82, 111, 98, 51, 74, 112, 100, 72, 107, 120, 82, 68, 66, 67, 66, 103, 78, 86, 66, 65, 77, 84, 79, 48, 104, 108, 98, 71, 120, 108, 98, 109, 108, 106, 73, 69, 70, 106, 89, 87, 82, 108, 98, 87, 108, 106, 73, 71, 70, 117, 90, 67, 66, 83, 90, 88, 78, 108, 89, 88, 74, 106, 10, 97, 67, 66, 74, 98, 110, 78, 48, 97, 88, 82, 49, 100, 71, 108, 118, 98, 110, 77, 103, 82, 85, 78, 68, 73, 70, 74, 118, 98, 51, 82, 68, 81, 83, 65, 121, 77, 68, 69, 49, 77, 66, 52, 88, 68, 84, 69, 49, 77, 68, 99, 119, 78, 122, 69, 119, 77, 122, 99, 120, 77, 108, 111, 88, 68, 84, 81, 119, 77, 68, 89, 122, 77, 68, 69, 119, 10, 77, 122, 99, 120, 77, 108, 111, 119, 103, 97, 111, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 100, 83, 77, 81, 56, 119, 68, 81, 89, 68, 86, 81, 81, 72, 69, 119, 90, 66, 100, 71, 104, 108, 98, 110, 77, 120, 82, 68, 66, 67, 66, 103, 78, 86, 66, 65, 111, 84, 79, 48, 104, 108, 98, 71, 120, 108, 98, 109, 108, 106, 10, 73, 69, 70, 106, 89, 87, 82, 108, 98, 87, 108, 106, 73, 71, 70, 117, 90, 67, 66, 83, 90, 88, 78, 108, 89, 88, 74, 106, 97, 67, 66, 74, 98, 110, 78, 48, 97, 88, 82, 49, 100, 71, 108, 118, 98, 110, 77, 103, 81, 50, 86, 121, 100, 67, 52, 103, 81, 88, 86, 48, 97, 71, 57, 121, 97, 88, 82, 53, 77, 85, 81, 119, 81, 103, 89, 68, 10, 86, 81, 81, 68, 69, 122, 116, 73, 90, 87, 120, 115, 90, 87, 53, 112, 89, 121, 66, 66, 89, 50, 70, 107, 90, 87, 49, 112, 89, 121, 66, 104, 98, 109, 81, 103, 85, 109, 86, 122, 90, 87, 70, 121, 89, 50, 103, 103, 83, 87, 53, 122, 100, 71, 108, 48, 100, 88, 82, 112, 98, 50, 53, 122, 73, 69, 86, 68, 81, 121, 66, 83, 98, 50, 57, 48, 10, 81, 48, 69, 103, 77, 106, 65, 120, 78, 84, 66, 50, 77, 66, 65, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 66, 83, 117, 66, 66, 65, 65, 105, 65, 50, 73, 65, 66, 74, 75, 103, 81, 101, 104, 76, 103, 111, 82, 99, 52, 118, 103, 120, 69, 90, 109, 71, 90, 69, 52, 74, 74, 83, 43, 100, 81, 83, 56, 75, 114, 106, 86, 80, 10, 100, 74, 87, 121, 85, 87, 82, 114, 106, 87, 118, 109, 80, 51, 67, 86, 56, 65, 86, 69, 82, 54, 90, 121, 79, 70, 66, 50, 108, 81, 74, 97, 106, 113, 52, 111, 110, 118, 107, 116, 84, 112, 110, 118, 76, 69, 104, 118, 84, 67, 85, 112, 54, 78, 70, 120, 87, 57, 56, 100, 119, 88, 85, 51, 116, 78, 102, 54, 101, 51, 112, 67, 110, 71, 111, 75, 10, 86, 108, 112, 56, 97, 81, 117, 113, 103, 65, 107, 107, 98, 72, 55, 66, 82, 113, 78, 67, 77, 69, 65, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 10, 66, 66, 89, 69, 70, 76, 81, 105, 67, 52, 75, 90, 74, 65, 69, 79, 110, 76, 118, 107, 68, 118, 50, 47, 43, 53, 99, 103, 107, 53, 107, 113, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 65, 50, 99, 65, 77, 71, 81, 67, 77, 71, 102, 79, 70, 109, 73, 52, 111, 113, 120, 105, 82, 97, 101, 112, 108, 83, 84, 65, 10, 71, 105, 101, 99, 77, 106, 118, 65, 119, 78, 87, 54, 113, 101, 102, 52, 66, 69, 78, 84, 104, 101, 53, 83, 73, 100, 54, 100, 57, 83, 87, 68, 80, 112, 53, 89, 83, 121, 47, 88, 90, 120, 77, 79, 73, 81, 73, 119, 66, 101, 70, 49, 65, 100, 53, 111, 55, 83, 111, 102, 84, 85, 119, 74, 67, 65, 51, 115, 83, 54, 49, 107, 70, 121, 106, 110, 10, 100, 99, 53, 70, 90, 88, 73, 104, 70, 56, 115, 105, 81, 81, 54, 77, 69, 53, 103, 52, 109, 108, 82, 116, 109, 56, 114, 105, 102, 79, 111, 67, 87, 67, 75, 82, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 101, 114, 116, 112, 108, 117, 115, 32, 82, 111, 111, 116, 32, 67, 65, 32, 71, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 97, 122, 67, 67, 65, 49, 79, 103, 65, 119, 73, 66, 65, 103, 73, 83, 69, 83, 66, 86, 103, 43, 81, 116, 80, 108, 82, 87, 104, 83, 50, 68, 78, 55, 99, 115, 51, 69, 89, 82, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 68, 81, 85, 65, 77, 68, 52, 120, 67, 122, 65, 74, 66, 103, 78, 86, 10, 66, 65, 89, 84, 65, 107, 90, 83, 77, 82, 69, 119, 68, 119, 89, 68, 86, 81, 81, 75, 68, 65, 104, 68, 90, 88, 74, 48, 99, 71, 120, 49, 99, 122, 69, 99, 77, 66, 111, 71, 65, 49, 85, 69, 65, 119, 119, 84, 81, 50, 86, 121, 100, 72, 66, 115, 100, 88, 77, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 66, 72, 77, 84, 65, 101, 10, 70, 119, 48, 120, 78, 68, 65, 49, 77, 106, 89, 119, 77, 68, 65, 119, 77, 68, 66, 97, 70, 119, 48, 122, 79, 68, 65, 120, 77, 84, 85, 119, 77, 68, 65, 119, 77, 68, 66, 97, 77, 68, 52, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 90, 83, 77, 82, 69, 119, 68, 119, 89, 68, 86, 81, 81, 75, 68, 65, 104, 68, 10, 90, 88, 74, 48, 99, 71, 120, 49, 99, 122, 69, 99, 77, 66, 111, 71, 65, 49, 85, 69, 65, 119, 119, 84, 81, 50, 86, 121, 100, 72, 66, 115, 100, 88, 77, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 66, 72, 77, 84, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 10, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 78, 112, 81, 104, 55, 98, 97, 117, 75, 107, 43, 110, 87, 84, 54, 86, 106, 79, 97, 86, 106, 48, 87, 53, 81, 79, 86, 115, 106, 81, 99, 109, 109, 49, 105, 66, 100, 84, 89, 106, 43, 101, 74, 90, 74, 43, 54, 50, 50, 83, 76, 90, 79, 90, 53, 75, 109, 72, 78, 10, 114, 52, 57, 97, 105, 90, 70, 108, 117, 86, 106, 56, 116, 65, 78, 102, 107, 84, 56, 116, 69, 66, 88, 103, 102, 115, 43, 56, 47, 72, 57, 68, 90, 54, 105, 116, 88, 106, 89, 106, 50, 74, 105, 122, 84, 102, 78, 68, 110, 106, 108, 56, 75, 118, 122, 115, 105, 78, 87, 73, 55, 110, 67, 57, 104, 82, 89, 116, 54, 107, 117, 74, 80, 75, 78, 120, 10, 81, 118, 52, 99, 47, 100, 77, 99, 76, 82, 67, 52, 104, 108, 84, 113, 81, 55, 106, 98, 120, 111, 102, 97, 113, 75, 54, 65, 74, 99, 57, 54, 74, 104, 50, 113, 107, 98, 66, 73, 98, 54, 54, 49, 51, 112, 55, 89, 49, 47, 111, 65, 47, 99, 97, 80, 48, 70, 71, 55, 89, 110, 50, 107, 115, 89, 121, 121, 47, 121, 65, 82, 117, 106, 86, 106, 10, 66, 89, 90, 72, 89, 69, 77, 122, 107, 80, 90, 72, 111, 103, 78, 80, 108, 107, 50, 100, 84, 56, 72, 113, 54, 112, 121, 105, 47, 106, 81, 117, 51, 114, 102, 75, 71, 51, 97, 107, 116, 54, 50, 102, 54, 97, 106, 85, 101, 68, 57, 52, 47, 118, 73, 52, 67, 84, 89, 100, 48, 104, 89, 67, 121, 79, 119, 113, 97, 75, 47, 49, 106, 112, 84, 118, 10, 76, 82, 78, 54, 72, 107, 74, 75, 72, 82, 85, 120, 114, 103, 119, 69, 86, 47, 120, 104, 99, 47, 77, 120, 86, 111, 89, 120, 103, 75, 68, 69, 69, 87, 52, 119, 100, 117, 79, 85, 56, 70, 56, 69, 120, 75, 121, 72, 99, 111, 109, 89, 120, 90, 51, 77, 86, 119, 105, 97, 57, 65, 122, 56, 102, 88, 111, 70, 79, 118, 112, 72, 103, 68, 109, 50, 10, 122, 52, 81, 84, 100, 50, 56, 110, 54, 118, 43, 87, 90, 120, 99, 73, 98, 101, 107, 78, 49, 105, 78, 81, 77, 76, 65, 86, 100, 66, 77, 43, 53, 83, 47, 47, 68, 115, 51, 69, 67, 48, 112, 100, 56, 78, 103, 65, 77, 48, 108, 109, 54, 54, 69, 89, 102, 70, 107, 117, 80, 83, 105, 53, 89, 88, 72, 76, 116, 97, 87, 54, 117, 79, 114, 99, 10, 52, 110, 66, 118, 67, 71, 114, 99, 104, 50, 99, 48, 55, 57, 56, 119, 99, 116, 51, 122, 121, 84, 56, 106, 47, 122, 88, 104, 118, 105, 69, 112, 73, 68, 67, 66, 53, 66, 109, 108, 73, 79, 107, 108, 121, 110, 77, 120, 100, 67, 109, 43, 52, 107, 76, 86, 56, 55, 73, 109, 90, 115, 100, 111, 47, 82, 109, 122, 53, 121, 67, 84, 109, 101, 104, 100, 10, 52, 70, 54, 72, 53, 48, 98, 111, 74, 90, 119, 75, 75, 83, 84, 85, 122, 86, 105, 71, 85, 107, 65, 107, 115, 110, 115, 80, 109, 66, 73, 103, 74, 80, 97, 81, 98, 69, 102, 73, 68, 98, 115, 89, 73, 67, 55, 90, 47, 102, 121, 76, 56, 105, 110, 113, 104, 51, 83, 86, 52, 69, 74, 81, 101, 73, 81, 69, 81, 87, 71, 119, 57, 67, 69, 106, 10, 106, 121, 51, 76, 75, 67, 72, 121, 97, 109, 122, 48, 71, 113, 98, 70, 70, 76, 81, 51, 90, 85, 43, 86, 47, 89, 68, 73, 43, 72, 76, 108, 74, 87, 118, 69, 89, 76, 70, 55, 98, 89, 53, 75, 105, 110, 80, 79, 87, 102, 116, 119, 101, 110, 77, 71, 69, 57, 110, 84, 100, 68, 99, 107, 81, 81, 111, 82, 98, 53, 102, 99, 53, 43, 82, 43, 10, 111, 98, 48, 86, 56, 114, 113, 72, 68, 122, 49, 111, 105, 104, 89, 72, 65, 103, 77, 66, 65, 65, 71, 106, 89, 122, 66, 104, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 48, 71, 10, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 83, 111, 119, 99, 67, 98, 107, 97, 104, 68, 70, 88, 120, 100, 66, 105, 101, 48, 75, 108, 72, 89, 108, 119, 117, 66, 115, 84, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 83, 111, 119, 99, 67, 98, 107, 97, 104, 68, 70, 88, 120, 100, 66, 105, 101, 48, 75, 108, 72, 89, 10, 108, 119, 117, 66, 115, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 48, 70, 65, 65, 79, 67, 65, 103, 69, 65, 110, 70, 90, 118, 65, 88, 55, 82, 118, 85, 122, 49, 105, 115, 98, 119, 74, 104, 47, 107, 52, 68, 103, 89, 122, 68, 76, 68, 75, 84, 117, 100, 81, 83, 107, 48, 89, 99, 98, 88, 56, 65, 67, 104, 10, 54, 54, 82, 121, 106, 53, 81, 88, 118, 66, 77, 115, 100, 98, 82, 88, 55, 103, 112, 56, 67, 88, 114, 99, 49, 99, 113, 104, 48, 68, 81, 84, 43, 72, 101, 114, 110, 43, 88, 43, 50, 66, 53, 48, 105, 111, 85, 72, 106, 51, 47, 77, 101, 88, 114, 75, 108, 115, 51, 78, 47, 85, 47, 55, 47, 83, 77, 78, 107, 80, 88, 48, 88, 116, 80, 71, 10, 89, 88, 50, 101, 69, 101, 65, 67, 55, 103, 107, 69, 50, 81, 102, 100, 112, 111, 113, 51, 68, 73, 77, 107, 117, 52, 78, 81, 107, 118, 53, 103, 100, 82, 69, 43, 50, 74, 50, 119, 105, 110, 113, 49, 52, 74, 50, 98, 121, 53, 66, 83, 83, 55, 67, 84, 75, 116, 81, 43, 70, 106, 80, 108, 110, 115, 90, 108, 70, 84, 53, 107, 79, 119, 81, 47, 10, 50, 119, 121, 80, 88, 49, 119, 100, 97, 82, 43, 118, 56, 43, 107, 104, 106, 80, 80, 118, 108, 47, 97, 97, 116, 120, 109, 50, 104, 72, 83, 99, 111, 49, 83, 49, 99, 69, 53, 106, 50, 70, 100, 100, 85, 121, 71, 98, 81, 74, 74, 68, 43, 116, 90, 51, 86, 84, 78, 80, 90, 78, 88, 55, 48, 67, 120, 113, 106, 109, 48, 108, 112, 117, 43, 70, 10, 54, 65, 76, 69, 85, 122, 54, 53, 110, 111, 101, 56, 122, 68, 85, 97, 51, 113, 72, 112, 105, 109, 79, 72, 90, 82, 52, 82, 75, 116, 116, 106, 100, 53, 99, 85, 118, 112, 111, 85, 109, 82, 71, 121, 119, 79, 54, 119, 84, 47, 103, 85, 73, 84, 74, 68, 84, 53, 43, 114, 111, 115, 117, 111, 68, 54, 111, 55, 66, 108, 88, 71, 69, 105, 108, 88, 10, 67, 78, 81, 51, 49, 52, 99, 110, 114, 85, 108, 90, 112, 53, 71, 114, 82, 72, 112, 101, 106, 88, 68, 98, 108, 56, 53, 73, 85, 76, 70, 122, 107, 47, 98, 119, 103, 50, 68, 53, 122, 102, 72, 104, 77, 102, 49, 98, 102, 72, 69, 104, 89, 120, 81, 85, 113, 113, 47, 70, 51, 112, 78, 43, 97, 76, 72, 115, 73, 113, 75, 113, 107, 72, 87, 101, 10, 116, 85, 78, 121, 54, 109, 83, 106, 104, 69, 118, 57, 68, 75, 103, 109, 97, 51, 71, 88, 55, 108, 90, 106, 90, 117, 104, 67, 86, 80, 110, 72, 72, 100, 47, 81, 106, 49, 118, 102, 121, 68, 66, 118, 105, 80, 52, 78, 120, 68, 77, 99, 85, 54, 105, 106, 47, 85, 103, 81, 56, 117, 81, 75, 84, 117, 69, 86, 86, 47, 120, 117, 90, 68, 68, 67, 10, 86, 82, 72, 99, 54, 113, 110, 78, 83, 108, 83, 115, 75, 87, 78, 69, 122, 48, 112, 65, 111, 78, 90, 111, 87, 82, 115, 122, 43, 101, 56, 54, 105, 57, 115, 103, 107, 116, 120, 67, 104, 76, 56, 66, 113, 52, 102, 65, 49, 83, 67, 67, 50, 56, 97, 53, 103, 52, 86, 67, 88, 65, 57, 68, 79, 50, 112, 74, 78, 100, 87, 89, 57, 66, 87, 47, 10, 43, 109, 71, 66, 68, 65, 107, 103, 71, 78, 76, 81, 70, 119, 122, 76, 83, 65, 66, 81, 54, 88, 97, 67, 106, 71, 84, 88, 79, 113, 65, 72, 86, 99, 119, 101, 77, 99, 68, 118, 79, 114, 82, 108, 43, 43, 79, 47, 81, 109, 117, 101, 68, 54, 105, 57, 97, 53, 106, 99, 50, 78, 118, 76, 105, 54, 84, 100, 49, 49, 110, 48, 98, 116, 51, 43, 10, 113, 115, 79, 82, 48, 67, 53, 67, 66, 56, 65, 77, 84, 86, 80, 78, 74, 76, 70, 77, 87, 120, 53, 82, 57, 78, 47, 112, 107, 118, 111, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 67, 101, 114, 116, 112, 108, 117, 115, 32, 82, 111, 111, 116, 32, 67, 65, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 72, 68, 67, 67, 65, 97, 75, 103, 65, 119, 73, 66, 65, 103, 73, 83, 69, 83, 68, 90, 107, 99, 54, 117, 111, 43, 106, 70, 53, 47, 47, 112, 65, 113, 47, 80, 99, 55, 120, 86, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 68, 77, 68, 52, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 10, 65, 107, 90, 83, 77, 82, 69, 119, 68, 119, 89, 68, 86, 81, 81, 75, 68, 65, 104, 68, 90, 88, 74, 48, 99, 71, 120, 49, 99, 122, 69, 99, 77, 66, 111, 71, 65, 49, 85, 69, 65, 119, 119, 84, 81, 50, 86, 121, 100, 72, 66, 115, 100, 88, 77, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 66, 72, 77, 106, 65, 101, 70, 119, 48, 120, 10, 78, 68, 65, 49, 77, 106, 89, 119, 77, 68, 65, 119, 77, 68, 66, 97, 70, 119, 48, 122, 79, 68, 65, 120, 77, 84, 85, 119, 77, 68, 65, 119, 77, 68, 66, 97, 77, 68, 52, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 90, 83, 77, 82, 69, 119, 68, 119, 89, 68, 86, 81, 81, 75, 68, 65, 104, 68, 90, 88, 74, 48, 10, 99, 71, 120, 49, 99, 122, 69, 99, 77, 66, 111, 71, 65, 49, 85, 69, 65, 119, 119, 84, 81, 50, 86, 121, 100, 72, 66, 115, 100, 88, 77, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 66, 72, 77, 106, 66, 50, 77, 66, 65, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 66, 83, 117, 66, 66, 65, 65, 105, 65, 50, 73, 65, 10, 66, 77, 48, 80, 87, 49, 97, 67, 51, 47, 66, 70, 71, 116, 97, 116, 57, 51, 110, 119, 72, 99, 109, 115, 108, 116, 97, 101, 84, 112, 119, 102, 116, 69, 73, 82, 121, 111, 97, 47, 98, 102, 117, 70, 111, 56, 88, 108, 71, 86, 122, 88, 55, 113, 89, 47, 97, 87, 102, 89, 101, 79, 75, 109, 121, 99, 84, 98, 76, 88, 107, 117, 53, 52, 117, 78, 10, 65, 109, 56, 120, 73, 107, 48, 71, 52, 50, 66, 121, 82, 90, 48, 79, 81, 110, 101, 101, 122, 115, 47, 108, 102, 52, 87, 98, 71, 79, 84, 56, 122, 67, 53, 121, 48, 120, 97, 84, 84, 115, 113, 90, 89, 49, 121, 104, 66, 83, 112, 115, 66, 113, 78, 106, 77, 71, 69, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 10, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 78, 113, 68, 89, 119, 74, 53, 106, 116, 112, 77, 120, 106, 119, 106, 70, 78, 105, 80, 119, 121, 67, 114, 75, 71, 66, 90, 77, 66, 56, 71, 65, 49, 85, 100, 10, 73, 119, 81, 89, 77, 66, 97, 65, 70, 78, 113, 68, 89, 119, 74, 53, 106, 116, 112, 77, 120, 106, 119, 106, 70, 78, 105, 80, 119, 121, 67, 114, 75, 71, 66, 90, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 68, 65, 50, 103, 65, 77, 71, 85, 67, 77, 72, 68, 43, 115, 65, 118, 90, 57, 52, 79, 88, 55, 80, 78, 86, 10, 72, 100, 84, 99, 115, 119, 89, 79, 47, 106, 79, 89, 110, 89, 115, 53, 107, 71, 117, 85, 73, 101, 50, 50, 49, 49, 51, 87, 84, 78, 99, 104, 112, 43, 101, 47, 73, 81, 56, 114, 122, 102, 99, 113, 51, 73, 85, 72, 110, 81, 73, 120, 65, 73, 89, 85, 70, 117, 88, 99, 115, 71, 88, 67, 119, 73, 52, 85, 110, 55, 56, 107, 70, 109, 106, 108, 10, 118, 80, 108, 53, 97, 100, 121, 116, 82, 83, 118, 51, 116, 106, 70, 122, 122, 65, 97, 108, 85, 53, 79, 82, 71, 112, 79, 117, 99, 71, 112, 110, 117, 116, 101, 101, 53, 87, 69, 97, 88, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 79, 112, 101, 110, 84, 114, 117, 115, 116, 32, 82, 111, 111, 116, 32, 67, 65, 32, 71, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 98, 122, 67, 67, 65, 49, 101, 103, 65, 119, 73, 66, 65, 103, 73, 83, 69, 83, 67, 122, 107, 70, 85, 53, 102, 88, 56, 50, 98, 87, 84, 67, 112, 53, 57, 114, 89, 52, 53, 110, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 77, 69, 65, 120, 67, 122, 65, 74, 66, 103, 78, 86, 10, 66, 65, 89, 84, 65, 107, 90, 83, 77, 82, 73, 119, 69, 65, 89, 68, 86, 81, 81, 75, 68, 65, 108, 80, 99, 71, 86, 117, 86, 72, 74, 49, 99, 51, 81, 120, 72, 84, 65, 98, 66, 103, 78, 86, 66, 65, 77, 77, 70, 69, 57, 119, 90, 87, 53, 85, 99, 110, 86, 122, 100, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 69, 99, 120, 10, 77, 66, 52, 88, 68, 84, 69, 48, 77, 68, 85, 121, 78, 106, 65, 52, 78, 68, 85, 49, 77, 70, 111, 88, 68, 84, 77, 52, 77, 68, 69, 120, 78, 84, 65, 119, 77, 68, 65, 119, 77, 70, 111, 119, 81, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 108, 73, 120, 69, 106, 65, 81, 66, 103, 78, 86, 66, 65, 111, 77, 10, 67, 85, 57, 119, 90, 87, 53, 85, 99, 110, 86, 122, 100, 68, 69, 100, 77, 66, 115, 71, 65, 49, 85, 69, 65, 119, 119, 85, 84, 51, 66, 108, 98, 108, 82, 121, 100, 88, 78, 48, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 82, 122, 69, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 10, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 68, 52, 101, 85, 98, 97, 108, 115, 85, 119, 88, 111, 112, 120, 65, 121, 49, 119, 112, 76, 117, 119, 120, 81, 106, 99, 122, 101, 89, 49, 119, 73, 67, 107, 69, 83, 51, 100, 53, 111, 101, 117, 88, 84, 50, 82, 48, 111, 100, 115, 78, 55, 102, 97, 10, 89, 112, 54, 98, 119, 105, 84, 88, 106, 47, 72, 98, 112, 113, 98, 102, 82, 109, 57, 82, 112, 110, 72, 76, 80, 104, 115, 120, 90, 50, 76, 51, 69, 86, 115, 48, 74, 57, 86, 53, 84, 111, 121, 98, 87, 76, 48, 105, 69, 65, 49, 99, 74, 119, 122, 100, 77, 79, 87, 111, 48, 49, 48, 104, 79, 72, 81, 88, 47, 117, 77, 102, 116, 107, 56, 55, 10, 97, 121, 51, 98, 102, 87, 65, 102, 106, 72, 49, 77, 66, 99, 76, 114, 65, 82, 89, 86, 109, 66, 83, 79, 48, 90, 66, 51, 73, 106, 47, 115, 119, 106, 109, 52, 101, 84, 114, 119, 83, 83, 84, 105, 108, 90, 72, 99, 89, 84, 83, 83, 106, 70, 82, 48, 55, 55, 70, 57, 106, 65, 72, 105, 79, 72, 51, 66, 88, 50, 112, 102, 74, 76, 75, 79, 10, 89, 104, 101, 116, 101, 83, 67, 116, 113, 120, 50, 51, 52, 76, 83, 87, 83, 69, 57, 109, 81, 120, 65, 71, 70, 105, 81, 68, 52, 101, 67, 99, 106, 115, 90, 71, 84, 52, 52, 97, 109, 101, 71, 80, 117, 89, 52, 122, 98, 71, 110, 101, 87, 75, 50, 103, 68, 113, 100, 107, 86, 66, 70, 112, 82, 71, 90, 80, 84, 66, 75, 110, 106, 105, 120, 57, 10, 120, 78, 82, 98, 120, 81, 65, 48, 77, 77, 72, 90, 109, 102, 52, 121, 122, 103, 101, 69, 116, 69, 55, 78, 67, 118, 56, 50, 84, 87, 76, 120, 112, 50, 78, 88, 53, 78, 116, 113, 112, 54, 54, 47, 75, 55, 110, 74, 53, 114, 73, 110, 105, 101, 86, 43, 109, 104, 120, 78, 97, 77, 98, 66, 71, 78, 52, 122, 75, 49, 70, 71, 83, 120, 121, 79, 10, 57, 122, 48, 77, 43, 89, 111, 48, 70, 77, 84, 55, 77, 122, 85, 106, 56, 99, 122, 120, 75, 115, 101, 108, 117, 55, 67, 105, 122, 118, 53, 84, 97, 48, 49, 66, 71, 50, 89, 111, 115, 112, 98, 54, 112, 54, 52, 75, 84, 114, 107, 53, 77, 48, 83, 99, 100, 77, 71, 84, 72, 80, 106, 103, 110, 105, 81, 108, 81, 47, 71, 98, 73, 52, 75, 113, 10, 51, 121, 119, 103, 115, 78, 119, 50, 84, 103, 79, 122, 102, 65, 76, 85, 53, 110, 115, 97, 113, 111, 99, 84, 118, 122, 54, 104, 100, 76, 117, 98, 68, 117, 72, 65, 107, 53, 47, 88, 112, 71, 98, 75, 117, 120, 115, 55, 52, 122, 68, 48, 77, 49, 109, 75, 66, 51, 73, 68, 86, 101, 100, 122, 97, 103, 77, 120, 98, 109, 43, 87, 71, 43, 79, 105, 10, 110, 54, 43, 83, 120, 43, 51, 49, 81, 114, 99, 108, 84, 68, 115, 84, 66, 77, 56, 99, 108, 113, 56, 99, 73, 113, 80, 81, 113, 119, 87, 121, 84, 66, 73, 106, 85, 116, 122, 57, 71, 86, 115, 110, 110, 66, 52, 55, 101, 118, 49, 67, 73, 57, 115, 106, 103, 66, 80, 119, 118, 70, 69, 86, 86, 74, 83, 109, 100, 122, 55, 81, 100, 70, 71, 57, 10, 85, 82, 81, 73, 79, 84, 102, 76, 72, 122, 83, 112, 77, 74, 49, 83, 104, 67, 53, 86, 107, 76, 71, 54, 51, 49, 85, 65, 67, 57, 104, 87, 76, 98, 70, 74, 83, 88, 75, 65, 113, 87, 76, 88, 119, 80, 89, 89, 69, 81, 82, 86, 122, 88, 82, 55, 122, 50, 70, 119, 101, 102, 82, 55, 76, 70, 120, 99, 107, 118, 122, 108, 117, 70, 113, 114, 10, 84, 74, 79, 86, 111, 83, 102, 117, 112, 98, 55, 80, 99, 83, 78, 67, 117, 112, 116, 50, 76, 81, 73, 68, 65, 81, 65, 66, 111, 50, 77, 119, 89, 84, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 10, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 108, 48, 89, 104, 86, 121, 69, 49, 50, 106, 90, 86, 120, 47, 80, 120, 78, 51, 68, 108, 67, 80, 97, 84, 75, 98, 89, 119, 72, 119, 89, 68, 86, 82, 48, 106, 66, 66, 103, 119, 70, 111, 65, 85, 108, 48, 89, 104, 86, 121, 69, 49, 50, 106, 90, 86, 120, 47, 80, 120, 10, 78, 51, 68, 108, 67, 80, 97, 84, 75, 98, 89, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 73, 66, 65, 66, 51, 100, 65, 109, 66, 56, 52, 68, 87, 110, 53, 112, 104, 55, 54, 107, 84, 79, 90, 48, 66, 80, 56, 112, 78, 117, 90, 116, 81, 53, 105, 83, 97, 115, 48, 48, 48, 69, 10, 80, 76, 117, 72, 73, 84, 56, 51, 57, 72, 69, 108, 50, 107, 117, 54, 113, 53, 97, 67, 103, 90, 71, 50, 55, 100, 109, 120, 112, 71, 87, 88, 52, 109, 57, 107, 87, 97, 83, 87, 55, 109, 68, 75, 72, 121, 80, 55, 82, 98, 114, 47, 106, 121, 84, 119, 121, 113, 107, 120, 102, 51, 107, 102, 103, 76, 77, 116, 77, 114, 112, 107, 90, 50, 67, 118, 10, 117, 86, 110, 78, 51, 53, 112, 74, 48, 54, 105, 67, 115, 102, 109, 89, 108, 73, 114, 77, 52, 76, 118, 103, 66, 66, 117, 90, 89, 76, 70, 71, 90, 100, 119, 73, 111, 114, 74, 71, 110, 107, 83, 73, 54, 112, 78, 43, 86, 120, 98, 83, 70, 88, 74, 102, 76, 107, 117, 114, 49, 74, 49, 106, 117, 79, 78, 73, 53, 102, 54, 69, 76, 108, 103, 75, 10, 110, 48, 77, 100, 47, 114, 99, 89, 107, 111, 90, 68, 83, 119, 54, 99, 77, 111, 89, 115, 89, 80, 88, 112, 83, 79, 113, 86, 55, 88, 65, 112, 56, 100, 85, 118, 47, 84, 87, 48, 86, 56, 47, 98, 104, 85, 105, 90, 117, 99, 74, 118, 98, 73, 47, 78, 101, 74, 87, 115, 90, 67, 106, 57, 86, 114, 68, 68, 98, 56, 79, 43, 87, 86, 76, 104, 10, 88, 52, 83, 80, 103, 80, 76, 48, 68, 84, 97, 116, 100, 114, 79, 106, 116, 101, 70, 107, 100, 106, 112, 89, 51, 72, 49, 80, 88, 108, 90, 115, 53, 86, 86, 90, 86, 54, 88, 102, 56, 89, 112, 109, 77, 73, 122, 85, 85, 109, 73, 52, 100, 55, 83, 43, 75, 78, 102, 75, 78, 115, 83, 98, 66, 102, 68, 52, 70, 100, 118, 98, 56, 101, 56, 48, 10, 110, 82, 49, 52, 83, 111, 104, 87, 90, 50, 53, 103, 47, 52, 47, 73, 105, 43, 71, 79, 118, 85, 75, 112, 77, 119, 112, 90, 81, 104, 73, 83, 75, 118, 113, 120, 110, 85, 79, 79, 66, 90, 117, 90, 50, 109, 75, 116, 86, 122, 97, 122, 72, 98, 89, 78, 101, 83, 50, 87, 117, 79, 118, 121, 68, 69, 115, 77, 112, 90, 84, 71, 77, 75, 99, 109, 10, 71, 83, 51, 116, 84, 65, 90, 81, 77, 80, 72, 57, 87, 68, 50, 53, 83, 120, 100, 102, 71, 98, 82, 113, 104, 70, 83, 48, 79, 69, 56, 53, 111, 103, 50, 87, 97, 77, 77, 111, 108, 80, 51, 116, 76, 82, 57, 75, 97, 48, 79, 87, 76, 112, 65, 66, 69, 80, 115, 52, 112, 111, 69, 76, 48, 76, 57, 49, 48, 57, 83, 53, 122, 118, 69, 47, 10, 98, 119, 52, 99, 72, 106, 100, 120, 53, 82, 105, 72, 100, 82, 107, 47, 85, 76, 108, 101, 112, 69, 85, 48, 114, 98, 68, 75, 53, 117, 85, 84, 100, 103, 56, 120, 70, 75, 109, 79, 76, 90, 84, 87, 49, 89, 86, 78, 99, 120, 86, 80, 83, 47, 75, 121, 80, 117, 49, 115, 118, 102, 48, 79, 110, 87, 90, 122, 115, 68, 50, 48, 57, 55, 43, 111, 10, 52, 66, 71, 107, 120, 75, 53, 49, 67, 85, 112, 106, 65, 69, 103, 103, 112, 115, 97, 100, 67, 119, 109, 75, 116, 79, 68, 109, 122, 106, 55, 72, 80, 105, 89, 52, 54, 83, 118, 101, 112, 103, 104, 74, 65, 119, 83, 81, 105, 117, 109, 80, 118, 43, 105, 50, 116, 67, 113, 106, 73, 52, 48, 99, 72, 76, 73, 53, 107, 113, 105, 80, 65, 108, 120, 65, 10, 79, 88, 88, 85, 99, 48, 69, 67, 100, 57, 55, 78, 52, 69, 79, 72, 49, 117, 83, 54, 83, 115, 78, 115, 69, 110, 47, 43, 75, 117, 89, 106, 49, 111, 120, 120, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 79, 112, 101, 110, 84, 114, 117, 115, 116, 32, 82, 111, 111, 116, 32, 67, 65, 32, 71, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 98, 122, 67, 67, 65, 49, 101, 103, 65, 119, 73, 66, 65, 103, 73, 83, 69, 83, 67, 104, 97, 82, 117, 47, 118, 98, 109, 57, 85, 112, 97, 80, 73, 43, 104, 73, 118, 121, 89, 82, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 68, 81, 85, 65, 77, 69, 65, 120, 67, 122, 65, 74, 66, 103, 78, 86, 10, 66, 65, 89, 84, 65, 107, 90, 83, 77, 82, 73, 119, 69, 65, 89, 68, 86, 81, 81, 75, 68, 65, 108, 80, 99, 71, 86, 117, 86, 72, 74, 49, 99, 51, 81, 120, 72, 84, 65, 98, 66, 103, 78, 86, 66, 65, 77, 77, 70, 69, 57, 119, 90, 87, 53, 85, 99, 110, 86, 122, 100, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 69, 99, 121, 10, 77, 66, 52, 88, 68, 84, 69, 48, 77, 68, 85, 121, 78, 106, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 77, 52, 77, 68, 69, 120, 78, 84, 65, 119, 77, 68, 65, 119, 77, 70, 111, 119, 81, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 108, 73, 120, 69, 106, 65, 81, 66, 103, 78, 86, 66, 65, 111, 77, 10, 67, 85, 57, 119, 90, 87, 53, 85, 99, 110, 86, 122, 100, 68, 69, 100, 77, 66, 115, 71, 65, 49, 85, 69, 65, 119, 119, 85, 84, 51, 66, 108, 98, 108, 82, 121, 100, 88, 78, 48, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 82, 122, 73, 119, 103, 103, 73, 105, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 10, 65, 81, 85, 65, 65, 52, 73, 67, 68, 119, 65, 119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 68, 77, 116, 108, 101, 108, 77, 53, 81, 81, 103, 84, 74, 84, 51, 50, 70, 43, 68, 51, 89, 53, 122, 49, 122, 67, 85, 51, 85, 100, 83, 88, 113, 87, 79, 78, 50, 105, 99, 50, 114, 120, 98, 57, 53, 101, 111, 108, 113, 53, 99, 83, 71, 43, 10, 78, 116, 109, 104, 47, 76, 122, 117, 98, 75, 104, 56, 78, 66, 112, 120, 71, 117, 103, 97, 50, 70, 56, 79, 82, 65, 98, 116, 112, 43, 68, 122, 48, 109, 69, 76, 52, 68, 75, 105, 108, 116, 69, 52, 56, 77, 76, 97, 65, 82, 102, 56, 53, 75, 120, 80, 54, 79, 54, 74, 72, 110, 83, 114, 84, 55, 56, 101, 67, 98, 89, 50, 97, 108, 98, 122, 10, 52, 101, 54, 87, 105, 87, 89, 107, 66, 117, 84, 78, 81, 106, 112, 75, 51, 101, 67, 97, 115, 77, 83, 67, 82, 98, 80, 43, 121, 97, 116, 99, 102, 68, 55, 74, 54, 120, 99, 118, 68, 72, 49, 117, 114, 113, 87, 80, 121, 75, 119, 108, 67, 109, 47, 54, 49, 85, 87, 89, 48, 106, 85, 74, 57, 103, 78, 68, 108, 80, 55, 90, 118, 121, 67, 86, 10, 101, 89, 67, 89, 105, 116, 109, 74, 78, 98, 116, 82, 71, 54, 81, 51, 102, 102, 121, 90, 79, 54, 118, 47, 118, 54, 119, 78, 106, 48, 79, 120, 109, 88, 115, 87, 69, 72, 52, 100, 98, 48, 102, 69, 70, 89, 56, 69, 108, 103, 103, 71, 81, 103, 84, 52, 104, 78, 89, 100, 118, 74, 71, 109, 81, 114, 53, 74, 49, 87, 113, 73, 80, 55, 119, 116, 10, 85, 100, 71, 101, 106, 101, 66, 83, 122, 70, 102, 100, 78, 84, 86, 89, 50, 55, 83, 80, 74, 73, 106, 107, 105, 57, 47, 99, 97, 49, 84, 83, 103, 83, 117, 121, 122, 112, 74, 76, 72, 66, 57, 71, 43, 104, 51, 89, 107, 115, 116, 50, 90, 55, 85, 74, 109, 81, 110, 108, 114, 66, 99, 85, 86, 88, 68, 71, 80, 75, 66, 87, 67, 103, 79, 122, 10, 51, 71, 73, 90, 51, 56, 105, 49, 77, 72, 47, 49, 80, 67, 90, 49, 69, 98, 51, 88, 71, 55, 79, 72, 110, 103, 101, 118, 90, 88, 72, 108, 111, 77, 56, 97, 112, 119, 107, 81, 72, 90, 79, 74, 90, 108, 118, 111, 80, 71, 73, 121, 116, 98, 85, 54, 98, 117, 109, 70, 65, 89, 117, 101, 81, 52, 120, 110, 99, 121, 104, 90, 87, 43, 118, 106, 10, 51, 67, 122, 77, 112, 83, 90, 121, 89, 104, 75, 48, 53, 112, 121, 68, 82, 80, 90, 82, 112, 79, 76, 65, 101, 105, 82, 88, 121, 103, 54, 108, 80, 122, 113, 49, 79, 52, 118, 108, 100, 117, 53, 119, 53, 112, 76, 101, 70, 108, 119, 111, 87, 53, 99, 90, 74, 53, 76, 43, 101, 112, 74, 85, 122, 112, 77, 53, 67, 104, 97, 72, 118, 71, 79, 122, 10, 57, 98, 71, 84, 88, 79, 66, 117, 116, 57, 68, 113, 43, 87, 73, 121, 105, 69, 84, 55, 118, 121, 99, 111, 116, 106, 67, 86, 88, 82, 73, 111, 117, 90, 87, 43, 106, 49, 77, 89, 53, 97, 73, 89, 70, 117, 74, 87, 112, 76, 73, 115, 69, 80, 85, 100, 78, 54, 98, 52, 116, 47, 98, 81, 87, 86, 121, 74, 57, 56, 76, 86, 116, 90, 82, 48, 10, 48, 100, 88, 43, 71, 55, 98, 119, 53, 116, 89, 101, 101, 57, 73, 56, 121, 54, 106, 106, 57, 82, 106, 122, 73, 82, 57, 117, 55, 48, 49, 111, 66, 110, 115, 116, 88, 87, 53, 68, 105, 97, 98, 65, 43, 97, 67, 47, 103, 104, 55, 80, 85, 51, 43, 48, 54, 121, 122, 98, 88, 102, 90, 113, 102, 85, 65, 107, 66, 88, 75, 74, 79, 65, 71, 84, 10, 121, 51, 72, 67, 79, 86, 48, 71, 69, 102, 90, 118, 101, 80, 103, 51, 68, 84, 109, 69, 74, 119, 73, 68, 65, 81, 65, 66, 111, 50, 77, 119, 89, 84, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 10, 47, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 97, 106, 110, 54, 81, 105, 76, 51, 53, 111, 107, 65, 84, 86, 53, 57, 77, 52, 80, 76, 117, 71, 53, 51, 104, 113, 56, 119, 72, 119, 89, 68, 86, 82, 48, 106, 66, 66, 103, 119, 70, 111, 65, 85, 97, 106, 110, 54, 81, 105, 76, 51, 53, 111, 107, 65, 84, 86, 53, 57, 10, 77, 52, 80, 76, 117, 71, 53, 51, 104, 113, 56, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 78, 66, 81, 65, 68, 103, 103, 73, 66, 65, 74, 106, 76, 113, 48, 65, 56, 53, 84, 77, 67, 108, 51, 56, 116, 104, 54, 97, 80, 49, 70, 53, 75, 114, 55, 103, 101, 53, 55, 116, 120, 43, 52, 66, 107, 74, 97, 109, 122, 10, 71, 106, 53, 111, 88, 83, 99, 109, 112, 55, 111, 113, 52, 102, 66, 88, 103, 119, 112, 107, 84, 120, 52, 105, 100, 66, 118, 112, 107, 70, 47, 119, 114, 77, 47, 47, 84, 50, 104, 54, 79, 75, 81, 81, 98, 65, 50, 120, 120, 54, 82, 51, 103, 66, 105, 50, 111, 105, 104, 69, 100, 113, 99, 48, 110, 88, 71, 69, 76, 56, 112, 90, 48, 107, 101, 73, 10, 109, 85, 69, 105, 121, 84, 67, 89, 89, 87, 52, 57, 113, 75, 103, 70, 98, 100, 69, 102, 119, 70, 70, 69, 86, 110, 56, 110, 78, 81, 76, 100, 88, 112, 103, 75, 81, 117, 115, 119, 118, 52, 50, 104, 109, 49, 71, 113, 79, 43, 113, 84, 82, 109, 84, 70, 65, 72, 110, 101, 73, 87, 118, 50, 86, 54, 67, 71, 49, 119, 90, 121, 55, 72, 66, 71, 10, 83, 52, 116, 122, 51, 97, 65, 104, 100, 84, 55, 99, 72, 99, 67, 80, 48, 48, 57, 122, 72, 73, 88, 90, 47, 110, 57, 105, 121, 74, 86, 118, 116, 116, 78, 55, 106, 76, 112, 84, 119, 109, 43, 98, 82, 69, 120, 53, 48, 66, 49, 119, 115, 57, 101, 102, 65, 118, 83, 121, 66, 55, 68, 72, 53, 102, 105, 116, 73, 119, 54, 109, 86, 115, 107, 112, 10, 69, 110, 100, 73, 50, 83, 57, 71, 47, 84, 118, 119, 47, 72, 82, 119, 107, 113, 87, 79, 79, 65, 103, 102, 90, 68, 67, 50, 116, 48, 118, 55, 78, 113, 119, 81, 106, 113, 66, 83, 77, 50, 79, 100, 65, 122, 86, 87, 120, 87, 109, 57, 120, 105, 78, 97, 74, 53, 84, 50, 112, 66, 76, 52, 76, 84, 77, 56, 111, 86, 97, 108, 88, 57, 89, 90, 10, 54, 101, 49, 56, 67, 76, 49, 51, 122, 83, 100, 107, 122, 74, 84, 97, 84, 107, 90, 81, 104, 43, 68, 53, 119, 86, 79, 65, 72, 114, 117, 116, 43, 48, 100, 83, 105, 120, 118, 57, 111, 118, 110, 101, 68, 105, 75, 51, 80, 84, 78, 90, 98, 78, 84, 101, 57, 90, 85, 71, 77, 103, 49, 82, 71, 85, 70, 99, 80, 107, 56, 71, 57, 55, 107, 114, 10, 103, 67, 102, 50, 111, 54, 112, 54, 102, 65, 98, 104, 81, 56, 77, 84, 79, 87, 73, 97, 78, 114, 51, 103, 75, 67, 54, 85, 65, 117, 81, 112, 76, 109, 66, 86, 114, 107, 65, 57, 115, 72, 83, 83, 88, 118, 65, 103, 90, 74, 89, 47, 88, 48, 86, 100, 105, 76, 87, 75, 50, 103, 75, 103, 87, 48, 86, 85, 51, 106, 103, 57, 67, 99, 67, 111, 10, 83, 109, 86, 71, 70, 118, 121, 113, 118, 49, 82, 79, 84, 86, 117, 43, 79, 69, 79, 51, 75, 77, 113, 76, 77, 54, 111, 97, 74, 98, 111, 108, 88, 67, 107, 118, 87, 48, 112, 117, 106, 79, 111, 116, 110, 67, 114, 50, 66, 88, 98, 103, 100, 53, 101, 65, 105, 78, 49, 110, 69, 50, 56, 100, 97, 67, 83, 76, 84, 55, 100, 48, 103, 101, 88, 48, 10, 89, 74, 57, 54, 86, 100, 99, 43, 78, 57, 111, 87, 97, 122, 53, 51, 114, 75, 52, 89, 99, 74, 85, 73, 101, 83, 107, 68, 105, 118, 55, 66, 79, 55, 77, 47, 71, 103, 43, 107, 79, 49, 52, 102, 87, 75, 71, 86, 121, 97, 115, 118, 99, 48, 114, 81, 76, 87, 54, 97, 87, 81, 57, 86, 71, 72, 103, 116, 80, 70, 71, 109, 108, 52, 118, 109, 10, 117, 55, 74, 119, 113, 107, 119, 82, 51, 118, 57, 56, 75, 122, 102, 85, 101, 116, 70, 51, 78, 73, 47, 110, 43, 85, 76, 51, 80, 73, 69, 77, 83, 49, 73, 75, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 79, 112, 101, 110, 84, 114, 117, 115, 116, 32, 82, 111, 111, 116, 32, 67, 65, 32, 71, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 73, 84, 67, 67, 65, 97, 97, 103, 65, 119, 73, 66, 65, 103, 73, 83, 69, 83, 68, 109, 43, 69, 122, 56, 74, 76, 67, 43, 66, 85, 67, 115, 50, 111, 77, 98, 78, 71, 65, 47, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 68, 77, 69, 65, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 10, 65, 107, 90, 83, 77, 82, 73, 119, 69, 65, 89, 68, 86, 81, 81, 75, 68, 65, 108, 80, 99, 71, 86, 117, 86, 72, 74, 49, 99, 51, 81, 120, 72, 84, 65, 98, 66, 103, 78, 86, 66, 65, 77, 77, 70, 69, 57, 119, 90, 87, 53, 85, 99, 110, 86, 122, 100, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 69, 99, 122, 77, 66, 52, 88, 10, 68, 84, 69, 48, 77, 68, 85, 121, 78, 106, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 77, 52, 77, 68, 69, 120, 78, 84, 65, 119, 77, 68, 65, 119, 77, 70, 111, 119, 81, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 82, 108, 73, 120, 69, 106, 65, 81, 66, 103, 78, 86, 66, 65, 111, 77, 67, 85, 57, 119, 10, 90, 87, 53, 85, 99, 110, 86, 122, 100, 68, 69, 100, 77, 66, 115, 71, 65, 49, 85, 69, 65, 119, 119, 85, 84, 51, 66, 108, 98, 108, 82, 121, 100, 88, 78, 48, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 82, 122, 77, 119, 100, 106, 65, 81, 66, 103, 99, 113, 104, 107, 106, 79, 80, 81, 73, 66, 66, 103, 85, 114, 103, 81, 81, 65, 10, 73, 103, 78, 105, 65, 65, 82, 75, 55, 108, 105, 117, 84, 99, 112, 109, 51, 103, 89, 54, 111, 120, 72, 56, 52, 66, 106, 119, 98, 104, 121, 54, 76, 84, 65, 77, 105, 100, 110, 87, 55, 112, 116, 122, 103, 54, 107, 106, 70, 89, 119, 118, 87, 89, 112, 97, 51, 82, 84, 113, 110, 86, 107, 114, 81, 55, 99, 71, 55, 68, 75, 50, 117, 117, 53, 66, 10, 116, 97, 49, 100, 111, 89, 88, 77, 54, 104, 48, 85, 90, 113, 78, 110, 102, 107, 98, 105, 108, 80, 80, 110, 116, 108, 97, 104, 70, 86, 109, 104, 84, 122, 101, 88, 117, 83, 73, 101, 118, 82, 72, 114, 57, 76, 73, 102, 88, 115, 77, 85, 109, 117, 88, 90, 108, 53, 109, 106, 89, 122, 66, 104, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 10, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 72, 100, 56, 77, 85, 105, 50, 73, 53, 68, 77, 108, 118, 52, 86, 66, 78, 48, 66, 66, 89, 51, 74, 87, 73, 98, 84, 65, 102, 10, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 82, 72, 100, 56, 77, 85, 105, 50, 73, 53, 68, 77, 108, 118, 52, 86, 66, 78, 48, 66, 66, 89, 51, 74, 87, 73, 98, 84, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 119, 78, 112, 65, 68, 66, 109, 65, 106, 69, 65, 106, 54, 106, 99, 110, 98, 111, 77, 10, 66, 66, 102, 54, 70, 101, 107, 57, 76, 121, 107, 66, 108, 55, 43, 66, 70, 106, 78, 65, 107, 50, 122, 56, 43, 101, 50, 65, 99, 71, 43, 113, 106, 57, 117, 69, 119, 111, 118, 49, 78, 99, 111, 71, 51, 71, 82, 118, 97, 66, 98, 104, 106, 53, 71, 53, 65, 106, 69, 65, 50, 69, 117, 108, 121, 56, 76, 81, 67, 71, 122, 112, 71, 80, 116, 97, 10, 51, 85, 49, 102, 74, 65, 117, 119, 65, 67, 69, 108, 55, 52, 43, 110, 66, 67, 90, 120, 52, 110, 120, 112, 53, 86, 50, 97, 43, 69, 69, 102, 79, 122, 109, 84, 107, 53, 49, 86, 54, 115, 50, 78, 56, 102, 118, 66, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 73, 83, 82, 71, 32, 82, 111, 111, 116, 32, 88, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 97, 122, 67, 67, 65, 49, 79, 103, 65, 119, 73, 66, 65, 103, 73, 82, 65, 73, 73, 81, 122, 55, 68, 83, 81, 79, 78, 90, 82, 71, 80, 103, 117, 50, 79, 67, 105, 119, 65, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 84, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 10, 66, 104, 77, 67, 86, 86, 77, 120, 75, 84, 65, 110, 66, 103, 78, 86, 66, 65, 111, 84, 73, 69, 108, 117, 100, 71, 86, 121, 98, 109, 86, 48, 73, 70, 78, 108, 89, 51, 86, 121, 97, 88, 82, 53, 73, 70, 74, 108, 99, 50, 86, 104, 99, 109, 78, 111, 73, 69, 100, 121, 98, 51, 86, 119, 77, 82, 85, 119, 69, 119, 89, 68, 86, 81, 81, 68, 10, 69, 119, 120, 74, 85, 49, 74, 72, 73, 70, 74, 118, 98, 51, 81, 103, 87, 68, 69, 119, 72, 104, 99, 78, 77, 84, 85, 119, 78, 106, 65, 48, 77, 84, 69, 119, 78, 68, 77, 52, 87, 104, 99, 78, 77, 122, 85, 119, 78, 106, 65, 48, 77, 84, 69, 119, 78, 68, 77, 52, 87, 106, 66, 80, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 112, 77, 67, 99, 71, 65, 49, 85, 69, 67, 104, 77, 103, 83, 87, 53, 48, 90, 88, 74, 117, 90, 88, 81, 103, 85, 50, 86, 106, 100, 88, 74, 112, 100, 72, 107, 103, 85, 109, 86, 122, 90, 87, 70, 121, 89, 50, 103, 103, 82, 51, 74, 118, 100, 88, 65, 120, 70, 84, 65, 84, 66, 103, 78, 86, 66, 65, 77, 84, 10, 68, 69, 108, 84, 85, 107, 99, 103, 85, 109, 57, 118, 100, 67, 66, 89, 77, 84, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 75, 51, 111, 74, 72, 80, 48, 70, 68, 102, 122, 109, 53, 52, 114, 10, 86, 121, 103, 99, 104, 55, 55, 99, 116, 57, 56, 52, 107, 73, 120, 117, 80, 79, 90, 88, 111, 72, 106, 51, 100, 99, 75, 105, 47, 118, 86, 113, 98, 118, 89, 65, 84, 121, 106, 98, 51, 109, 105, 71, 98, 69, 83, 84, 116, 114, 70, 106, 47, 82, 81, 83, 97, 55, 56, 102, 48, 117, 111, 120, 109, 121, 70, 43, 48, 84, 77, 56, 117, 107, 106, 49, 10, 51, 88, 110, 102, 115, 55, 106, 47, 69, 118, 69, 104, 109, 107, 118, 66, 105, 111, 90, 120, 97, 85, 112, 109, 90, 109, 121, 80, 102, 106, 120, 119, 118, 54, 48, 112, 73, 103, 98, 122, 53, 77, 68, 109, 103, 75, 55, 105, 83, 52, 43, 51, 109, 88, 54, 85, 65, 53, 47, 84, 82, 53, 100, 56, 109, 85, 103, 106, 85, 43, 103, 52, 114, 107, 56, 75, 10, 98, 52, 77, 117, 48, 85, 108, 88, 106, 73, 66, 48, 116, 116, 111, 118, 48, 68, 105, 78, 101, 119, 78, 119, 73, 82, 116, 49, 56, 106, 65, 56, 43, 111, 43, 117, 51, 100, 112, 106, 113, 43, 115, 87, 84, 56, 75, 79, 69, 85, 116, 43, 122, 119, 118, 111, 47, 55, 86, 51, 76, 118, 83, 121, 101, 48, 114, 103, 84, 66, 73, 108, 68, 72, 67, 78, 10, 65, 121, 109, 103, 52, 86, 77, 107, 55, 66, 80, 90, 55, 104, 109, 47, 69, 76, 78, 75, 106, 68, 43, 74, 111, 50, 70, 82, 51, 113, 121, 72, 66, 53, 84, 48, 89, 51, 72, 115, 76, 117, 74, 118, 87, 53, 105, 66, 52, 89, 108, 99, 78, 72, 108, 115, 100, 117, 56, 55, 107, 71, 74, 53, 53, 116, 117, 107, 109, 105, 56, 109, 120, 100, 65, 81, 10, 52, 81, 55, 101, 50, 82, 67, 79, 70, 118, 117, 51, 57, 54, 106, 51, 120, 43, 85, 67, 66, 53, 105, 80, 78, 103, 105, 86, 53, 43, 73, 51, 108, 103, 48, 50, 100, 90, 55, 55, 68, 110, 75, 120, 72, 90, 117, 56, 65, 47, 108, 74, 66, 100, 105, 66, 51, 81, 87, 48, 75, 116, 90, 66, 54, 97, 119, 66, 100, 112, 85, 75, 68, 57, 106, 102, 10, 49, 98, 48, 83, 72, 122, 85, 118, 75, 66, 100, 115, 48, 112, 106, 66, 113, 65, 108, 107, 100, 50, 53, 72, 78, 55, 114, 79, 114, 70, 108, 101, 97, 74, 49, 47, 99, 116, 97, 74, 120, 81, 90, 66, 75, 84, 53, 90, 80, 116, 48, 109, 57, 83, 84, 74, 69, 97, 100, 97, 111, 48, 120, 65, 72, 48, 97, 104, 109, 98, 87, 110, 79, 108, 70, 117, 10, 104, 106, 117, 101, 102, 88, 75, 110, 69, 103, 86, 52, 87, 101, 48, 43, 85, 88, 103, 86, 67, 119, 79, 80, 106, 100, 65, 118, 66, 98, 73, 43, 101, 48, 111, 99, 83, 51, 77, 70, 69, 118, 122, 71, 54, 117, 66, 81, 69, 51, 120, 68, 107, 51, 83, 122, 121, 110, 84, 110, 106, 104, 56, 66, 67, 78, 65, 119, 49, 70, 116, 120, 78, 114, 81, 72, 10, 117, 115, 69, 119, 77, 70, 120, 73, 116, 52, 73, 55, 109, 75, 90, 57, 89, 73, 113, 105, 111, 121, 109, 67, 122, 76, 113, 57, 103, 119, 81, 98, 111, 111, 77, 68, 81, 97, 72, 87, 66, 102, 69, 98, 119, 114, 98, 119, 113, 72, 121, 71, 79, 48, 97, 111, 83, 67, 113, 73, 51, 72, 97, 97, 100, 114, 56, 102, 97, 113, 85, 57, 71, 89, 47, 114, 10, 79, 80, 78, 107, 51, 115, 103, 114, 68, 81, 111, 111, 47, 47, 102, 98, 52, 104, 86, 67, 49, 67, 76, 81, 74, 49, 51, 104, 101, 102, 52, 89, 53, 51, 67, 73, 114, 85, 55, 109, 50, 89, 115, 54, 120, 116, 48, 110, 85, 87, 55, 47, 118, 71, 84, 49, 77, 48, 78, 80, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 77, 65, 52, 71, 10, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 80, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 82, 53, 116, 70, 110, 109, 101, 55, 98, 108, 53, 65, 70, 122, 103, 65, 105, 73, 121, 66, 112, 89, 10, 57, 117, 109, 98, 98, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, 67, 65, 103, 69, 65, 86, 82, 57, 89, 113, 98, 121, 121, 113, 70, 68, 81, 68, 76, 72, 89, 71, 109, 107, 103, 74, 121, 107, 73, 114, 71, 70, 49, 88, 73, 112, 117, 43, 73, 76, 108, 97, 83, 47, 86, 57, 108, 90, 76, 10, 117, 98, 104, 122, 69, 70, 110, 84, 73, 90, 100, 43, 53, 48, 120, 120, 43, 55, 76, 83, 89, 75, 48, 53, 113, 65, 118, 113, 70, 121, 70, 87, 104, 102, 70, 81, 68, 108, 110, 114, 122, 117, 66, 90, 54, 98, 114, 74, 70, 101, 43, 71, 110, 89, 43, 69, 103, 80, 98, 107, 54, 90, 71, 81, 51, 66, 101, 98, 89, 104, 116, 70, 56, 71, 97, 86, 10, 48, 110, 120, 118, 119, 117, 111, 55, 55, 120, 47, 80, 121, 57, 97, 117, 74, 47, 71, 112, 115, 77, 105, 117, 47, 88, 49, 43, 109, 118, 111, 105, 66, 79, 118, 47, 50, 88, 47, 113, 107, 83, 115, 105, 115, 82, 99, 79, 106, 47, 75, 75, 78, 70, 116, 89, 50, 80, 119, 66, 121, 86, 83, 53, 117, 67, 98, 77, 105, 111, 103, 122, 105, 85, 119, 116, 10, 104, 68, 121, 67, 51, 43, 54, 87, 86, 119, 87, 54, 76, 76, 118, 51, 120, 76, 102, 72, 84, 106, 117, 67, 118, 106, 72, 73, 73, 110, 78, 122, 107, 116, 72, 67, 103, 75, 81, 53, 79, 82, 65, 122, 73, 52, 74, 77, 80, 74, 43, 71, 115, 108, 87, 89, 72, 98, 52, 112, 104, 111, 119, 105, 109, 53, 55, 105, 97, 122, 116, 88, 79, 111, 74, 119, 10, 84, 100, 119, 74, 120, 52, 110, 76, 67, 103, 100, 78, 98, 79, 104, 100, 106, 115, 110, 118, 122, 113, 118, 72, 117, 55, 85, 114, 84, 107, 88, 87, 83, 116, 65, 109, 122, 79, 86, 121, 121, 103, 104, 113, 112, 90, 88, 106, 70, 97, 72, 51, 112, 79, 51, 74, 76, 70, 43, 108, 43, 47, 43, 115, 75, 65, 73, 117, 118, 116, 100, 55, 117, 43, 78, 120, 10, 101, 53, 65, 87, 48, 119, 100, 101, 82, 108, 78, 56, 78, 119, 100, 67, 106, 78, 80, 69, 108, 112, 122, 86, 109, 98, 85, 113, 52, 74, 85, 97, 103, 69, 105, 117, 84, 68, 107, 72, 122, 115, 120, 72, 112, 70, 75, 86, 75, 55, 113, 52, 43, 54, 51, 83, 77, 49, 78, 57, 53, 82, 49, 78, 98, 100, 87, 104, 115, 99, 100, 67, 98, 43, 90, 65, 10, 74, 122, 86, 99, 111, 121, 105, 51, 66, 52, 51, 110, 106, 84, 79, 81, 53, 121, 79, 102, 43, 49, 67, 99, 101, 87, 120, 71, 49, 98, 81, 86, 115, 53, 90, 117, 102, 112, 115, 77, 108, 106, 113, 52, 85, 105, 48, 47, 49, 108, 118, 104, 43, 119, 106, 67, 104, 80, 52, 107, 113, 75, 79, 74, 50, 113, 120, 113, 52, 82, 103, 113, 115, 97, 104, 68, 10, 89, 86, 118, 84, 72, 57, 119, 55, 106, 88, 98, 121, 76, 101, 105, 78, 100, 100, 56, 88, 77, 50, 119, 57, 85, 47, 116, 55, 121, 48, 70, 102, 47, 57, 121, 105, 48, 71, 69, 52, 52, 90, 97, 52, 114, 70, 50, 76, 78, 57, 100, 49, 49, 84, 80, 65, 109, 82, 71, 117, 110, 85, 72, 66, 99, 110, 87, 69, 118, 103, 74, 66, 81, 108, 57, 110, 10, 74, 69, 105, 85, 48, 90, 115, 110, 118, 103, 99, 47, 117, 98, 104, 80, 103, 88, 82, 82, 52, 88, 113, 51, 55, 90, 48, 106, 52, 114, 55, 103, 49, 83, 103, 69, 69, 122, 119, 120, 65, 53, 55, 100, 101, 109, 121, 80, 120, 103, 99, 89, 120, 110, 47, 101, 82, 52, 52, 47, 75, 74, 52, 69, 66, 115, 43, 108, 86, 68, 82, 51, 118, 101, 121, 74, 10, 109, 43, 107, 88, 81, 57, 57, 98, 50, 49, 47, 43, 106, 104, 53, 88, 111, 115, 49, 65, 110, 88, 53, 105, 73, 116, 114, 101, 71, 67, 99, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 67, 32, 82, 65, 73, 90, 32, 70, 78, 77, 84, 45, 82, 67, 77, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 103, 122, 67, 67, 65, 50, 117, 103, 65, 119, 73, 66, 65, 103, 73, 80, 88, 90, 79, 78, 77, 71, 99, 50, 121, 65, 89, 100, 71, 115, 100, 85, 104, 71, 107, 72, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, 67, 119, 85, 65, 77, 68, 115, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 10, 65, 107, 86, 84, 77, 82, 69, 119, 68, 119, 89, 68, 86, 81, 81, 75, 68, 65, 104, 71, 84, 107, 49, 85, 76, 86, 74, 68, 84, 84, 69, 90, 77, 66, 99, 71, 65, 49, 85, 69, 67, 119, 119, 81, 81, 85, 77, 103, 85, 107, 70, 74, 87, 105, 66, 71, 84, 107, 49, 85, 76, 86, 74, 68, 84, 84, 65, 101, 70, 119, 48, 119, 79, 68, 69, 119, 10, 77, 106, 107, 120, 78, 84, 85, 53, 78, 84, 90, 97, 70, 119, 48, 122, 77, 68, 65, 120, 77, 68, 69, 119, 77, 68, 65, 119, 77, 68, 66, 97, 77, 68, 115, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 107, 86, 84, 77, 82, 69, 119, 68, 119, 89, 68, 86, 81, 81, 75, 68, 65, 104, 71, 84, 107, 49, 85, 76, 86, 74, 68, 10, 84, 84, 69, 90, 77, 66, 99, 71, 65, 49, 85, 69, 67, 119, 119, 81, 81, 85, 77, 103, 85, 107, 70, 74, 87, 105, 66, 71, 84, 107, 49, 85, 76, 86, 74, 68, 84, 84, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 10, 103, 103, 73, 66, 65, 76, 112, 120, 103, 72, 112, 77, 104, 109, 53, 47, 121, 66, 78, 116, 119, 77, 90, 57, 72, 65, 67, 88, 106, 121, 119, 77, 73, 55, 115, 81, 109, 107, 67, 112, 71, 114, 101, 72, 105, 80, 105, 98, 86, 109, 114, 55, 53, 110, 117, 79, 105, 53, 75, 79, 112, 121, 86, 100, 87, 82, 72, 98, 78, 105, 54, 51, 85, 82, 99, 102, 10, 113, 81, 103, 102, 66, 66, 99, 107, 87, 75, 111, 51, 83, 104, 106, 102, 53, 84, 110, 85, 86, 47, 51, 88, 119, 83, 121, 82, 65, 90, 72, 105, 73, 116, 81, 68, 119, 70, 106, 56, 100, 48, 102, 115, 106, 122, 53, 48, 81, 55, 113, 115, 78, 73, 49, 78, 79, 72, 90, 110, 106, 114, 68, 73, 98, 122, 65, 122, 87, 72, 70, 99, 116, 80, 86, 114, 10, 98, 116, 81, 66, 85, 76, 103, 84, 102, 109, 120, 75, 111, 48, 110, 82, 73, 66, 110, 117, 118, 77, 65, 112, 71, 71, 87, 110, 51, 118, 55, 118, 51, 81, 113, 81, 73, 101, 99, 97, 90, 53, 74, 67, 69, 74, 104, 102, 84, 122, 67, 56, 80, 104, 120, 70, 116, 66, 68, 88, 97, 69, 65, 85, 119, 69, 68, 54, 53, 51, 99, 88, 101, 117, 89, 76, 10, 106, 50, 86, 98, 80, 78, 109, 97, 85, 116, 117, 49, 118, 90, 53, 71, 122, 122, 51, 114, 107, 81, 85, 67, 119, 74, 97, 121, 100, 107, 120, 78, 69, 74, 89, 55, 107, 118, 113, 99, 102, 119, 43, 90, 51, 55, 52, 106, 78, 85, 85, 101, 65, 108, 122, 43, 116, 97, 105, 98, 109, 83, 88, 97, 88, 118, 77, 105, 119, 122, 110, 49, 53, 67, 111, 117, 10, 48, 56, 89, 102, 120, 71, 121, 113, 120, 82, 120, 113, 65, 81, 86, 75, 76, 57, 76, 70, 119, 97, 103, 48, 74, 108, 49, 109, 112, 100, 73, 67, 73, 102, 107, 89, 116, 119, 98, 49, 84, 112, 108, 118, 113, 75, 116, 77, 85, 101, 106, 80, 85, 66, 106, 70, 100, 56, 103, 53, 67, 83, 120, 74, 107, 106, 75, 90, 113, 76, 115, 88, 70, 51, 109, 119, 10, 87, 115, 88, 109, 111, 56, 82, 90, 90, 85, 99, 49, 103, 49, 54, 112, 54, 68, 85, 76, 109, 98, 118, 107, 122, 83, 68, 71, 109, 48, 111, 71, 79, 98, 86, 111, 47, 67, 75, 54, 55, 108, 87, 77, 75, 48, 55, 113, 56, 55, 72, 106, 47, 76, 97, 90, 109, 116, 86, 67, 43, 110, 70, 78, 67, 77, 43, 72, 72, 109, 112, 120, 102, 102, 110, 84, 10, 116, 79, 109, 108, 99, 89, 70, 55, 119, 107, 53, 72, 108, 113, 88, 50, 100, 111, 87, 106, 75, 73, 47, 112, 103, 71, 54, 66, 85, 54, 86, 116, 88, 55, 104, 73, 43, 99, 76, 53, 78, 113, 89, 117, 83, 102, 43, 52, 108, 115, 75, 77, 66, 55, 79, 98, 105, 70, 106, 56, 54, 120, 115, 99, 51, 105, 49, 119, 52, 112, 101, 83, 77, 75, 71, 74, 10, 52, 55, 120, 86, 113, 67, 102, 87, 83, 43, 50, 81, 114, 89, 118, 54, 89, 121, 86, 90, 76, 97, 103, 49, 51, 99, 113, 88, 77, 55, 122, 108, 122, 99, 101, 100, 48, 101, 122, 118, 88, 103, 53, 75, 107, 65, 89, 109, 89, 54, 50, 53, 50, 84, 85, 116, 66, 55, 112, 50, 90, 83, 121, 115, 86, 52, 57, 57, 57, 65, 101, 85, 49, 52, 69, 67, 10, 108, 108, 50, 106, 66, 48, 110, 86, 101, 116, 66, 88, 43, 82, 118, 110, 85, 48, 90, 49, 113, 114, 66, 53, 81, 115, 116, 111, 99, 81, 106, 112, 89, 76, 48, 53, 97, 99, 55, 48, 114, 56, 78, 87, 81, 77, 101, 116, 85, 113, 73, 74, 53, 71, 43, 71, 82, 52, 111, 102, 54, 121, 103, 110, 88, 89, 77, 103, 114, 119, 84, 74, 98, 70, 97, 97, 10, 105, 48, 98, 49, 65, 103, 77, 66, 65, 65, 71, 106, 103, 89, 77, 119, 103, 89, 65, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 81, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 10, 70, 80, 100, 57, 120, 102, 51, 69, 54, 74, 111, 98, 100, 50, 83, 110, 57, 82, 50, 103, 122, 76, 43, 72, 89, 74, 112, 116, 77, 68, 52, 71, 65, 49, 85, 100, 73, 65, 81, 51, 77, 68, 85, 119, 77, 119, 89, 69, 86, 82, 48, 103, 65, 68, 65, 114, 77, 67, 107, 71, 67, 67, 115, 71, 65, 81, 85, 70, 66, 119, 73, 66, 70, 104, 49, 111, 10, 100, 72, 82, 119, 79, 105, 56, 118, 100, 51, 100, 51, 76, 109, 78, 108, 99, 110, 81, 117, 90, 109, 53, 116, 100, 67, 53, 108, 99, 121, 57, 107, 99, 71, 78, 122, 76, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, 67, 65, 103, 69, 65, 66, 53, 66, 75, 51, 47, 77, 106, 84, 118, 68, 68, 10, 110, 70, 70, 108, 109, 53, 119, 105, 111, 111, 111, 77, 104, 102, 78, 122, 75, 87, 116, 78, 47, 103, 72, 105, 113, 81, 120, 106, 65, 98, 56, 69, 90, 54, 87, 100, 109, 70, 47, 57, 65, 82, 80, 54, 55, 74, 112, 105, 54, 89, 98, 43, 116, 109, 76, 83, 98, 107, 121, 85, 43, 56, 66, 49, 82, 88, 120, 108, 68, 80, 105, 121, 78, 56, 43, 115, 10, 68, 56, 43, 78, 98, 47, 107, 90, 57, 52, 47, 115, 72, 118, 74, 119, 110, 118, 68, 75, 117, 79, 43, 51, 47, 51, 89, 51, 100, 108, 118, 50, 98, 111, 106, 122, 114, 50, 73, 121, 73, 112, 77, 78, 79, 109, 113, 79, 70, 71, 89, 77, 76, 86, 78, 48, 86, 50, 85, 101, 49, 98, 76, 100, 73, 52, 69, 55, 112, 87, 89, 106, 74, 50, 99, 74, 10, 106, 43, 70, 51, 113, 107, 80, 78, 90, 86, 69, 73, 55, 86, 70, 89, 47, 117, 89, 53, 43, 99, 116, 72, 104, 75, 81, 86, 56, 88, 97, 55, 112, 79, 54, 107, 79, 56, 82, 102, 55, 55, 73, 122, 108, 104, 69, 89, 116, 56, 108, 108, 118, 104, 106, 104, 111, 54, 84, 99, 43, 104, 106, 53, 48, 55, 119, 84, 109, 122, 108, 54, 78, 76, 114, 84, 10, 81, 102, 118, 54, 77, 111, 111, 113, 116, 121, 117, 71, 67, 50, 109, 68, 79, 76, 55, 78, 105, 105, 52, 76, 99, 75, 50, 78, 74, 112, 76, 117, 72, 118, 85, 66, 75, 119, 114, 90, 49, 112, 101, 98, 98, 117, 67, 111, 71, 82, 119, 54, 73, 89, 115, 77, 72, 107, 67, 116, 65, 43, 102, 100, 90, 110, 55, 49, 117, 83, 65, 78, 65, 43, 105, 87, 10, 43, 89, 74, 70, 49, 68, 110, 103, 111, 65, 66, 100, 49, 53, 106, 109, 102, 90, 53, 110, 99, 56, 79, 97, 75, 118, 101, 114, 105, 54, 69, 54, 70, 79, 56, 48, 118, 70, 73, 79, 105, 90, 105, 97, 66, 69, 67, 69, 72, 88, 53, 70, 97, 90, 78, 88, 122, 117, 118, 79, 43, 70, 66, 56, 84, 120, 120, 117, 66, 69, 79, 98, 43, 100, 89, 55, 10, 73, 120, 106, 112, 54, 111, 55, 82, 84, 85, 97, 78, 56, 84, 118, 107, 97, 115, 113, 54, 43, 121, 79, 51, 109, 47, 113, 90, 65, 83, 108, 97, 87, 70, 111, 116, 52, 47, 110, 85, 98, 81, 52, 109, 114, 99, 70, 117, 78, 76, 119, 121, 43, 65, 119, 70, 43, 109, 87, 106, 50, 122, 115, 51, 103, 121, 76, 112, 49, 116, 120, 121, 77, 47, 49, 100, 10, 56, 105, 67, 57, 100, 106, 119, 106, 50, 105, 106, 51, 43, 82, 118, 114, 87, 87, 84, 86, 51, 70, 57, 121, 102, 105, 68, 56, 122, 89, 109, 49, 107, 71, 100, 78, 89, 110, 111, 47, 84, 113, 48, 100, 119, 122, 110, 43, 101, 118, 81, 111, 70, 116, 57, 66, 57, 107, 105, 65, 66, 100, 99, 80, 85, 88, 109, 115, 69, 75, 118, 85, 55, 65, 78, 109, 10, 53, 109, 113, 119, 117, 106, 71, 83, 81, 107, 66, 113, 118, 106, 114, 84, 99, 117, 70, 113, 78, 49, 87, 56, 114, 66, 50, 86, 116, 50, 108, 104, 56, 107, 79, 82, 100, 79, 97, 103, 48, 119, 111, 107, 82, 113, 69, 73, 114, 57, 98, 97, 82, 82, 109, 87, 49, 70, 77, 100, 87, 52, 82, 53, 56, 77, 68, 51, 82, 43, 43, 76, 106, 56, 85, 71, 10, 114, 112, 49, 77, 89, 112, 51, 47, 82, 103, 84, 52, 48, 56, 109, 50, 69, 67, 86, 65, 100, 102, 52, 87, 113, 115, 108, 75, 89, 73, 89, 118, 117, 117, 56, 119, 100, 43, 82, 85, 52, 114, 105, 69, 109, 86, 105, 65, 113, 104, 79, 76, 85, 84, 112, 80, 83, 80, 97, 76, 116, 114, 77, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 109, 97, 122, 111, 110, 32, 82, 111, 111, 116, 32, 67, 65, 32, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 68, 81, 84, 67, 67, 65, 105, 109, 103, 65, 119, 73, 66, 65, 103, 73, 84, 66, 109, 121, 102, 122, 53, 109, 47, 106, 65, 111, 53, 52, 118, 66, 52, 105, 107, 80, 109, 108, 106, 90, 98, 121, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 65, 53, 77, 81, 115, 119, 67, 81, 89, 68, 10, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 80, 77, 65, 48, 71, 65, 49, 85, 69, 67, 104, 77, 71, 81, 87, 49, 104, 101, 109, 57, 117, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 68, 69, 120, 66, 66, 98, 87, 70, 54, 98, 50, 52, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 120, 77, 66, 52, 88, 68, 84, 69, 49, 10, 77, 68, 85, 121, 78, 106, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 77, 52, 77, 68, 69, 120, 78, 122, 65, 119, 77, 68, 65, 119, 77, 70, 111, 119, 79, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 68, 122, 65, 78, 66, 103, 78, 86, 66, 65, 111, 84, 66, 107, 70, 116, 89, 88, 112, 118, 10, 98, 106, 69, 90, 77, 66, 99, 71, 65, 49, 85, 69, 65, 120, 77, 81, 81, 87, 49, 104, 101, 109, 57, 117, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 77, 84, 67, 67, 65, 83, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 69, 80, 65, 68, 67, 67, 65, 81, 111, 67, 10, 103, 103, 69, 66, 65, 76, 74, 52, 103, 72, 72, 75, 101, 78, 88, 106, 99, 97, 57, 72, 103, 70, 66, 48, 102, 87, 55, 89, 49, 52, 104, 50, 57, 74, 108, 111, 57, 49, 103, 104, 89, 80, 108, 48, 104, 65, 69, 118, 114, 65, 73, 116, 104, 116, 79, 103, 81, 51, 112, 79, 115, 113, 84, 81, 78, 114, 111, 66, 118, 111, 51, 98, 83, 77, 103, 72, 10, 70, 122, 90, 77, 57, 79, 54, 73, 73, 56, 99, 43, 54, 122, 102, 49, 116, 82, 110, 52, 83, 87, 105, 119, 51, 116, 101, 53, 100, 106, 103, 100, 89, 90, 54, 107, 47, 111, 73, 50, 112, 101, 86, 75, 86, 117, 82, 70, 52, 102, 110, 57, 116, 66, 98, 54, 100, 78, 113, 99, 109, 122, 85, 53, 76, 47, 113, 119, 73, 70, 65, 71, 98, 72, 114, 81, 10, 103, 76, 75, 109, 43, 97, 47, 115, 82, 120, 109, 80, 85, 68, 103, 72, 51, 75, 75, 72, 79, 86, 106, 52, 117, 116, 87, 112, 43, 85, 104, 110, 77, 74, 98, 117, 108, 72, 104, 101, 98, 52, 109, 106, 85, 99, 65, 119, 104, 109, 97, 104, 82, 87, 97, 54, 86, 79, 117, 106, 119, 53, 72, 53, 83, 78, 122, 47, 48, 101, 103, 119, 76, 88, 48, 116, 10, 100, 72, 65, 49, 49, 52, 103, 107, 57, 53, 55, 69, 87, 87, 54, 55, 99, 52, 99, 88, 56, 106, 74, 71, 75, 76, 104, 68, 43, 114, 99, 100, 113, 115, 113, 48, 56, 112, 56, 107, 68, 105, 49, 76, 57, 51, 70, 99, 88, 109, 110, 47, 54, 112, 85, 67, 121, 122, 105, 75, 114, 108, 65, 52, 98, 57, 118, 55, 76, 87, 73, 98, 120, 99, 99, 101, 10, 86, 79, 70, 51, 52, 71, 102, 73, 68, 53, 121, 72, 73, 57, 89, 47, 81, 67, 66, 47, 73, 73, 68, 69, 103, 69, 119, 43, 79, 121, 81, 109, 106, 103, 83, 117, 98, 74, 114, 73, 113, 103, 48, 67, 65, 119, 69, 65, 65, 97, 78, 67, 77, 69, 65, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 10, 47, 122, 65, 79, 66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 89, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 73, 81, 89, 122, 73, 85, 48, 55, 76, 119, 77, 108, 74, 81, 117, 67, 70, 109, 99, 120, 55, 73, 81, 84, 103, 111, 73, 77, 65, 48, 71, 67, 83, 113, 71, 83, 73, 98, 51, 10, 68, 81, 69, 66, 67, 119, 85, 65, 65, 52, 73, 66, 65, 81, 67, 89, 56, 106, 100, 97, 81, 90, 67, 104, 71, 115, 86, 50, 85, 83, 103, 103, 78, 105, 77, 79, 114, 117, 89, 111, 117, 54, 114, 52, 108, 75, 53, 73, 112, 68, 66, 47, 71, 47, 119, 107, 106, 85, 117, 48, 121, 75, 71, 88, 57, 114, 98, 120, 101, 110, 68, 73, 85, 53, 80, 77, 10, 67, 67, 106, 106, 109, 67, 88, 80, 73, 54, 84, 53, 51, 105, 72, 84, 102, 73, 85, 74, 114, 85, 54, 97, 100, 84, 114, 67, 67, 50, 113, 74, 101, 72, 90, 69, 82, 120, 104, 108, 98, 73, 49, 66, 106, 106, 116, 47, 109, 115, 118, 48, 116, 97, 100, 81, 49, 119, 85, 115, 78, 43, 103, 68, 83, 54, 51, 112, 89, 97, 65, 67, 98, 118, 88, 121, 10, 56, 77, 87, 121, 55, 86, 117, 51, 51, 80, 113, 85, 88, 72, 101, 101, 69, 54, 86, 47, 85, 113, 50, 86, 56, 118, 105, 84, 79, 57, 54, 76, 88, 70, 118, 75, 87, 108, 74, 98, 89, 75, 56, 85, 57, 48, 118, 118, 111, 47, 117, 102, 81, 74, 86, 116, 77, 86, 84, 56, 81, 116, 80, 72, 82, 104, 56, 106, 114, 100, 107, 80, 83, 72, 67, 97, 10, 50, 88, 86, 52, 99, 100, 70, 121, 81, 122, 82, 49, 98, 108, 100, 90, 119, 103, 74, 99, 74, 109, 65, 112, 122, 121, 77, 90, 70, 111, 54, 73, 81, 54, 88, 85, 53, 77, 115, 73, 43, 121, 77, 82, 81, 43, 104, 68, 75, 88, 74, 105, 111, 97, 108, 100, 88, 103, 106, 85, 107, 75, 54, 52, 50, 77, 52, 85, 119, 116, 66, 86, 56, 111, 98, 50, 10, 120, 74, 78, 68, 100, 50, 90, 104, 119, 76, 110, 111, 81, 100, 101, 88, 101, 71, 65, 68, 98, 107, 112, 121, 114, 113, 88, 82, 102, 98, 111, 81, 110, 111, 90, 115, 71, 52, 113, 53, 87, 84, 80, 52, 54, 56, 83, 81, 118, 118, 71, 53, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 109, 97, 122, 111, 110, 32, 82, 111, 111, 116, 32, 67, 65, 32, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 81, 84, 67, 67, 65, 121, 109, 103, 65, 119, 73, 66, 65, 103, 73, 84, 66, 109, 121, 102, 48, 112, 89, 49, 104, 112, 56, 75, 68, 43, 87, 71, 101, 80, 104, 98, 74, 114, 117, 75, 78, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 119, 70, 65, 68, 65, 53, 77, 81, 115, 119, 67, 81, 89, 68, 10, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 80, 77, 65, 48, 71, 65, 49, 85, 69, 67, 104, 77, 71, 81, 87, 49, 104, 101, 109, 57, 117, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 68, 69, 120, 66, 66, 98, 87, 70, 54, 98, 50, 52, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 121, 77, 66, 52, 88, 68, 84, 69, 49, 10, 77, 68, 85, 121, 78, 106, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 81, 119, 77, 68, 85, 121, 78, 106, 65, 119, 77, 68, 65, 119, 77, 70, 111, 119, 79, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 68, 122, 65, 78, 66, 103, 78, 86, 66, 65, 111, 84, 66, 107, 70, 116, 89, 88, 112, 118, 10, 98, 106, 69, 90, 77, 66, 99, 71, 65, 49, 85, 69, 65, 120, 77, 81, 81, 87, 49, 104, 101, 109, 57, 117, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 77, 106, 67, 67, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 10, 103, 103, 73, 66, 65, 75, 50, 87, 110, 121, 50, 99, 83, 107, 120, 75, 103, 88, 108, 82, 109, 101, 121, 75, 121, 50, 116, 103, 85, 82, 79, 56, 84, 87, 48, 71, 47, 76, 65, 73, 106, 100, 48, 90, 69, 71, 114, 72, 74, 103, 119, 49, 50, 77, 66, 118, 73, 73, 84, 112, 108, 76, 71, 98, 104, 81, 80, 68, 87, 57, 116, 75, 54, 77, 106, 52, 10, 107, 72, 98, 90, 87, 48, 47, 106, 84, 79, 103, 71, 78, 107, 51, 77, 109, 113, 119, 57, 68, 74, 65, 114, 107, 116, 81, 71, 71, 87, 67, 115, 78, 48, 82, 53, 104, 89, 71, 67, 114, 86, 111, 51, 52, 65, 51, 77, 110, 97, 90, 77, 85, 110, 98, 113, 81, 53, 50, 51, 66, 78, 70, 81, 57, 108, 88, 103, 49, 100, 75, 109, 83, 89, 88, 112, 10, 78, 43, 110, 75, 102, 113, 53, 99, 108, 85, 49, 73, 109, 106, 43, 117, 73, 70, 112, 116, 105, 74, 88, 90, 78, 76, 104, 83, 71, 107, 79, 81, 115, 76, 57, 115, 66, 98, 109, 50, 101, 76, 102, 113, 48, 79, 81, 54, 80, 66, 74, 84, 89, 118, 57, 75, 56, 110, 117, 43, 78, 81, 87, 112, 69, 106, 84, 106, 56, 50, 82, 48, 89, 105, 119, 57, 10, 65, 69, 108, 97, 75, 80, 52, 121, 82, 76, 117, 72, 51, 87, 85, 110, 65, 110, 69, 55, 50, 107, 114, 51, 72, 57, 114, 78, 57, 121, 70, 86, 107, 69, 56, 80, 55, 75, 54, 67, 52, 90, 57, 114, 50, 85, 88, 84, 117, 47, 66, 102, 104, 43, 48, 56, 76, 68, 109, 71, 50, 106, 47, 101, 55, 72, 74, 86, 54, 51, 109, 106, 114, 100, 118, 100, 10, 102, 76, 67, 54, 72, 77, 55, 56, 51, 107, 56, 49, 100, 115, 56, 80, 43, 72, 103, 102, 97, 106, 90, 82, 82, 105, 100, 104, 87, 43, 109, 101, 122, 47, 67, 105, 86, 88, 49, 56, 74, 89, 112, 118, 76, 55, 84, 70, 122, 52, 81, 117, 75, 47, 48, 78, 85, 82, 66, 115, 43, 49, 56, 98, 118, 66, 116, 43, 120, 97, 52, 55, 109, 65, 69, 120, 10, 107, 118, 56, 76, 86, 47, 83, 97, 115, 114, 108, 88, 54, 97, 118, 118, 68, 88, 98, 82, 56, 79, 55, 48, 122, 111, 97, 110, 52, 71, 55, 112, 116, 71, 109, 104, 51, 50, 110, 50, 77, 56, 90, 112, 76, 112, 99, 84, 110, 113, 87, 72, 115, 70, 99, 81, 103, 84, 102, 74, 85, 55, 79, 55, 102, 47, 97, 83, 48, 90, 122, 81, 71, 80, 83, 83, 10, 98, 116, 113, 68, 84, 54, 90, 106, 109, 85, 121, 108, 43, 49, 55, 118, 73, 87, 82, 54, 73, 70, 57, 115, 90, 73, 85, 86, 121, 122, 102, 112, 89, 103, 119, 76, 75, 104, 98, 99, 65, 83, 52, 121, 50, 106, 53, 76, 57, 90, 52, 54, 57, 104, 100, 65, 108, 79, 43, 101, 107, 81, 105, 71, 43, 114, 53, 106, 113, 70, 111, 122, 55, 77, 116, 48, 10, 81, 53, 88, 53, 98, 71, 108, 83, 78, 115, 99, 112, 98, 47, 120, 86, 65, 49, 119, 102, 43, 53, 43, 57, 82, 43, 118, 110, 83, 85, 101, 86, 67, 48, 54, 74, 73, 103, 108, 74, 52, 80, 86, 104, 72, 118, 71, 47, 76, 111, 112, 121, 98, 111, 66, 90, 47, 49, 99, 54, 43, 88, 85, 121, 111, 48, 53, 102, 55, 79, 48, 111, 89, 116, 108, 78, 10, 99, 47, 76, 77, 103, 82, 100, 103, 55, 99, 51, 114, 51, 78, 117, 110, 121, 115, 86, 43, 65, 114, 51, 121, 86, 65, 104, 85, 47, 98, 81, 116, 67, 83, 119, 88, 86, 69, 113, 89, 48, 86, 84, 104, 85, 87, 99, 73, 48, 117, 49, 117, 102, 109, 56, 47, 48, 105, 50, 66, 87, 83, 108, 109, 121, 53, 65, 53, 108, 82, 69, 101, 100, 67, 102, 43, 10, 51, 101, 117, 118, 65, 103, 77, 66, 65, 65, 71, 106, 81, 106, 66, 65, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 71, 71, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 83, 119, 10, 68, 80, 66, 77, 77, 80, 81, 70, 87, 65, 74, 73, 47, 84, 80, 108, 85, 113, 57, 76, 104, 79, 78, 109, 85, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 119, 70, 65, 65, 79, 67, 65, 103, 69, 65, 113, 113, 105, 65, 106, 119, 53, 52, 111, 43, 67, 105, 49, 77, 51, 109, 57, 90, 104, 54, 79, 43, 111, 65, 10, 65, 55, 67, 88, 68, 112, 79, 56, 87, 113, 106, 50, 76, 73, 120, 121, 104, 54, 109, 120, 47, 72, 57, 122, 47, 87, 78, 120, 101, 75, 87, 72, 87, 99, 56, 119, 52, 81, 48, 81, 115, 104, 78, 97, 98, 89, 76, 49, 97, 117, 97, 65, 110, 54, 65, 70, 67, 50, 106, 107, 82, 50, 118, 72, 97, 116, 43, 50, 47, 88, 99, 121, 99, 117, 85, 89, 10, 43, 103, 110, 48, 111, 74, 77, 115, 88, 100, 75, 77, 100, 89, 86, 50, 90, 90, 65, 77, 65, 51, 109, 51, 77, 83, 78, 106, 114, 88, 105, 68, 67, 89, 90, 111, 104, 77, 114, 47, 43, 99, 56, 109, 109, 112, 74, 53, 53, 56, 49, 76, 120, 101, 100, 104, 112, 120, 102, 76, 56, 54, 107, 83, 107, 53, 78, 114, 112, 43, 103, 118, 85, 53, 76, 69, 10, 89, 70, 105, 119, 122, 65, 74, 82, 71, 70, 117, 70, 106, 87, 74, 90, 89, 55, 97, 116, 116, 78, 54, 97, 43, 121, 98, 51, 65, 67, 102, 65, 88, 86, 85, 51, 100, 74, 110, 74, 85, 72, 47, 106, 87, 83, 53, 69, 52, 121, 119, 108, 55, 117, 120, 77, 77, 110, 101, 48, 110, 120, 114, 112, 83, 49, 48, 103, 120, 100, 114, 57, 72, 73, 99, 87, 10, 120, 107, 80, 111, 49, 76, 115, 109, 109, 107, 86, 119, 88, 113, 107, 76, 78, 49, 80, 105, 82, 110, 115, 110, 47, 101, 66, 71, 56, 111, 109, 51, 122, 69, 75, 50, 121, 121, 103, 109, 98, 116, 109, 108, 121, 84, 114, 73, 81, 82, 78, 103, 57, 49, 67, 77, 70, 97, 54, 121, 98, 82, 111, 86, 71, 108, 100, 52, 53, 112, 73, 113, 50, 87, 87, 81, 10, 103, 106, 57, 115, 65, 113, 43, 117, 69, 106, 111, 110, 108, 106, 89, 69, 49, 120, 50, 105, 103, 71, 79, 112, 109, 47, 72, 108, 117, 114, 82, 56, 70, 76, 66, 79, 121, 98, 69, 102, 100, 70, 56, 52, 57, 108, 72, 113, 109, 47, 111, 115, 111, 104, 72, 85, 113, 83, 48, 110, 71, 107, 87, 120, 114, 55, 74, 79, 99, 81, 51, 65, 87, 69, 98, 87, 10, 97, 81, 98, 76, 85, 56, 117, 122, 47, 109, 116, 66, 122, 85, 70, 43, 102, 85, 119, 80, 102, 72, 74, 53, 101, 108, 110, 78, 88, 107, 111, 79, 114, 74, 117, 112, 109, 72, 78, 53, 102, 76, 84, 48, 122, 76, 109, 52, 66, 119, 121, 121, 100, 70, 121, 52, 120, 50, 43, 73, 111, 90, 67, 110, 57, 75, 114, 53, 118, 50, 99, 54, 57, 66, 111, 86, 10, 89, 104, 54, 51, 110, 55, 52, 57, 115, 83, 109, 118, 90, 54, 69, 83, 56, 108, 103, 81, 71, 86, 77, 68, 77, 66, 117, 52, 71, 111, 110, 50, 110, 76, 50, 88, 65, 52, 54, 106, 67, 102, 77, 100, 105, 121, 72, 120, 116, 78, 47, 107, 72, 78, 71, 102, 90, 81, 73, 71, 54, 108, 122, 87, 69, 55, 79, 69, 55, 54, 75, 108, 88, 73, 120, 51, 10, 75, 97, 100, 111, 119, 71, 117, 117, 81, 78, 75, 111, 116, 79, 114, 78, 56, 73, 49, 76, 79, 74, 119, 90, 109, 104, 115, 111, 86, 76, 105, 74, 107, 79, 47, 75, 100, 89, 69, 43, 72, 118, 74, 107, 74, 77, 99, 89, 114, 48, 55, 47, 82, 53, 52, 72, 57, 106, 86, 108, 112, 78, 77, 75, 86, 118, 47, 49, 70, 50, 82, 115, 55, 54, 103, 105, 10, 74, 85, 109, 84, 116, 116, 56, 65, 70, 57, 112, 89, 102, 108, 51, 117, 120, 82, 117, 119, 48, 100, 70, 102, 73, 82, 68, 72, 43, 102, 79, 54, 65, 103, 111, 110, 66, 56, 88, 120, 49, 115, 102, 84, 52, 80, 115, 74, 89, 71, 119, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 109, 97, 122, 111, 110, 32, 82, 111, 111, 116, 32, 67, 65, 32, 51, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 66, 116, 106, 67, 67, 65, 86, 117, 103, 65, 119, 73, 66, 65, 103, 73, 84, 66, 109, 121, 102, 49, 88, 83, 88, 78, 109, 89, 47, 79, 119, 117, 97, 50, 101, 105, 101, 100, 103, 80, 121, 83, 106, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 106, 65, 53, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 80, 77, 65, 48, 71, 65, 49, 85, 69, 67, 104, 77, 71, 81, 87, 49, 104, 101, 109, 57, 117, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 68, 69, 120, 66, 66, 98, 87, 70, 54, 98, 50, 52, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 122, 77, 66, 52, 88, 68, 84, 69, 49, 77, 68, 85, 121, 10, 78, 106, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 81, 119, 77, 68, 85, 121, 78, 106, 65, 119, 77, 68, 65, 119, 77, 70, 111, 119, 79, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 68, 122, 65, 78, 66, 103, 78, 86, 66, 65, 111, 84, 66, 107, 70, 116, 89, 88, 112, 118, 98, 106, 69, 90, 10, 77, 66, 99, 71, 65, 49, 85, 69, 65, 120, 77, 81, 81, 87, 49, 104, 101, 109, 57, 117, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 77, 122, 66, 90, 77, 66, 77, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 67, 67, 113, 71, 83, 77, 52, 57, 65, 119, 69, 72, 65, 48, 73, 65, 66, 67, 109, 88, 112, 56, 90, 66, 10, 102, 56, 65, 78, 109, 43, 103, 66, 71, 49, 98, 71, 56, 108, 75, 108, 117, 105, 50, 121, 69, 117, 106, 83, 76, 116, 102, 54, 121, 99, 88, 89, 113, 109, 48, 102, 99, 52, 69, 55, 79, 53, 104, 114, 79, 88, 119, 122, 112, 99, 86, 79, 104, 111, 54, 65, 70, 50, 104, 105, 82, 86, 100, 57, 82, 70, 103, 100, 115, 122, 102, 108, 90, 119, 106, 114, 10, 90, 116, 54, 106, 81, 106, 66, 65, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 71, 71, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, 87, 66, 66, 83, 114, 116, 116, 118, 88, 66, 112, 52, 51, 10, 114, 68, 67, 71, 66, 53, 70, 119, 120, 53, 122, 69, 71, 98, 70, 52, 119, 68, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 103, 78, 74, 65, 68, 66, 71, 65, 105, 69, 65, 52, 73, 87, 83, 111, 120, 101, 51, 106, 102, 107, 114, 66, 113, 87, 84, 114, 66, 113, 89, 97, 71, 70, 121, 43, 117, 71, 104, 48, 80, 115, 99, 10, 101, 71, 67, 109, 81, 53, 110, 70, 117, 77, 81, 67, 73, 81, 67, 99, 65, 117, 47, 120, 108, 74, 121, 122, 108, 118, 110, 114, 120, 105, 114, 52, 116, 105, 122, 43, 79, 112, 65, 85, 70, 116, 101, 77, 89, 121, 82, 73, 72, 78, 56, 119, 102, 100, 86, 111, 79, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 65, 109, 97, 122, 111, 110, 32, 82, 111, 111, 116, 32, 67, 65, 32, 52, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 66, 56, 106, 67, 67, 65, 88, 105, 103, 65, 119, 73, 66, 65, 103, 73, 84, 66, 109, 121, 102, 49, 56, 71, 55, 69, 69, 119, 112, 81, 43, 86, 120, 101, 51, 115, 115, 121, 66, 114, 66, 68, 106, 65, 75, 66, 103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 122, 65, 53, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 10, 69, 119, 74, 86, 85, 122, 69, 80, 77, 65, 48, 71, 65, 49, 85, 69, 67, 104, 77, 71, 81, 87, 49, 104, 101, 109, 57, 117, 77, 82, 107, 119, 70, 119, 89, 68, 86, 81, 81, 68, 69, 120, 66, 66, 98, 87, 70, 54, 98, 50, 52, 103, 85, 109, 57, 118, 100, 67, 66, 68, 81, 83, 65, 48, 77, 66, 52, 88, 68, 84, 69, 49, 77, 68, 85, 121, 10, 78, 106, 65, 119, 77, 68, 65, 119, 77, 70, 111, 88, 68, 84, 81, 119, 77, 68, 85, 121, 78, 106, 65, 119, 77, 68, 65, 119, 77, 70, 111, 119, 79, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 120, 68, 122, 65, 78, 66, 103, 78, 86, 66, 65, 111, 84, 66, 107, 70, 116, 89, 88, 112, 118, 98, 106, 69, 90, 10, 77, 66, 99, 71, 65, 49, 85, 69, 65, 120, 77, 81, 81, 87, 49, 104, 101, 109, 57, 117, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 103, 78, 68, 66, 50, 77, 66, 65, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 66, 83, 117, 66, 66, 65, 65, 105, 65, 50, 73, 65, 66, 78, 75, 114, 105, 106, 100, 80, 111, 49, 77, 78, 10, 47, 115, 71, 75, 101, 48, 117, 111, 101, 48, 90, 76, 89, 55, 66, 105, 57, 105, 48, 98, 50, 119, 104, 120, 73, 100, 73, 65, 54, 71, 79, 57, 109, 105, 102, 55, 56, 68, 108, 117, 88, 101, 111, 57, 112, 99, 109, 66, 113, 113, 78, 98, 73, 74, 104, 70, 88, 82, 98, 98, 47, 101, 103, 81, 98, 101, 79, 99, 52, 79, 79, 57, 88, 52, 82, 105, 10, 56, 51, 66, 107, 77, 54, 68, 76, 74, 67, 57, 119, 117, 111, 105, 104, 75, 113, 66, 49, 43, 73, 71, 117, 89, 103, 98, 69, 103, 100, 115, 53, 98, 105, 109, 119, 72, 118, 111, 117, 88, 75, 78, 67, 77, 69, 65, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 47, 122, 65, 79, 66, 103, 78, 86, 10, 72, 81, 56, 66, 65, 102, 56, 69, 66, 65, 77, 67, 65, 89, 89, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 78, 80, 115, 120, 122, 112, 108, 98, 115, 122, 104, 50, 110, 97, 97, 86, 118, 117, 99, 56, 52, 90, 116, 86, 43, 87, 66, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 68, 65, 50, 103, 65, 10, 77, 71, 85, 67, 77, 68, 113, 76, 73, 102, 71, 57, 102, 104, 71, 116, 48, 79, 57, 89, 108, 105, 47, 87, 54, 53, 49, 43, 107, 73, 48, 114, 122, 50, 90, 86, 119, 121, 122, 106, 75, 75, 108, 119, 67, 107, 99, 79, 56, 68, 100, 90, 69, 118, 56, 116, 109, 90, 81, 111, 84, 105, 112, 80, 78, 85, 48, 122, 87, 103, 73, 120, 65, 79, 112, 49, 10, 65, 69, 52, 55, 120, 68, 113, 85, 69, 112, 72, 74, 87, 69, 97, 100, 73, 82, 78, 121, 112, 52, 105, 99, 105, 117, 82, 77, 83, 116, 117, 87, 49, 75, 121, 76, 97, 50, 116, 74, 69, 108, 77, 122, 114, 100, 102, 107, 118, 105, 84, 56, 116, 81, 112, 50, 49, 75, 87, 56, 69, 65, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 76, 117, 120, 84, 114, 117, 115, 116, 32, 71, 108, 111, 98, 97, 108, 32, 82, 111, 111, 116, 32, 50, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 70, 119, 122, 67, 67, 65, 54, 117, 103, 65, 119, 73, 66, 65, 103, 73, 85, 67, 110, 54, 109, 51, 48, 116, 69, 110, 116, 112, 113, 74, 73, 87, 101, 53, 114, 103, 86, 48, 120, 90, 47, 117, 55, 69, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, 82, 106, 69, 76, 77, 65, 107, 71, 10, 65, 49, 85, 69, 66, 104, 77, 67, 84, 70, 85, 120, 70, 106, 65, 85, 66, 103, 78, 86, 66, 65, 111, 77, 68, 85, 120, 49, 101, 70, 82, 121, 100, 88, 78, 48, 73, 70, 77, 117, 81, 83, 52, 120, 72, 122, 65, 100, 66, 103, 78, 86, 66, 65, 77, 77, 70, 107, 120, 49, 101, 70, 82, 121, 100, 88, 78, 48, 73, 69, 100, 115, 98, 50, 74, 104, 10, 98, 67, 66, 83, 98, 50, 57, 48, 73, 68, 73, 119, 72, 104, 99, 78, 77, 84, 85, 119, 77, 122, 65, 49, 77, 84, 77, 121, 77, 84, 85, 51, 87, 104, 99, 78, 77, 122, 85, 119, 77, 122, 65, 49, 77, 84, 77, 121, 77, 84, 85, 51, 87, 106, 66, 71, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 77, 86, 84, 69, 87, 10, 77, 66, 81, 71, 65, 49, 85, 69, 67, 103, 119, 78, 84, 72, 86, 52, 86, 72, 74, 49, 99, 51, 81, 103, 85, 121, 53, 66, 76, 106, 69, 102, 77, 66, 48, 71, 65, 49, 85, 69, 65, 119, 119, 87, 84, 72, 86, 52, 86, 72, 74, 49, 99, 51, 81, 103, 82, 50, 120, 118, 89, 109, 70, 115, 73, 70, 74, 118, 98, 51, 81, 103, 77, 106, 67, 67, 10, 65, 105, 73, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 66, 66, 81, 65, 68, 103, 103, 73, 80, 65, 68, 67, 67, 65, 103, 111, 67, 103, 103, 73, 66, 65, 78, 101, 70, 108, 55, 56, 82, 109, 79, 110, 119, 89, 111, 78, 77, 80, 73, 102, 53, 85, 50, 111, 51, 67, 47, 73, 80, 80, 73, 102, 79, 98, 57, 119, 109, 10, 75, 98, 51, 70, 105, 98, 114, 74, 103, 122, 51, 51, 55, 115, 112, 98, 120, 109, 49, 74, 99, 55, 84, 74, 82, 113, 77, 98, 78, 66, 77, 47, 119, 89, 108, 70, 86, 47, 84, 90, 115, 102, 115, 50, 90, 85, 118, 55, 67, 79, 74, 73, 99, 82, 72, 73, 98, 106, 117, 101, 110, 100, 43, 74, 90, 84, 101, 109, 104, 102, 89, 55, 82, 66, 105, 50, 10, 120, 106, 99, 119, 89, 107, 83, 83, 108, 50, 108, 57, 81, 106, 65, 107, 53, 65, 48, 77, 105, 87, 116, 106, 51, 115, 88, 104, 51, 48, 54, 112, 70, 71, 120, 84, 52, 71, 72, 79, 57, 104, 99, 118, 72, 84, 121, 57, 53, 105, 74, 77, 72, 90, 80, 49, 69, 77, 83, 104, 100, 117, 120, 113, 51, 115, 86, 115, 51, 53, 97, 48, 86, 107, 66, 67, 10, 119, 71, 75, 83, 77, 75, 69, 116, 70, 90, 83, 103, 48, 105, 65, 71, 67, 87, 53, 113, 98, 101, 88, 114, 116, 55, 55, 85, 56, 80, 69, 86, 102, 73, 118, 109, 84, 114, 111, 84, 122, 69, 115, 110, 88, 112, 107, 56, 70, 49, 50, 80, 103, 88, 56, 122, 80, 85, 47, 84, 80, 120, 118, 115, 88, 68, 47, 119, 80, 69, 120, 49, 98, 118, 75, 109, 10, 49, 90, 51, 97, 76, 81, 100, 106, 65, 115, 90, 121, 54, 90, 83, 56, 84, 69, 109, 86, 84, 52, 104, 83, 121, 78, 118, 111, 97, 89, 76, 52, 122, 68, 82, 98, 73, 118, 67, 71, 112, 52, 109, 57, 83, 65, 112, 116, 90, 111, 70, 116, 121, 77, 104, 107, 43, 119, 72, 104, 57, 79, 72, 101, 50, 90, 55, 100, 50, 49, 118, 85, 75, 112, 107, 109, 10, 70, 82, 115, 101, 84, 74, 73, 112, 103, 112, 55, 86, 107, 111, 71, 83, 81, 88, 65, 90, 57, 54, 84, 108, 107, 48, 117, 56, 100, 50, 99, 120, 51, 82, 122, 57, 77, 88, 65, 78, 70, 53, 107, 77, 43, 81, 119, 53, 71, 83, 111, 88, 116, 84, 66, 120, 86, 100, 85, 80, 114, 108, 106, 104, 80, 83, 56, 48, 109, 56, 43, 102, 57, 110, 105, 70, 10, 119, 112, 78, 54, 99, 106, 53, 109, 106, 53, 119, 87, 69, 87, 67, 80, 110, 111, 108, 118, 90, 55, 55, 103, 82, 49, 111, 55, 68, 74, 112, 110, 105, 56, 57, 71, 120, 113, 52, 52, 111, 47, 75, 110, 118, 79, 98, 87, 104, 87, 115, 122, 74, 72, 65, 105, 83, 56, 115, 73, 109, 55, 118, 73, 43, 65, 73, 112, 72, 98, 52, 103, 68, 69, 97, 47, 10, 97, 52, 101, 98, 115, 121, 112, 109, 81, 106, 86, 71, 98, 75, 113, 54, 114, 102, 109, 89, 101, 43, 108, 81, 86, 82, 81, 120, 118, 55, 72, 97, 76, 101, 50, 65, 114, 87, 103, 107, 43, 50, 109, 114, 50, 72, 69, 84, 77, 79, 90, 110, 115, 52, 100, 65, 47, 89, 108, 43, 56, 107, 80, 82, 69, 100, 56, 118, 90, 83, 57, 107, 122, 108, 56, 85, 10, 117, 98, 71, 47, 77, 98, 50, 72, 101, 70, 112, 90, 90, 89, 105, 113, 47, 70, 107, 121, 83, 73, 98, 87, 84, 76, 107, 112, 83, 53, 88, 84, 100, 118, 78, 51, 74, 87, 49, 67, 72, 68, 105, 68, 84, 102, 50, 106, 88, 53, 116, 47, 76, 97, 120, 53, 71, 119, 53, 67, 77, 90, 100, 106, 112, 80, 117, 75, 97, 100, 85, 105, 68, 84, 83, 81, 10, 77, 67, 54, 111, 116, 79, 66, 116, 116, 112, 83, 115, 118, 73, 116, 79, 49, 51, 68, 56, 120, 84, 105, 79, 90, 67, 88, 104, 84, 84, 109, 81, 122, 115, 109, 72, 104, 70, 104, 120, 65, 103, 77, 66, 65, 65, 71, 106, 103, 97, 103, 119, 103, 97, 85, 119, 68, 119, 89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, 65, 119, 69, 66, 10, 47, 122, 66, 67, 66, 103, 78, 86, 72, 83, 65, 69, 79, 122, 65, 53, 77, 68, 99, 71, 66, 121, 117, 66, 75, 119, 69, 66, 65, 81, 111, 119, 76, 68, 65, 113, 66, 103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 67, 65, 82, 89, 101, 97, 72, 82, 48, 99, 72, 77, 54, 76, 121, 57, 121, 90, 88, 66, 118, 99, 50, 108, 48, 98, 51, 74, 53, 10, 76, 109, 120, 49, 101, 72, 82, 121, 100, 88, 78, 48, 76, 109, 120, 49, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 66, 66, 106, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 84, 47, 71, 67, 104, 50, 43, 85, 103, 70, 76, 75, 71, 117, 56, 83, 115, 98, 75, 55, 74, 84, 10, 43, 69, 116, 56, 115, 122, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 47, 120, 103, 111, 100, 118, 108, 73, 66, 83, 121, 104, 114, 118, 69, 114, 71, 121, 117, 121, 85, 47, 104, 76, 102, 76, 77, 119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 73, 66, 65, 71, 111, 90, 10, 70, 79, 49, 117, 101, 99, 69, 115, 104, 57, 81, 78, 99, 72, 55, 88, 57, 110, 106, 74, 67, 119, 82, 79, 120, 76, 72, 79, 107, 51, 68, 43, 115, 70, 84, 65, 77, 115, 50, 90, 77, 71, 81, 88, 118, 119, 47, 108, 52, 106, 80, 57, 66, 122, 90, 65, 99, 103, 52, 97, 116, 109, 112, 90, 49, 103, 68, 108, 97, 67, 68, 100, 76, 110, 73, 78, 10, 72, 50, 112, 107, 77, 83, 67, 69, 102, 85, 109, 109, 87, 106, 102, 114, 82, 99, 109, 70, 57, 100, 84, 72, 70, 53, 107, 72, 53, 112, 116, 86, 53, 65, 122, 111, 113, 98, 84, 79, 106, 70, 117, 49, 69, 86, 122, 80, 105, 103, 52, 78, 49, 113, 120, 51, 103, 102, 52, 121, 110, 67, 83, 101, 99, 115, 53, 85, 56, 57, 66, 118, 111, 108, 98, 87, 10, 55, 77, 77, 51, 76, 71, 86, 89, 118, 108, 99, 65, 71, 118, 73, 49, 43, 117, 116, 55, 77, 86, 51, 67, 119, 82, 73, 57, 108, 111, 71, 73, 108, 111, 110, 66, 87, 86, 120, 54, 53, 110, 57, 119, 78, 79, 101, 68, 52, 114, 72, 104, 52, 98, 104, 89, 55, 57, 83, 86, 53, 71, 67, 99, 56, 74, 97, 88, 99, 111, 122, 114, 104, 65, 73, 117, 10, 90, 89, 43, 107, 116, 57, 74, 47, 90, 57, 51, 73, 48, 53, 53, 99, 113, 113, 109, 107, 111, 67, 85, 85, 66, 112, 118, 115, 84, 51, 52, 116, 67, 51, 56, 100, 100, 102, 69, 122, 50, 79, 51, 79, 117, 72, 86, 116, 80, 108, 117, 53, 109, 66, 48, 120, 68, 86, 98, 89, 81, 119, 56, 119, 107, 98, 73, 69, 97, 57, 49, 87, 118, 112, 87, 65, 10, 86, 87, 101, 43, 50, 77, 50, 68, 50, 82, 106, 117, 76, 103, 43, 71, 76, 90, 75, 101, 99, 66, 80, 115, 51, 108, 72, 74, 81, 51, 103, 67, 112, 85, 51, 73, 43, 86, 47, 69, 107, 86, 104, 71, 70, 110, 100, 97, 100, 75, 112, 65, 118, 65, 101, 102, 77, 76, 109, 120, 57, 120, 73, 88, 51, 101, 80, 47, 74, 69, 65, 100, 101, 109, 114, 82, 10, 84, 120, 103, 75, 113, 112, 65, 100, 54, 48, 65, 101, 51, 54, 69, 101, 82, 74, 73, 81, 109, 118, 75, 78, 52, 100, 70, 76, 82, 112, 55, 111, 82, 85, 75, 88, 54, 107, 87, 90, 56, 43, 120, 109, 49, 81, 76, 54, 56, 113, 90, 75, 74, 75, 114, 101, 122, 114, 110, 75, 43, 84, 43, 84, 98, 47, 109, 106, 117, 117, 113, 108, 80, 112, 109, 116, 10, 47, 102, 57, 55, 109, 102, 86, 108, 55, 118, 66, 90, 75, 71, 102, 88, 107, 74, 87, 107, 69, 52, 83, 112, 104, 77, 72, 111, 122, 115, 53, 49, 107, 50, 77, 97, 118, 68, 122, 113, 49, 87, 81, 102, 76, 83, 111, 83, 79, 99, 98, 68, 87, 106, 76, 116, 82, 53, 69, 87, 68, 114, 119, 52, 119, 86, 68, 101, 106, 56, 111, 113, 107, 68, 81, 99, 10, 55, 107, 71, 85, 110, 70, 52, 90, 76, 118, 104, 70, 83, 90, 108, 48, 107, 98, 65, 69, 98, 43, 77, 69, 87, 114, 71, 114, 75, 113, 118, 43, 120, 57, 67, 87, 116, 116, 114, 104, 83, 109, 81, 71, 98, 109, 66, 78, 118, 85, 74, 79, 47, 51, 106, 97, 74, 77, 111, 98, 116, 78, 101, 87, 79, 87, 121, 117, 56, 81, 54, 113, 112, 51, 49, 73, 10, 105, 121, 66, 77, 122, 50, 84, 87, 117, 74, 100, 71, 115, 69, 55, 82, 75, 108, 89, 54, 111, 74, 79, 57, 114, 52, 65, 107, 52, 65, 112, 43, 53, 56, 114, 86, 121, 117, 105, 70, 86, 100, 119, 50, 75, 117, 71, 85, 97, 74, 80, 72, 90, 110, 74, 69, 68, 52, 65, 104, 77, 109, 119, 108, 120, 121, 79, 65, 103, 119, 114, 114, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 84, 85, 66, 73, 84, 65, 75, 32, 75, 97, 109, 117, 32, 83, 77, 32, 83, 83, 76, 32, 75, 111, 107, 32, 83, 101, 114, 116, 105, 102, 105, 107, 97, 115, 105, 32, 45, 32, 83, 117, 114, 117, 109, 32, 49, 10, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 89, 122, 67, 67, 65, 48, 117, 103, 65, 119, 73, 66, 65, 103, 73, 66, 65, 84, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 68, 67, 66, 48, 106, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 70, 73, 120, 71, 68, 65, 87, 66, 103, 78, 86, 66, 65, 99, 84, 10, 68, 48, 100, 108, 89, 110, 112, 108, 73, 67, 48, 103, 83, 50, 57, 106, 89, 87, 86, 115, 97, 84, 70, 67, 77, 69, 65, 71, 65, 49, 85, 69, 67, 104, 77, 53, 86, 72, 86, 121, 97, 50, 108, 53, 90, 83, 66, 67, 97, 87, 120, 112, 98, 88, 78, 108, 98, 67, 66, 50, 90, 83, 66, 85, 90, 87, 116, 117, 98, 50, 120, 118, 97, 109, 108, 114, 10, 73, 69, 70, 121, 89, 88, 78, 48, 97, 88, 74, 116, 89, 83, 66, 76, 100, 88, 74, 49, 98, 88, 85, 103, 76, 83, 66, 85, 86, 85, 74, 74, 86, 69, 70, 76, 77, 83, 48, 119, 75, 119, 89, 68, 86, 81, 81, 76, 69, 121, 82, 76, 89, 87, 49, 49, 73, 70, 78, 108, 99, 110, 82, 112, 90, 109, 108, 114, 89, 88, 78, 53, 98, 50, 52, 103, 10, 84, 87, 86, 121, 97, 50, 86, 54, 97, 83, 65, 116, 73, 69, 116, 104, 98, 88, 85, 103, 85, 48, 48, 120, 78, 106, 65, 48, 66, 103, 78, 86, 66, 65, 77, 84, 76, 86, 82, 86, 81, 107, 108, 85, 81, 85, 115, 103, 83, 50, 70, 116, 100, 83, 66, 84, 84, 83, 66, 84, 85, 48, 119, 103, 83, 50, 57, 114, 73, 70, 78, 108, 99, 110, 82, 112, 10, 90, 109, 108, 114, 89, 88, 78, 112, 73, 67, 48, 103, 85, 51, 86, 121, 100, 87, 48, 103, 77, 84, 65, 101, 70, 119, 48, 120, 77, 122, 69, 120, 77, 106, 85, 119, 79, 68, 73, 49, 78, 84, 86, 97, 70, 119, 48, 48, 77, 122, 69, 119, 77, 106, 85, 119, 79, 68, 73, 49, 78, 84, 86, 97, 77, 73, 72, 83, 77, 81, 115, 119, 67, 81, 89, 68, 10, 86, 81, 81, 71, 69, 119, 74, 85, 85, 106, 69, 89, 77, 66, 89, 71, 65, 49, 85, 69, 66, 120, 77, 80, 82, 50, 86, 105, 101, 109, 85, 103, 76, 83, 66, 76, 98, 50, 78, 104, 90, 87, 120, 112, 77, 85, 73, 119, 81, 65, 89, 68, 86, 81, 81, 75, 69, 122, 108, 85, 100, 88, 74, 114, 97, 88, 108, 108, 73, 69, 74, 112, 98, 71, 108, 116, 10, 99, 50, 86, 115, 73, 72, 90, 108, 73, 70, 82, 108, 97, 50, 53, 118, 98, 71, 57, 113, 97, 87, 115, 103, 81, 88, 74, 104, 99, 51, 82, 112, 99, 109, 49, 104, 73, 69, 116, 49, 99, 110, 86, 116, 100, 83, 65, 116, 73, 70, 82, 86, 81, 107, 108, 85, 81, 85, 115, 120, 76, 84, 65, 114, 66, 103, 78, 86, 66, 65, 115, 84, 74, 69, 116, 104, 10, 98, 88, 85, 103, 85, 50, 86, 121, 100, 71, 108, 109, 97, 87, 116, 104, 99, 51, 108, 118, 98, 105, 66, 78, 90, 88, 74, 114, 90, 88, 112, 112, 73, 67, 48, 103, 83, 50, 70, 116, 100, 83, 66, 84, 84, 84, 69, 50, 77, 68, 81, 71, 65, 49, 85, 69, 65, 120, 77, 116, 86, 70, 86, 67, 83, 86, 82, 66, 83, 121, 66, 76, 89, 87, 49, 49, 10, 73, 70, 78, 78, 73, 70, 78, 84, 84, 67, 66, 76, 98, 50, 115, 103, 85, 50, 86, 121, 100, 71, 108, 109, 97, 87, 116, 104, 99, 50, 107, 103, 76, 83, 66, 84, 100, 88, 74, 49, 98, 83, 65, 120, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 10, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 114, 51, 85, 119, 77, 54, 113, 55, 97, 57, 79, 90, 76, 66, 73, 51, 104, 78, 109, 78, 101, 53, 101, 65, 48, 50, 55, 110, 47, 53, 116, 81, 108, 84, 54, 81, 108, 86, 90, 67, 49, 120, 108, 56, 74, 111, 83, 78, 107, 118, 111, 66, 72, 84, 111, 80, 52, 109, 81, 52, 116, 52, 121, 56, 10, 54, 73, 106, 53, 105, 121, 83, 114, 76, 113, 80, 49, 78, 43, 82, 65, 106, 104, 103, 108, 101, 89, 78, 49, 72, 122, 118, 47, 98, 75, 106, 70, 120, 108, 98, 52, 116, 79, 50, 75, 82, 75, 79, 114, 98, 69, 122, 56, 72, 100, 68, 99, 55, 50, 105, 57, 122, 43, 83, 113, 122, 118, 66, 86, 57, 54, 73, 48, 49, 73, 78, 114, 78, 51, 119, 99, 10, 119, 118, 54, 49, 65, 43, 120, 88, 122, 114, 121, 48, 116, 99, 88, 116, 65, 65, 57, 84, 78, 121, 112, 78, 57, 69, 56, 77, 103, 47, 117, 71, 122, 56, 118, 43, 106, 69, 54, 57, 104, 47, 109, 110, 105, 121, 70, 88, 110, 72, 114, 102, 65, 50, 101, 74, 76, 74, 50, 88, 89, 97, 99, 81, 117, 70, 87, 81, 102, 119, 52, 116, 74, 122, 104, 48, 10, 51, 43, 102, 57, 50, 107, 52, 83, 52, 48, 48, 86, 73, 103, 76, 73, 52, 79, 68, 56, 68, 54, 50, 75, 49, 56, 108, 85, 85, 77, 119, 55, 68, 56, 111, 87, 103, 73, 84, 81, 85, 86, 98, 68, 106, 108, 90, 47, 105, 83, 73, 122, 76, 43, 97, 70, 67, 114, 50, 108, 113, 66, 115, 50, 51, 116, 80, 99, 76, 71, 48, 55, 120, 120, 79, 57, 10, 87, 83, 77, 115, 53, 117, 87, 107, 57, 57, 103, 76, 55, 101, 113, 81, 81, 69, 83, 111, 108, 98, 117, 84, 49, 100, 67, 65, 78, 76, 90, 71, 101, 65, 52, 102, 65, 74, 78, 71, 52, 101, 55, 112, 43, 101, 120, 80, 70, 119, 73, 68, 65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 10, 90, 84, 47, 72, 105, 111, 98, 71, 80, 78, 48, 56, 86, 70, 119, 49, 43, 68, 114, 116, 85, 103, 120, 72, 86, 56, 103, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 65, 56, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 70, 77, 65, 77, 66, 65, 102, 56, 119, 68, 81, 89, 74, 10, 75, 111, 90, 73, 104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 68, 103, 103, 69, 66, 65, 67, 111, 47, 52, 102, 69, 121, 106, 113, 55, 104, 109, 70, 120, 76, 88, 115, 57, 114, 72, 109, 111, 74, 48, 105, 75, 112, 69, 115, 100, 101, 86, 51, 49, 122, 86, 109, 83, 65, 104, 72, 113, 84, 53, 65, 109, 53, 69, 77, 50, 102, 75, 105, 102, 104, 10, 65, 72, 101, 43, 83, 77, 103, 49, 113, 73, 71, 102, 53, 76, 103, 115, 121, 88, 56, 79, 115, 78, 74, 76, 78, 49, 51, 113, 117, 100, 85, 76, 88, 106, 83, 57, 57, 72, 77, 112, 119, 43, 48, 109, 70, 90, 120, 43, 67, 70, 79, 75, 87, 73, 51, 81, 83, 121, 106, 102, 119, 98, 80, 102, 73, 80, 80, 53, 52, 43, 77, 54, 51, 56, 121, 99, 10, 108, 78, 104, 79, 84, 56, 78, 114, 70, 55, 102, 51, 99, 117, 105, 116, 90, 106, 79, 49, 74, 86, 79, 114, 52, 80, 104, 77, 113, 90, 51, 57, 56, 103, 50, 54, 114, 114, 110, 90, 113, 115, 90, 114, 43, 90, 79, 55, 114, 113, 117, 52, 108, 122, 119, 68, 71, 114, 112, 68, 120, 112, 97, 53, 82, 88, 73, 52, 115, 54, 101, 104, 108, 106, 50, 82, 10, 101, 51, 55, 65, 73, 86, 78, 77, 104, 43, 51, 121, 67, 49, 83, 86, 85, 90, 80, 86, 73, 113, 85, 78, 105, 118, 71, 84, 68, 106, 53, 85, 68, 114, 68, 89, 121, 85, 55, 99, 56, 106, 69, 121, 86, 117, 112, 107, 43, 101, 113, 49, 110, 82, 90, 109, 81, 110, 76, 122, 102, 57, 79, 120, 77, 85, 80, 56, 112, 73, 52, 88, 56, 87, 48, 106, 10, 113, 53, 82, 109, 43, 75, 51, 55, 68, 119, 104, 117, 74, 105, 49, 47, 70, 119, 99, 74, 115, 111, 122, 55, 85, 77, 67, 102, 108, 111, 51, 80, 116, 118, 48, 65, 110, 86, 111, 85, 109, 114, 56, 67, 82, 80, 88, 66, 119, 112, 56, 105, 88, 113, 73, 80, 111, 101, 77, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, }; return cav; } } // namespace net } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/net/connect.cpp000066400000000000000000000304701315356162600242420ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifdef HAVE_CONFIG_H #include "config.h" // For MK_CA_BUNDLE #endif #ifndef MK_CA_BUNDLE #error "MK_CA_BUNDLE is not set." #endif #include "private/net/connect_impl.hpp" #include "private/net/emitter.hpp" #include "private/net/socks5.hpp" #include "private/net/utils.hpp" #include "private/libevent/connection.hpp" #include "private/net/libssl.hpp" #include #include #include #include #include #include #include #include #include void mk_bufferevent_on_event(bufferevent *bev, short what, void *ptr) { auto cb = static_cast *>(ptr); if ((what & BEV_EVENT_CONNECTED) != 0) { (*cb)(mk::NoError(), bev); } else if ((what & BEV_EVENT_TIMEOUT) != 0) { (*cb)(mk::net::TimeoutError(), bev); } else { mk::Error err; /* * If there's not network error, assume it's going to be a SSL error, * which is reasonable because currently we only use this function * as callback for either socket or SSL connect. */ if (errno != 0) { err = mk::net::map_errno(errno); } else { long ssl_err = bufferevent_get_openssl_error(bev); std::string s = ERR_error_string(ssl_err, nullptr); err = mk::net::SslError(s); } (*cb)(err, bev); } delete cb; } namespace mk { namespace net { using namespace mk::libevent; void connect_first_of(Var result, int port, ConnectFirstOfCb cb, Settings settings, Var reactor, Var logger, size_t index, Var> errors) { logger->debug("connect_first_of begin"); if (!errors) { errors.reset(new std::vector()); } if (index >= result->resolve_result.addresses.size()) { logger->debug("connect_first_of all addresses failed"); cb(*errors, nullptr); return; } double timeout = settings.get("net/timeout", 30.0); connect_base(result->resolve_result.addresses[index], port, [=](Error err, bufferevent *bev, double connect_time) { errors->push_back(err); if (err) { logger->debug("connect_first_of failure"); connect_first_of(result, port, cb, settings, reactor, logger, index + 1, errors); return; } logger->debug("connect_first_of success"); result->connect_time = connect_time; cb(*errors, bev); }, timeout, reactor, logger); } void connect_logic(std::string hostname, int port, Callback> cb, Settings settings, Var reactor, Var logger) { Var result(new ConnectResult); dns::resolve_hostname(hostname, [=](dns::ResolveHostnameResult r) { result->resolve_result = r; if (result->resolve_result.addresses.size() <= 0) { cb(DnsGenericError(), result); return; } connect_first_of( result, port, [=](std::vector e, bufferevent *b) { result->connect_result = e; result->connected_bev = b; if (!b) { if (e.size() == 1) { // Improvement: do not hide the reason // why we failed if we have just one // connect() attempt in the vector cb(e[0], result); return; } // Otherwise, report them all Error connect_error = ConnectFailedError(); for (auto se: e) { connect_error.add_child_error(se); } cb(connect_error, result); return; } Error nagle_error = disable_nagle( bufferevent_getfd(result->connected_bev) ); for (auto se: e) { nagle_error.add_child_error(se); } cb(nagle_error, result); }, settings, reactor, logger); }, settings, reactor, logger); } void connect_ssl(bufferevent *orig_bev, ssl_st *ssl, std::string hostname, Callback cb, Var reactor, Var logger) { logger->debug("connect ssl..."); // See similar comment in connect_impl.hpp for rationale. static const int flags = BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS; auto bev = bufferevent_openssl_filter_new( reactor->get_event_base(), orig_bev, ssl, BUFFEREVENT_SSL_CONNECTING, flags); if (bev == nullptr) { bufferevent_free(orig_bev); cb(GenericError(), nullptr); return; } bufferevent_setcb( bev, nullptr, nullptr, mk_bufferevent_on_event, new Callback( [cb, logger, hostname](Error err, bufferevent *bev) { logger->debug("connect ssl... callback (error: %d)", err.code); ssl_st *ssl = bufferevent_openssl_get_ssl(bev); if (err) { std::string s = err.explain(); logger->debug("error in connection: %s", s.c_str()); bufferevent_free(bev); cb(err, nullptr); return; } err = libssl::verify_peer(hostname, ssl, logger); if (err) { bufferevent_free(bev); cb(err, nullptr); return; } cb(err, bev); })); } void connect_many(std::string address, int port, int num, ConnectManyCb callback, Settings settings, Var reactor, Var logger) { connect_many_impl(connect_many_make( address, port, num, callback, settings, reactor, logger)); } void connect(std::string address, int port, Callback> callback, Settings settings, Var reactor, Var logger) { if (settings.find("net/dumb_transport") != settings.end()) { callback(NoError(), make_txp( 0.0, nullptr, reactor, logger)); return; } if (settings.find("net/socks5_proxy") != settings.end()) { socks5_connect(address, port, settings, callback, reactor, logger); return; } if (settings.find("net/timeout") == settings.end()) { settings["net/timeout"] = 30.0; } double timeout = settings["net/timeout"].as(); connect_logic( address, port, [=](Error err, Var r) { if (err) { callback(err, make_txp( timeout, r, reactor, logger)); return; } if (settings.find("net/ssl") != settings.end()) { std::string cbp = MK_CA_BUNDLE; if (settings.find("net/ca_bundle_path") != settings.end()) { cbp = settings.at("net/ca_bundle_path"); } logger->debug("ca_bundle_path: '%s'", cbp.c_str()); ErrorOr cssl = libssl::Cache<>::thread_local_instance() .get_client_ssl(cbp, address, logger); if (!cssl) { Error err = cssl.as_error(); bufferevent_free(r->connected_bev); callback(err, make_txp( timeout, r, reactor, logger)); return; } ErrorOr allow_ssl23 = settings.get_noexcept("net/allow_ssl23", false); if (!allow_ssl23) { Error err = ValueError(); bufferevent_free(r->connected_bev); callback(err, make_txp( timeout, r, reactor, logger)); return; } if (*allow_ssl23 == true) { logger->info("Re-enabling SSLv2 and SSLv3"); libssl::enable_v23(*cssl); } connect_ssl(r->connected_bev, *cssl, address, [r, callback, timeout, reactor, logger, settings](Error err, bufferevent *bev) { if (err) { callback(err, make_txp( timeout, r, reactor, logger)); return; } ErrorOr allow_dirty_shutdown = settings.get_noexcept( "net/ssl_allow_dirty_shutdown", false); if (!allow_dirty_shutdown) { Error err = allow_dirty_shutdown.as_error(); bufferevent_free(bev); callback(err, make_txp( timeout, r, reactor, logger)); return; } if (*allow_dirty_shutdown == true) { /* * This useful libevent function is only * available since libevent 2.1.0: */ #ifdef HAVE_BUFFEREVENT_OPENSSL_SET_ALLOW_DIRTY_SHUTDOWN bufferevent_openssl_set_allow_dirty_shutdown( bev, 1); logger->info("Allowing dirty SSL shutdown"); #else logger->warn("Cannot tell libevent to " "allow SSL dirty shutdowns " "as requested by the " "programmer: as a result" "some SSL connections may " "interrupt abruptly with an " "error. This happens because " "you are not using version " "2.1.x of libevent."); #endif } assert(err == NoError()); callback(err, make_txp( libevent::Connection::make( bev, reactor, logger), timeout, r)); }, reactor, logger); return; } assert(err == NoError()); callback(err, make_txp(libevent::Connection::make( r->connected_bev, reactor, logger), timeout, r)); }, settings, reactor, logger); } } // namespace net } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/net/emitter.cpp000066400000000000000000000022471315356162600242630ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/net/emitter.hpp" namespace mk { namespace net { EmitterBase::~EmitterBase() { if (close_cb) { close_cb(); } } void EmitterBase::close(Callback<> cb) { if (close_pending) { /* * Rationale for throwing rather than ignoring: (1) it was the * behavior before we started refactoring; (2) the user expects * a callback to be called after close is successful. If we do * ignore subsequent close attempts, the promise that the callback * will be called is silently broken, and it seems instead better * to inform the caller that there is a problem with the code * because `close()` has been called more than once. */ throw std::runtime_error("close already pending"); } close_pending = true; shutdown(); on_connect(nullptr); on_data(nullptr); on_flush(nullptr); on_error(nullptr); close_cb = cb; } Emitter::~Emitter() {} } // namespace net } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/net/socks5.cpp000066400000000000000000000155141315356162600240220ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/net/socks5.hpp" #include "private/net/connect_impl.hpp" #include "private/libevent/connection.hpp" namespace mk { namespace net { Socks5::Socks5(Var tx, Settings s, Var r, Var lp) : Emitter(r, lp), settings(s), conn(tx), proxy_address(settings["net/socks5_address"]), proxy_port(settings["net/socks5_port"]) { socks5_connect_(); } Buffer socks5_format_auth_request(Var logger) { Buffer out; out.write_uint8(5); // Version out.write_uint8(1); // Number of methods out.write_uint8(0); // "NO_AUTH" meth. logger->debug("socks5: >> version=5"); logger->debug("socks5: >> number of methods=1"); logger->debug("socks5: >> NO_AUTH (0)"); return out; } ErrorOr socks5_parse_auth_response(Buffer &buffer, Var logger) { auto readbuf = buffer.readn(2); if (readbuf == "") { return false; // Try again after next recv() } logger->debug("socks5: << version=%d", readbuf[0]); logger->debug("socks5: << preferred_auth=%d", readbuf[1]); if (readbuf[0] != 5) { return BadSocksVersionError(); } if (readbuf[1] != 0) { return NoAvailableSocksAuthenticationError(); } return true; } ErrorOr socks5_format_connect_request(Settings settings, Var logger) { Buffer out; out.write_uint8(5); // Version out.write_uint8(1); // CMD_CONNECT out.write_uint8(0); // Reserved out.write_uint8(3); // ATYPE_DOMAINNAME logger->debug("socks5: >> version=5"); logger->debug("socks5: >> CMD_CONNECT (1)"); logger->debug("socks5: >> Reserved (0)"); logger->debug("socks5: >> ATYPE_DOMAINNAME (3)"); auto address = settings["net/address"]; if (address.length() > 255) { return SocksAddressTooLongError(); } out.write_uint8(address.length()); // Len out.write(address.c_str(), address.length()); // String logger->debug("socks5: >> domain len=%d", (uint8_t)address.length()); logger->debug("socks5: >> domain str=%s", address.c_str()); int portnum = settings["net/port"].as(); if (portnum < 0 || portnum > 65535) { return SocksInvalidPortError(); } out.write_uint16(portnum); // Port logger->debug("socks5: >> port=%d", portnum); return out; } ErrorOr socks5_parse_connect_response(Buffer &buffer, Var logger) { if (buffer.length() < 5) { return false; // Try again after next recv() } auto peekbuf = buffer.peek(5); logger->debug("socks5: << version=%d", peekbuf[0]); logger->debug("socks5: << reply=%d", peekbuf[1]); logger->debug("socks5: << reserved=%d", peekbuf[2]); logger->debug("socks5: << atype=%d", peekbuf[3]); if (peekbuf[0] != 5) { return BadSocksVersionError(); } if (peekbuf[1] != 0) { return SocksError(); // TODO: also return the actual error } if (peekbuf[2] != 0) { return BadSocksReservedFieldError(); } auto atype = peekbuf[3]; // Atype size_t total = 4; // Version .. Atype size if (atype == 1) { total += 4; // IPv4 addr size } else if (atype == 3) { total += 1 + peekbuf[4]; // Len size + String size } else if (atype == 4) { total += 16; // IPv6 addr size } else { return BadSocksAtypeValueError(); } total += 2; // Port size if (buffer.length() < total) { return false; // Try again after next recv() } buffer.discard(total); return true; } void socks5_connect(std::string address, int port, Settings settings, Callback> callback, Var reactor, Var logger) { auto proxy = settings["net/socks5_proxy"]; auto pos = proxy.find(":"); if (pos == std::string::npos) { throw std::runtime_error("invalid argument"); } auto proxy_address = proxy.substr(0, pos); auto proxy_port = proxy.substr(pos + 1); settings["net/address"] = address; settings["net/port"] = port; connect_logic(proxy_address, lexical_cast(proxy_port), [=](Error err, Var r) { if (err) { callback(err, make_txp( 0.0, r, reactor, logger)); return; } Var txp = libevent::Connection::make( r->connected_bev, reactor, logger); Var socks5 = make_txp( 0.0, r, txp, settings, reactor, logger); socks5->on_connect([=]() { socks5->on_connect(nullptr); socks5->on_error(nullptr); callback(NoError(), socks5); }); socks5->on_error([=](Error error) { socks5->on_connect(nullptr); socks5->on_error(nullptr); callback(error, socks5); }); }, settings, reactor, logger); } void Socks5::socks5_connect_() { // Step #1: send out preferred authentication methods logger->debug("socks5: connected to Tor!"); conn->write(socks5_format_auth_request(logger)); // Step #2: receive the allowed authentication methods conn->on_data([this](Buffer d) { buffer << d; ErrorOr result = socks5_parse_auth_response(buffer, logger); if (!result) { emit_error(result.as_error()); return; } if (!*result) { return; } // Step #3: ask Tor to connect to remote host ErrorOr out = socks5_format_connect_request(settings, logger); if (!out) { emit_error(out.as_error()); return; } conn->write(*out); // Step #4: receive Tor's response conn->on_data([this](Buffer d) { buffer << d; ErrorOr rc = socks5_parse_connect_response(buffer, logger); if (!rc) { emit_error(rc.as_error()); return; } if (!*rc) { return; } // // Step #5: we are now connected // Restore the original hooks // Tell upstream we are connected // If more data, pass it up // conn->on_data([this](Buffer d) { emit_data(d); }); conn->on_flush([this]() { emit_flush(); }); emit_connect(); // Note that emit_connect() may have called close() if (!isclosed && buffer.length() > 0) { emit_data(buffer); } }); }); } } // namespace net } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/net/transport.cpp000066400000000000000000000036341315356162600246470ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include #include "private/net/connect.hpp" #include "private/net/emitter.hpp" #include "private/net/socks5.hpp" namespace mk { namespace net { TransportEmitter::~TransportEmitter() {} TransportRecorder::~TransportRecorder() {} TransportWriter::~TransportWriter() {} TransportSocks5::~TransportSocks5() {} TransportPollable::~TransportPollable() {} TransportConnectable::~TransportConnectable() {} TransportSockNamePeerName::~TransportSockNamePeerName() {} Transport::~Transport() {} void write(Var txp, Buffer buf, Callback cb) { txp->on_flush([=]() { txp->on_flush(nullptr); txp->on_error(nullptr); cb(NoError()); }); txp->on_error([=](Error err) { txp->on_flush(nullptr); txp->on_error(nullptr); cb(err); }); txp->write(buf); } void readn(Var txp, Var buff, size_t n, Callback cb, Var reactor) { if (buff->length() >= n) { // Shortcut that simplifies coding a great deal - yet, do not callback // immediately to avoid O(N) stack consumption reactor->call_soon([=]() { cb(NoError()); }); return; } txp->on_data([=](Buffer d) { *buff << d; if (buff->length() < n) { return; } txp->on_data(nullptr); txp->on_error(nullptr); cb(NoError()); }); txp->on_error([=](Error error) { txp->on_data(nullptr); txp->on_error(nullptr); cb(error); }); } void read(Var t, Var buff, Callback callback, Var reactor) { readn(t, buff, 1, callback, reactor); } } // namespace net } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/net/utils.cpp000066400000000000000000000246021315356162600237510ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ext/http_parser.h" #include "private/net/utils.hpp" #include #include #include #include #include #include #include namespace mk { namespace net { static Error make_sockaddr_ipv4(std::string s, uint16_t p, sockaddr_storage *ss, socklen_t *solen) noexcept { sockaddr_storage ss4 = {}; sockaddr_in *sin4 = (sockaddr_in *)&ss4; if (inet_pton(AF_INET, s.c_str(), &sin4->sin_addr) != 1) { return ValueError(); } sin4->sin_family = AF_INET; sin4->sin_port = htons(p); if (ss != nullptr) { *ss = ss4; } if (solen != nullptr) { *solen = sizeof(*sin4); } return NoError(); } static Error make_sockaddr_ipv6(std::string s, uint16_t p, sockaddr_storage *ss, socklen_t *solen) noexcept { sockaddr_storage ss6 = {}; sockaddr_in6 *sin6 = (sockaddr_in6 *)&ss6; if (inet_pton(AF_INET6, s.c_str(), &sin6->sin6_addr) != 1) { return ValueError(); } sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(p); if (ss != nullptr) { *ss = ss6; } if (solen != nullptr) { *solen = sizeof(*sin6); } return NoError(); } bool is_ipv4_addr(std::string s) { return make_sockaddr_ipv4(s, 80, nullptr, nullptr) == NoError(); } bool is_ipv6_addr(std::string s) { return make_sockaddr_ipv6(s, 80, nullptr, nullptr) == NoError(); } bool is_ip_addr(std::string s) { return is_ipv4_addr(s) || is_ipv6_addr(s); } static ErrorOr parse_endpoint_internal(std::string s) { http_parser_url parser = {}; http_parser_url_init(&parser); /* * Here the trick is that we ask the parser to parse the URL typically * passed to the CONNECT header, which is in the format we want. */ if (http_parser_parse_url(s.data(), s.size(), 1, &parser) != 0) { return ValueError(); } assert(parser.field_set == ((1 << UF_HOST) | (1 << UF_PORT))); Endpoint epnt = {}; epnt.hostname = s.substr(parser.field_data[UF_HOST].off, parser.field_data[UF_HOST].len); epnt.port = parser.port; return epnt; } static std::string serialize_address_port(std::string a, uint16_t p) { std::stringstream ss; bool is_ipv6 = is_ipv6_addr(a); if (is_ipv6) ss << "["; ss << a; if (is_ipv6) ss << "]"; ss << ":"; ss << p; std::string s = ss.str(); return s; } ErrorOr parse_endpoint(std::string s, uint16_t default_port) { ErrorOr maybe_epnt = parse_endpoint_internal(s); if (!!maybe_epnt) { return maybe_epnt; } /* * The CONNECT parser is quite strict. It fails if the port is not * present. After first failure, retry adding the default port. */ return parse_endpoint_internal(serialize_address_port(s, default_port)); } ErrorOr endpoint_from_sockaddr_storage(sockaddr_storage *ss) noexcept { // Code adapted from private/dns/getaddrinfo_async.hpp char abuf[128]; void *aptr = nullptr; Endpoint epnt; if (ss->ss_family == AF_INET) { aptr = &((sockaddr_in *)ss)->sin_addr; epnt.port = ntohs(((sockaddr_in *)ss)->sin_port); } else if (ss->ss_family == AF_INET6) { aptr = &((sockaddr_in6 *)ss)->sin6_addr; epnt.port = ntohs(((sockaddr_in6 *)ss)->sin6_port); } else { return ValueError("invalid_family"); } if (inet_ntop(ss->ss_family, aptr, abuf, sizeof(abuf)) == nullptr) { return GenericError("inet_ntop_failure"); } epnt.hostname = abuf; return epnt; } std::string serialize_endpoint(Endpoint epnt) { return serialize_address_port(epnt.hostname, epnt.port); } int storage_init(sockaddr_storage *storage, socklen_t *salen, const char *family, const char *address, const char *port, Var logger) { int _family; /* TODO: support also AF_INET, AF_INET6, ... */ if (strcmp(family, "PF_INET") == 0) { _family = PF_INET; } else if (strcmp(family, "PF_INET6") == 0) { _family = PF_INET6; } else { warn("utils:storage_init: invalid family"); return -1; } return storage_init(storage, salen, _family, address, port, logger); } int storage_init(sockaddr_storage *storage, socklen_t *salen, int _family, const char *address, const char *port, Var logger) { const char *errstr; int _port = (int)mkp_strtonum(port, 0, 65535, &errstr); if (errstr != nullptr) { warn("utils:storage_init: invalid port"); return -1; } return storage_init(storage, salen, _family, address, _port, logger); } int storage_init(sockaddr_storage *storage, socklen_t *salen, int _family, const char *address, int _port, Var logger) { int result; if (_port < 0 || _port > 65535) { logger->warn("utils:storage_init: invalid port"); return -1; } /* * TODO: merge this code with the above helpers. */ memset(storage, 0, sizeof(*storage)); switch (_family) { case PF_INET6: { sockaddr_in6 *sin6 = (sockaddr_in6 *)storage; sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(_port); if (address != nullptr) { result = inet_pton(AF_INET6, address, &sin6->sin6_addr); if (result != 1) { logger->warn("utils:storage_init: invalid addr"); return -1; } } else { sin6->sin6_addr = in6addr_any; } *salen = sizeof(sockaddr_in6); break; } case PF_INET: { sockaddr_in *sin = (sockaddr_in *)storage; sin->sin_family = AF_INET; sin->sin_port = htons(_port); if (address != nullptr) { result = inet_pton(AF_INET, address, &sin->sin_addr); if (result != 1) { logger->warn("utils:storage_init: invalid addr"); return -1; } } else { sin->sin_addr.s_addr = INADDR_ANY; } *salen = sizeof(sockaddr_in); break; } default: logger->warn("utils:storage_init - invalid family"); return -1; } return 0; } socket_t socket_create(int domain, int type, int protocol, Var logger) { socket_t filedesc; int result; filedesc = socket(domain, type, protocol); if (filedesc == -1) { logger->warn("utils:socket: cannot create socket"); return -1; } result = evutil_make_socket_nonblocking(filedesc); if (result != 0) { logger->warn("utils:socket: cannot make nonblocking"); (void)evutil_closesocket(filedesc); return -1; } return filedesc; } std::string unreverse_ipv6(std::string s) { size_t i = 0, added = 0; std::deque r; for (; i < s.size(); ++i) { if ((i % 2) == 0) { if (!isxdigit(s[i])) { break; } r.push_front(s[i]); if ((++added % 4) == 0 && added <= 28) { r.push_front(':'); } } else { if (s[i] != '.') { return ""; } } } if (s.substr(i) != "ip6.arpa" && s.substr(i) != "ip6.arpa.") { return ""; } return std::string(r.begin(), r.end()); } std::string unreverse_ipv4(std::string s) { std::deque r, t; size_t i = 0, seen = 0; unsigned cur = 0; for (; i < s.size(); ++i) { if (s[i] == '.') { if (cur > 255) { return ""; } if (seen++ > 0) { r.push_front('.'); } r.insert(r.begin(), t.begin(), t.end()); t.clear(); cur = 0; } else if (isdigit(s[i])) { t.push_back(s[i]); char tmpstr[] = {s[i], '\0'}; cur = cur * 10 + atoi(tmpstr); } else { break; } } if (s.substr(i) != "in-addr.arpa" && s.substr(i) != "in-addr.arpa.") { return ""; } return std::string(r.begin(), r.end()); } Error disable_nagle(socket_t sockfd) { static const int disable = 1; if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&disable, sizeof (disable)) != 0) { return SocketError(); } return NoError(); } Error map_errno(int error_code) { if (error_code == 0) { return NoError(); } /* * In most Unix systems they are the same error. For the few systems in * which they are not (and note I don't even know whether measurement-kit * does compile on these systems), force EAGAIN to be EWOULDBLOCK. * * (Yes, EWOULDBLOCK is a BSD-ism, but I like it more.) */ if (error_code == EAGAIN) { error_code = EWOULDBLOCK; // FALLTHROUGH } #define XX(_code_, _name_, _descr_) \ if (std::make_error_condition(std::errc::_descr_).value() == error_code) { \ return _name_(); \ } MK_NET_ERRORS_XX #undef XX return GenericError(); } Error make_sockaddr(std::string s, std::string p, sockaddr_storage *ss, socklen_t *solen) noexcept { auto maybe_pn = lexical_cast_noexcept(p); if (!maybe_pn) { return maybe_pn.as_error(); } /* * I initially thought that lexical_cast would have been able to detect * overflow caused by negative numbers being feed to it when requested to * parse a positive only integer. It seems it's not always like this. * * See */ if (*maybe_pn < 0 || *maybe_pn > 65535) { return ValueError(); } // Static cast good because above we make sure it is feasible return make_sockaddr(s, static_cast(*maybe_pn), ss, solen); } Error make_sockaddr(std::string s, uint16_t p, sockaddr_storage *ss, socklen_t *solen) noexcept { Error err = make_sockaddr_ipv4(s, p, ss, solen); if (err != NoError()) { err = make_sockaddr_ipv6(s, p, ss, solen); } return err; } } // namespace net } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/000077500000000000000000000000001315356162600231645ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/nettests/base_test.cpp000066400000000000000000000061261315356162600256460ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/nettests/runnable.hpp" #include "private/nettests/runner.hpp" #include #include namespace mk { namespace nettests { BaseTest &BaseTest::on_logger_eof(Delegate<> func) { runnable->logger->on_eof(func); return *this; } BaseTest &BaseTest::on_log(Delegate func) { runnable->logger->on_log(func); return *this; } BaseTest &BaseTest::on_event(Delegate func) { runnable->logger->on_event(func); return *this; } BaseTest &BaseTest::on_progress(Delegate func) { runnable->logger->on_progress(func); return *this; } BaseTest &BaseTest::set_verbosity(uint32_t level) { runnable->logger->set_verbosity(level); return *this; } BaseTest &BaseTest::increase_verbosity() { runnable->logger->increase_verbosity(); return *this; } BaseTest::BaseTest() {} BaseTest::~BaseTest() {} BaseTest &BaseTest::add_input(std::string s) { // Note: ooni-probe does not allow to specify more than one input from the // command line. Given that the underlying code allows that, I do not see a // reason to be artifically restrictive here. runnable->inputs.push_back(s); return *this; } BaseTest &BaseTest::add_input_filepath(std::string s) { runnable->input_filepaths.push_back(s); return *this; } BaseTest &BaseTest::set_input_filepath(std::string s) { runnable->input_filepaths.clear(); return add_input_filepath(s); } BaseTest &BaseTest::set_output_filepath(std::string s) { runnable->output_filepath = s; return *this; } BaseTest &BaseTest::set_error_filepath(std::string s) { runnable->logger->set_logfile(s); return *this; } BaseTest &BaseTest::set_options(std::string key, std::string value) { runnable->options[key] = value; return *this; } BaseTest &BaseTest::on_entry(Delegate cb) { runnable->entry_cb = cb; return *this; } BaseTest &BaseTest::on_begin(Delegate<> cb) { runnable->begin_cb = cb; return *this; } BaseTest &BaseTest::on_end(Delegate<> cb) { runnable->end_cbs.push_back(cb); return *this; } BaseTest &BaseTest::on_destroy(Delegate<> cb) { runnable->destroy_cbs.push_back(cb); return *this; } void BaseTest::run() { // Note: here we MUST point to a fresh reactor which we know for sure is // not already being used otherwise we cannot run the test assert(not runnable->reactor); Var reactor = Reactor::make(); runnable->reactor = reactor; reactor->loop_with_initial_event([&]() { runnable->begin([&](Error) { runnable->end([&](Error) { reactor->call_soon([&]() { reactor->stop(); }); }); }); }); } void BaseTest::start(Callback<> callback) { Runner::global()->start_test(runnable, [=](Var) { callback(); }); } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/dash.cpp000066400000000000000000000017341315356162600246140ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/nettests/runnable.hpp" #include #include namespace mk { namespace nettests { DashTest::DashTest() : BaseTest() { runnable.reset(new DashRunnable); runnable->test_name = "dash"; runnable->test_version = "0.7.0"; runnable->needs_input = false; } void DashRunnable::main(std::string /*input*/, Settings options, Callback> cb) { auto entry = Var::make(); neubot::dash::negotiate(entry, options, reactor, logger, [=](Error error) { if (error) { (*entry)["failure"] = error.as_ooni_error(); } else { (*entry)["failure"] = nullptr; } cb(entry); }); } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/dns_injection.cpp000066400000000000000000000014311315356162600265150ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/nettests/runnable.hpp" #include #include namespace mk { namespace nettests { DnsInjectionTest::DnsInjectionTest() : BaseTest() { runnable.reset(new DnsInjectionRunnable); runnable->test_name = "dns_injection"; runnable->test_version = "0.0.1"; runnable->needs_input = true; } void DnsInjectionRunnable::main(std::string input, Settings options, Callback> cb) { ooni::dns_injection(input, options, cb, reactor, logger); } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/http_header_field_manipulation.cpp000066400000000000000000000020031315356162600320750ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/nettests/runnable.hpp" #include #include namespace mk { namespace nettests { HttpHeaderFieldManipulationTest::HttpHeaderFieldManipulationTest() : BaseTest() { runnable.reset(new HttpHeaderFieldManipulationRunnable); runnable->test_name = "http_header_field_manipulation"; runnable->test_version = "0.0.1"; runnable->needs_input = false; runnable->test_helpers_data = {{"http-return-json-headers", "backend"}}; } void HttpHeaderFieldManipulationRunnable::main(std::string input, Settings options, Callback> cb) { ooni::http_header_field_manipulation(input, options, cb, reactor, logger); } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/http_invalid_request_line.cpp000066400000000000000000000015611315356162600311370ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/nettests/runnable.hpp" #include #include namespace mk { namespace nettests { HttpInvalidRequestLineTest::HttpInvalidRequestLineTest() : BaseTest() { runnable.reset(new HttpInvalidRequestLineRunnable); runnable->test_name = "http_invalid_request_line"; runnable->test_version = "0.0.2"; runnable->test_helpers_data = {{"tcp-echo", "backend"}}; } void HttpInvalidRequestLineRunnable::main(std::string, Settings options, Callback> cb) { ooni::http_invalid_request_line(options, cb, reactor, logger); } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/meek_fronted_requests.cpp000066400000000000000000000015051315356162600302660ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/nettests/runnable.hpp" #include #include namespace mk { namespace nettests { MeekFrontedRequestsTest::MeekFrontedRequestsTest() : BaseTest() { runnable.reset(new MeekFrontedRequestsRunnable); runnable->test_name = "meek_fronted_requests"; runnable->test_version = "0.0.1"; runnable->needs_input = true; } void MeekFrontedRequestsRunnable::main(std::string input, Settings options, Callback> cb) { ooni::meek_fronted_requests(input, options, cb, reactor, logger); } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/multi_ndt.cpp000066400000000000000000000124321315356162600256710ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/nettests/runnable.hpp" #include #include #include "private/ndt/utils.hpp" namespace mk { namespace nettests { MultiNdtTest::MultiNdtTest() : BaseTest() { runnable.reset(new MultiNdtRunnable); runnable->options["save_real_probe_ip"] = true; runnable->options["dns/engine"] = "system"; runnable->test_name = "multi_ndt"; runnable->test_version = "0.1.0"; /* Forked from `ndt` v0.0.4 */ } static void write_simple_stats(report::Entry &entry, Var logger) { report::Entry single = mk::ndt::utils::compute_simple_stats(entry["single_stream"], logger); single["fastest_test"] = "single_stream"; report::Entry multi = mk::ndt::utils::compute_simple_stats(entry["multi_stream"], logger); multi["fastest_test"] = "multi_stream"; report::Entry selected; /* * Here we basically pick up the fastest of the two tests. */ if (single["ping"] != nullptr and multi["ping"] != nullptr) { if (single["download"] != nullptr and multi["download"] != nullptr) { double singled = single["download"]; double multid = multi["download"]; if (singled > multid) { selected = single; } else { selected = multi; } } else if (single["download"] != nullptr) { logger->warn("Multi-stream download is null"); selected = single; } else if (multi["download"] != nullptr) { logger->warn("Single-stream download is null"); selected = multi; } else { logger->warn("Single- and multi-stream download are null"); } } else if (single["ping"] != nullptr) { logger->warn("Multi-stream ping is null"); selected = single; } else if (multi["ping"] != nullptr) { logger->warn("Single-stream ping is null"); selected = multi; } else { logger->warn("Single- and multi-stream ping are null"); } entry["simple"] = selected; } void MultiNdtRunnable::main(std::string, Settings ndt_settings, Callback> cb) { // Note: `options` is the class attribute and `settings` is instead a // possibly modified copy of the `options` object Var ndt_entry(new report::Entry); (*ndt_entry)["failure"] = nullptr; // By default we only run download but let's allow clients to decide if (ndt_settings.count("single_test_suite") != 0) { ndt_settings["test_suite"] = ndt_settings["single_test_suite"]; } else { ndt_settings["test_suite"] = MK_NDT_DOWNLOAD; } logger->set_progress_offset(0.15); logger->set_progress_scale(0.35); logger->progress(0.0, "Starting single-stream test"); ndt::run(ndt_entry, [=](Error ndt_error) { if (ndt_error) { (*ndt_entry)["failure"] = ndt_error.as_ooni_error(); logger->warn("Test failed: %s", ndt_error.explain().c_str()); // FALLTHROUGH } Var neubot_entry(new report::Entry); (*neubot_entry)["failure"] = nullptr; Settings neubot_settings{ndt_settings.begin(), ndt_settings.end()}; neubot_settings["test_suite"] = MK_NDT_DOWNLOAD_EXT; neubot_settings["mlabns_tool_name"] = "neubot"; logger->set_progress_offset(0.55); logger->set_progress_scale(0.35); logger->progress(0.0, "Starting multi-stream test"); ndt::run(neubot_entry, [=](Error neubot_error) { logger->progress(1.0, "Test completed"); if (neubot_error) { (*neubot_entry)["failure"] = neubot_error.as_ooni_error(); logger->warn("Test failed: %s", neubot_error.explain().c_str()); // FALLTHROUGH } Var overall_entry(new report::Entry); (*overall_entry)["failure"] = nullptr; (*overall_entry)["multi_stream"] = *neubot_entry; (*overall_entry)["single_stream"] = *ndt_entry; if (ndt_error or neubot_error) { Error overall_error = SequentialOperationError(); overall_error.child_errors.push_back( Var{new Error{ndt_error}} ); overall_error.child_errors.push_back( Var{new Error{neubot_error}} ); (*overall_entry)["failure"] = overall_error.as_ooni_error(); // FALLTHROUGH } try { write_simple_stats(*overall_entry, logger); } catch (const std::exception &) { /* Just in case */ ; } try { (*overall_entry)["advanced"] = mk::ndt::utils::compute_advanced_stats( (*overall_entry)["single_stream"], logger); } catch (const std::exception &) { /* Just in case */ ; } cb(overall_entry); }, neubot_settings, reactor, logger); }, ndt_settings, reactor, logger); } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/ndt.cpp000066400000000000000000000026411315356162600244600ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/nettests/runnable.hpp" #include #include #include "private/ndt/utils.hpp" namespace mk { namespace nettests { NdtTest::NdtTest() : BaseTest() { runnable.reset(new NdtRunnable); runnable->test_name = "ndt"; runnable->test_version = "0.1.0"; } void NdtRunnable::main(std::string, Settings settings, Callback> cb) { Var entry(new report::Entry); (*entry)["failure"] = nullptr; // Note: `options` is the class attribute and `settings` is instead a // possibly modified copy of the `options` object ndt::run(entry, [=](Error error) { if (error) { (*entry)["failure"] = error.as_ooni_error(); } try { (*entry)["simple"] = mk::ndt::utils::compute_simple_stats(*entry, logger); } catch (const std::exception &) { /* Just in case */ ; } try { (*entry)["advanced"] = mk::ndt::utils::compute_advanced_stats(*entry, logger); } catch (const std::exception &) { /* Just in case */ ; } cb(entry); }, settings, reactor, logger); } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/runnable.cpp000066400000000000000000000365201315356162600255040ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/common/fmap.hpp" #include "private/common/parallel.hpp" #include "private/common/range.hpp" #include "private/nettests/runnable.hpp" #include "private/common/utils.hpp" #include "private/ooni/utils.hpp" #include "private/nettests/utils.hpp" #include #include namespace mk { namespace nettests { using namespace mk::report; using namespace mk::ooni; Runnable::~Runnable() { for (auto fn : destroy_cbs) { try { fn(); } catch (const std::exception &) { /* Suppress */ ; } } } void Runnable::setup(std::string) {} void Runnable::teardown(std::string) {} void Runnable::main(std::string, Settings, Callback> cb) { reactor->call_soon([=]() { cb(Var{new report::Entry}); }); } void Runnable::fixup_entry(report::Entry &) {} void Runnable::run_next_measurement(size_t thread_id, Callback cb, size_t num_entries, Var current_entry) { logger->debug("net_test: running next measurement"); double max_rt = options.get("max_runtime", -1.0); double max_rt_tolerance = max_rt / 10.0; double delta = mk::time_now() - beginning; if (max_rt >= 0.0 && delta > max_rt - max_rt_tolerance) { logger->info("Exceeded test maximum runtime"); cb(NoError()); return; } if (inputs.size() <= 0) { logger->debug("net_test: reached end of input"); cb(NoError()); return; } std::string next_input = inputs.front(); inputs.pop_front(); double prog = 0.0; if (max_rt > 0.0) { prog = delta / max_rt; } else if (num_entries > 0) { prog = *current_entry / (double)num_entries; } *current_entry += 1; if (next_input != "") { std::string description; description += "Processing input: "; description += next_input; logger->progress(prog, description.c_str()); } logger->debug("net_test: creating entry"); struct tm measurement_start_time; double start_time; mk::utc_time_now(&measurement_start_time); start_time = mk::time_now(); logger->debug("net_test: calling setup"); setup(next_input); logger->debug("net_test: running with input %s", next_input.c_str()); main(next_input, options, [=](Var test_keys) { report::Entry entry; entry["input"] = next_input; // Make sure the input is `null` rather than empty string if (entry["input"] == "") { entry["input"] = nullptr; } entry["test_keys"] = *test_keys; entry["test_keys"]["client_resolver"] = resolver_ip; entry["measurement_start_time"] = *mk::timestamp(&measurement_start_time); entry["test_runtime"] = mk::time_now() - start_time; entry["id"] = mk::sole::uuid4().str(); // Until we have support for passing options, leave it empty entry["options"] = Entry::array(); // Until we have support for it, just put `null` entry["probe_city"] = nullptr; // Add test helpers entry["test_helpers"] = Entry::object(); for (auto &name : test_helpers_option_names()) { if (options.count(name) != 0) { entry["test_helpers"][name] = options[name]; } } // Add empty input hashes entry["input_hashes"] = Entry::array(); logger->debug("net_test: tearing down"); teardown(next_input); report.fill_entry(entry); fixup_entry(entry); // Let drivers possibly fix-up the entry if (entry_cb) { try { entry_cb(entry.dump(4)); } catch (const std::exception &exc) { logger->warn("Unhandled exception in entry_cb(): %s", exc.what()); /* FALLTHROUGH */ } } report.write_entry(entry, [=](Error error) { if (error) { logger->warn("cannot write entry"); if (not options.get("ignore_write_entry_error", true)) { cb(error); return; } } else { logger->debug("net_test: written entry"); } reactor->call_soon([=]() { run_next_measurement(thread_id, cb, num_entries, current_entry); }); }, logger); }); } void Runnable::geoip_lookup(Callback<> cb) { // This is to ensure that when calling multiple times geoip_lookup we // always reset the probe_ip, probe_asn and probe_cc values. probe_ip = "127.0.0.1"; probe_asn = "AS0"; probe_cc = "ZZ"; auto save_ip = options.get("save_real_probe_ip", false); auto save_asn = options.get("save_real_probe_asn", true); auto save_cc = options.get("save_real_probe_cc", true); // This code block allows the caller to override probe variables if (save_ip and options.find("probe_ip") != options.end()) { probe_ip = options.at("probe_ip"); save_ip = false; // We already have it, don't look it up and save it } if (save_asn and options.find("probe_asn") != options.end()) { probe_asn = options.at("probe_asn"); save_asn = false; // Ditto } if (save_cc and options.find("probe_cc") != options.end()) { probe_cc = options.at("probe_cc"); save_cc = false; // Ditto } // No need to perform further lookups if we don't need to save anything if (not save_ip and not save_asn and not save_cc) { logger->warn("Not knowing user_ip means we cannot attempt to scrub it " "from the report"); cb(); return; } ip_lookup( [=](Error err, std::string ip) { if (err) { logger->warn("ip_lookup() failed: error code: %d", err.code); logger->warn("Not knowing user_ip means we cannot attempt " "to scrub it from the report"); cb(); return; } logger->info("Your public IP address: %s", ip.c_str()); if (save_ip) { logger->debug("saving user's real ip on user's request"); probe_ip = ip; } /* * XXX Passing down the stack the real probe IP to allow * specific tests to scrub entries. * * See also measurement-kit/measurement-kit#1110. */ options["real_probe_ip_"] = ip; auto country_path = options.get("geoip_country_path", std::string{}); if (save_cc and country_path != "") { try { probe_cc = *GeoipCache::thread_local_instance() ->resolve_country_code(country_path, ip, logger); } catch (const Error &err) { logger->warn("cannot lookup country code: %s", err.explain().c_str()); } if (probe_cc != "ZZ") { logger->info("Your country: %s", probe_cc.c_str()); } } else if (country_path == "") { logger->warn("geoip_country_path is not set"); } auto asn_path = options.get("geoip_asn_path", std::string{}); if (save_asn and asn_path != "") { try { probe_asn = *GeoipCache::thread_local_instance() ->resolve_asn(asn_path, ip, logger); } catch (const Error &err) { logger->warn("cannot lookup asn: %s", err.explain().c_str()); } if (probe_asn != "AS0") { logger->info("Your ISP identifier: %s", probe_asn.c_str()); } } else if (asn_path == "") { logger->warn("geoip_asn_path is not set"); } cb(); }, options, reactor, logger); } void Runnable::open_report(Callback callback) { /* * TODO: it would probably more robust to future changes to * set these values using a constructor. */ report.test_name = test_name; report.test_version = test_version; report.test_start_time = test_start_time; report.options = options; report.probe_ip = probe_ip; report.probe_cc = probe_cc; report.probe_asn = probe_asn; if (output_filepath == "") { output_filepath = generate_output_filepath(); } if (!options.get("no_file_report", false)) { report.add_reporter(FileReporter::make(output_filepath)); } if (!options.get("no_collector", false)) { report.add_reporter(OoniReporter::make(options, reactor, logger)); } report.open(callback); } std::string Runnable::generate_output_filepath() { int idx = 0; std::stringstream filename; while (true) { filename.str(""); filename.clear(); char timestamp[100]; strftime(timestamp, sizeof(timestamp), "%FT%H%M%SZ", &test_start_time); filename << "report-" << test_name << "-"; filename << timestamp << "-" << idx << ".njson"; std::ifstream output_file(filename.str().c_str()); // If a file called this way already exists we increment the counter if (output_file.good()) { output_file.close(); idx++; continue; } break; } return filename.str(); } void Runnable::query_bouncer(Callback cb) { if (!use_bouncer) { logger->info("skipping bouncer"); cb(NoError()); return; } auto bouncer = options.get("bouncer_base_url", ooni::bouncer::production_bouncer_url()); logger->info("Contacting bouncer: %s", bouncer.c_str()); ooni::bouncer::post_net_tests( bouncer, test_name, test_version, test_helpers_bouncer_names(), [=](Error error, Var reply) { if (error) { cb(error); return; } assert(!!reply); if (options.find("collector_base_url") == options.end()) { auto maybe_collector = reply->get_collector_alternate("https"); if (!maybe_collector) { logger->warn("no collector found"); cb(maybe_collector.as_error()); return; } options["collector_base_url"] = *maybe_collector; logger->info("Using discovered collector: %s", maybe_collector->c_str()); } for (auto th: test_helpers_data) { auto maybe_helper = reply->get_test_helper_alternate( th.first, "https" ); if (!maybe_helper) { maybe_helper = reply->get_test_helper(th.first); if (!maybe_helper) { logger->warn("Cannot find alternate or normal helper"); continue; } } logger->info("Bouncer discovered helper for %s: %s", th.first.c_str(), maybe_helper->c_str()); if (options.find(th.second) != options.end()) { continue; } logger->info("Using discovered helper as '%s'", th.second.c_str()); options[th.second] = *maybe_helper; } cb(NoError()); }, options, reactor, logger); } void Runnable::begin(Callback cb) { if (begin_cb) { begin_cb(); } mk::utc_time_now(&test_start_time); beginning = mk::time_now(); query_bouncer([=](Error error) { if (error) { cb(error); return; } mk::dump_settings(options, "runnable", logger); geoip_lookup([=]() { resolver_lookup( [=](Error error, std::string resolver_ip_) { logger->progress(0.05, "geoip lookup"); if (!error) { resolver_ip = resolver_ip_; } else { logger->debug("failed to lookup resolver ip"); } open_report([=](Error error) { if (error) { logger->warn("Cannot open report: %s", error.explain().c_str()); // FALLTHROUGH } logger->progress(0.1, "open report"); if (error and not options.get("ignore_open_report_error", true)) { cb(error); return; } logger->set_progress_offset(0.1); logger->set_progress_scale(0.8); error = process_input_filepaths(inputs, needs_input, input_filepaths, probe_cc, options, logger, nullptr, nullptr); if (error) { cb(error); return; } size_t num_entries = inputs.size(); // Run `parallelism` measurements in parallel Var current_entry(new size_t(0)); mk::parallel(mk::fmap>( mk::range( options.get("parallelism", 3)), [=](size_t thread_id) { return [=](Callback cb) { run_next_measurement( thread_id, cb, num_entries, current_entry); }; }), cb); }); }, options, reactor, logger); }); }); } void Runnable::end(Callback cb) { for (auto fn : end_cbs) { try { fn(); } catch (const std::exception &) { /* Suppress */ ; } } logger->set_progress_offset(0.0); logger->set_progress_scale(1.0); logger->progress(0.95, "ending the test"); report.close([=](Error err) { logger->progress(1.00, "test complete"); cb(err); }); } std::list Runnable::test_helpers_option_names() { std::list values; for (auto &kv : test_helpers_data) { values.push_back(kv.second); } return values; } std::list Runnable::test_helpers_bouncer_names() { std::list values; for (auto &kv : test_helpers_data) { values.push_back(kv.first); } return values; } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/runner.cpp000066400000000000000000000024671315356162600252120ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/nettests/runnable.hpp" #include "private/nettests/runner.hpp" #include #include #include #include #include namespace mk { namespace nettests { void Runner::start_test(Var test, Callback> fn) { // Note: here we MUST force the runnable's reactor to be our reactor // otherwise we cannot run the specified test... assert(not test->reactor); test->reactor = impl_.reactor(); impl_.start(std::to_string((unsigned long long)test.get()), test->logger, [test](Callback &&cb) { test->begin([=](Error) { // TODO: do not ignore the error test->end([=](Error) { // TODO: do not ignore the error cb(NoError()); }); }); }, [fn, test](const Error && /*error*/) { fn(test); }); } void Runner::stop() { impl_.stop(); } bool Runner::empty() { return impl_.active() == 0; } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/tcp_connect.cpp000066400000000000000000000014131315356162600261660ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/nettests/runnable.hpp" #include #include namespace mk { namespace nettests { TcpConnectTest::TcpConnectTest() : BaseTest() { runnable.reset(new TcpConnectRunnable); runnable->test_name = "tcp_connect"; runnable->test_version = "0.1.0"; runnable->needs_input = true; } void TcpConnectRunnable::main(std::string input, Settings options, Callback> cb) { ooni::tcp_connect(input, options, cb, reactor, logger); } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/utils.cpp000066400000000000000000000015241315356162600250320ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/nettests/utils_impl.hpp" namespace mk { namespace nettests { Error process_input_filepaths(std::deque &input, const bool &needs_input, const std::list &input_filepaths, const std::string &probe_cc, const Settings &options, Var logger, std::function on_open_error, std::function on_io_error) { return process_input_filepaths_impl(input, needs_input, input_filepaths, probe_cc, options, logger, on_open_error, on_io_error); } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/nettests/web_connectivity.cpp000066400000000000000000000033331315356162600272450ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/nettests/runnable.hpp" #include #include namespace mk { namespace nettests { WebConnectivityTest::WebConnectivityTest() : BaseTest() { runnable.reset(new WebConnectivityRunnable); runnable->test_name = "web_connectivity"; runnable->test_version = "0.0.1"; runnable->needs_input = true; runnable->test_helpers_data = {{"web-connectivity", "backend"}}; } void WebConnectivityRunnable::main(std::string input, Settings options, Callback> cb) { ooni::web_connectivity(input, options, cb, reactor, logger); } void WebConnectivityRunnable::fixup_entry(report::Entry &entry) { try { auto backend = entry["test_helpers"]["backend"].get(); if (mk::startswith(backend, "https://")) { entry["test_helpers"]["backend"] = {{ "address", backend }, { "type", "https" }}; } else { /* TODO: Here we should deal with this case. Or, even better, we should probably enhance the model such that the backend isn't a string but a more structured object. This will probably happen when we finish the cloudfronted code. */ logger->warn("We are sending a string-only backend entry."); } } catch (const std::exception &exc) { logger->warn("Cannot fixup entry: %s", exc.what()); } } } // namespace nettests } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/neubot/000077500000000000000000000000001315356162600226075ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/neubot/dash.cpp000066400000000000000000000022561315356162600242370ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/neubot/dash_impl.hpp" namespace mk { namespace neubot { namespace dash { const std::vector &dash_rates() { static std::vector DASH_RATES{ {100, 150, 200, 250, 300, 400, 500, 700, 900, 1200, 1500, 2000, 2500, 3000, 4000, 5000, 6000, 7000, 10000, 20000, 30000, 40000, 50000}}; return DASH_RATES; } void run(std::string measurement_server_hostname, std::string auth_token, std::string real_address, Var entry, Settings settings, Var reactor, Var logger, Callback callback) { run_impl(measurement_server_hostname, auth_token, real_address, entry, settings, reactor, logger, callback); } void negotiate(Var entry, Settings settings, Var reactor, Var logger, Callback callback) { negotiate_impl(entry, settings, reactor, logger, callback); } } // namespace dash } // namespace neubot } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ooni/000077500000000000000000000000001315356162600222575ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/ooni/bouncer.cpp000066400000000000000000000061501315356162600244220ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ooni/bouncer_impl.hpp" namespace mk { namespace ooni { ErrorOr> BouncerReply::create(std::string data, Var logger) { return bouncer::create_impl(data, logger); } nlohmann::json BouncerReply::get_base() { // Note: this method can throw exceptions return response["net-tests"][0]; } ErrorOr BouncerReply::get_collector() { try { return get_base()["collector"].get(); } catch (const std::exception &) { /* FALLTHROUGH */; } return BouncerValueNotFoundError(); } ErrorOr BouncerReply::get_collector_alternate(std::string type) { try { auto collectors = get_base()["collector-alternate"]; for (auto collector : collectors) { if (collector["type"] == type) { return collector["address"].get(); } } } catch (const std::exception &) { /* FALLTHROUGH */; } return BouncerValueNotFoundError(); } ErrorOr BouncerReply::get_name() { try { return get_base()["name"].get(); } catch (const std::exception &) { /* FALLTHROUGH */; } return BouncerValueNotFoundError(); } ErrorOr BouncerReply::get_test_helper(std::string name) { try { return get_base()["test-helpers"][name].get(); } catch (const std::exception &) { /* FALLTHROUGH */; } return BouncerValueNotFoundError(); } ErrorOr BouncerReply::get_test_helper_alternate(std::string name, std::string type) { try { auto collectors = get_base()["test-helpers-alternate"][name]; for (auto collector : collectors) { if (collector["type"] == type) { return collector["address"].get(); } } } catch (const std::exception &) { /* FALLTHROUGH */; } return BouncerValueNotFoundError(); } ErrorOr BouncerReply::get_version() { try { return get_base()["version"].get(); } catch (const std::exception &) { /* FALLTHROUGH */; } return BouncerValueNotFoundError(); } namespace bouncer { void post_net_tests(std::string base_bouncer_url, std::string test_name, std::string test_version, std::list helpers, Callback> cb, Settings settings, Var reactor, Var logger) { post_net_tests_impl(base_bouncer_url, test_name, test_version, helpers, cb, settings, reactor, logger); } std::string production_bouncer_url() { return MK_OONI_PRODUCTION_BOUNCER_URL; } std::string testing_bouncer_url() { return MK_OONI_TESTING_BOUNCER_URL; } } // namespace bouncer } // namespace ooni } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ooni/collector_client.cpp000066400000000000000000000123521315356162600263120ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ooni/collector_client_impl.hpp" namespace mk { namespace ooni { namespace collector { using namespace mk::http; using namespace mk::net; using namespace mk::report; static const std::regex re_name{"^[A-Za-z0-9._-]+$"}; static const std::regex re_version{ "^[0-9]+.[0-9]+(.[0-9]+(-[A-Za-z0-9._-]+)?)?$"}; static std::map mandatory_re{ {"software_name", re_name}, {"software_version", re_version}, {"probe_asn", std::regex{"^AS[0-9]+$"}}, {"probe_cc", std::regex{"^[A-Z]{2}$"}}, {"test_name", re_name}, {"test_version", re_version}, {"data_format_version", re_version}, {"test_start_time", std::regex{"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$"}}, }; Error valid_entry(Entry entry) { // TODO: also validate the optional values for (auto pair : mandatory_re) { ErrorOr s = entry[pair.first]; if (!s) { return MissingMandatoryKeyError(s.as_error()); } if (!std::regex_match(*s, pair.second)) { return InvalidMandatoryValueError(pair.first); } } return NoError(); } void post(Var transport, std::string url_extra, std::string body, Callback callback, Settings conf, Var reactor, Var logger) { post_impl(transport, url_extra, body, callback, conf, reactor, logger); } void connect(Settings settings, Callback> callback, Var reactor, Var logger) { connect_impl(settings, callback, reactor, logger); } void create_report(Var transport, Entry entry, Callback callback, Settings settings, Var reactor, Var logger) { create_report_impl(transport, entry, callback, settings, reactor, logger); } void connect_and_create_report(report::Entry entry, Callback callback, Settings settings, Var reactor, Var logger) { connect_and_create_report_impl(entry, callback, settings, reactor, logger); } void update_report(Var transport, std::string report_id, Entry entry, Callback callback, Settings settings, Var reactor, Var logger) { update_report_impl(transport, report_id, entry, callback, settings, reactor, logger); } void connect_and_update_report(std::string report_id, report::Entry entry, Callback callback, Settings settings, Var reactor, Var logger) { connect_and_update_report_impl(report_id, entry, callback, settings, reactor, logger); } void close_report(Var transport, std::string report_id, Callback callback, Settings settings, Var reactor, Var logger) { close_report_impl(transport, report_id, callback, settings, reactor, logger); } void connect_and_close_report(std::string report_id, Callback callback, Settings settings, Var reactor, Var logger) { connect_and_close_report_impl(report_id, callback, settings, reactor, logger); } ErrorOr get_next_entry(Var file, Var logger) { std::string line; std::getline(*file, line); if (file->eof()) { logger->info("End of file found"); return FileEofError(); } if (!file->good()) { logger->warn("I/O error reading file"); return FileIoError(); } logger->debug("Read line from report: %s", line.c_str()); Entry entry; // Works because we are using nlohmann::json::json() as Entry::Entry() auto e = json_parse_and_process(line, [&](auto j) { entry = j; }); if (e != NoError()) { return e; } return entry; } void submit_report(std::string filepath, std::string collector_base_url, Callback callback, Settings conf, Var reactor, Var logger) { submit_report_impl(filepath, collector_base_url, "", callback, conf, reactor, logger); } void submit_report(std::string filepath, std::string collector_base_url, std::string collector_front_domain, Callback callback, Settings conf, Var reactor, Var logger) { submit_report_impl(filepath, collector_base_url, collector_front_domain, callback, conf, reactor, logger); } std::string production_collector_url() { return MK_OONI_PRODUCTION_COLLECTOR_URL; } std::string testing_collector_url() { return MK_OONI_TESTING_COLLECTOR_URL; } } // namespace collector } // namespace mk } // namespace ooni measurement-kit-0.7.1/src/libmeasurement_kit/ooni/dns_injection.cpp000066400000000000000000000025401315356162600256120ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include namespace mk { namespace ooni { using namespace mk::report; void dns_injection(std::string input, Settings options, Callback> cb, Var reactor, Var logger) { // Use libevent DNS engine for which we can force a specific nameserver. options["dns/engine"] = "libevent"; // Force timeout according to dns_injection specification. options["dns/timeout"] = 3.0; Var entry(new Entry); (*entry)["injected"] = nullptr; templates::dns_query(entry, "A", "IN", input, options["backend"], [=](Error err, Var message) { logger->debug("dns_injection: got response"); if (!err && message->error_code == DNS_ERR_NONE) { (*entry)["injected"] = true; } else { (*entry)["injected"] = false; } cb(entry); }, options, reactor, logger); } } // namespace ooni } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ooni/http_header_field_manipulation.cpp000066400000000000000000000115031315356162600311750ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/common/utils.hpp" #include "private/ooni/constants.hpp" #include "private/ooni/http_header_field_manipulation.hpp" #include "private/ooni/utils.hpp" #include namespace mk { namespace ooni { using namespace mk::report; void compare_headers_response(http::Headers headers, Var response, Var entry, Var logger) { if (response->body.empty()) { logger->warn("empty response body"); (*entry)["tampering"]["total"] = true; (*entry)["tampering"]["request_line_capitalization"] = true; return; } nlohmann::json resp; try { resp = nlohmann::json::parse(response->body); } catch (const std::invalid_argument &) { logger->warn("response body not valid JSON"); (*entry)["tampering"]["total"] = true; (*entry)["tampering"]["request_line_capitalization"] = true; return; } (*entry)["tampering"]["total"] = false; if (resp.find("request_line") == resp.end()) { (*entry)["tampering"]["request_line_capitalization"] = true; } else if (resp["request_line"] != "GET / HTTP/1.1") { (*entry)["tampering"]["request_line_capitalization"] = true; } else { (*entry)["tampering"]["request_line_capitalization"] = false; } // ooni-probe behavior to report header keys in the request or response // but not both. (case-sensitive, and ignoring values) nlohmann::json resp_headers = resp["headers_dict"]; std::set req_keys, resp_keys, diff; for (auto it = headers.begin(); it != headers.end(); ++it) { req_keys.insert(it->first); logger->debug("ins %s in req_keys", it->first.c_str()); } for (auto it = resp_headers.begin(); it != resp_headers.end(); ++it) { resp_keys.insert(it.key()); logger->debug("ins %s in resp_keys", it.key().c_str()); } std::set_difference(req_keys.begin(), req_keys.end(), resp_keys.begin(), resp_keys.end(), std::inserter(diff, diff.begin())); std::set_difference(resp_keys.begin(), resp_keys.end(), req_keys.begin(), req_keys.end(), std::inserter(diff, diff.begin())); (*entry)["tampering"]["header_name_diff"] = diff; (*entry)["tampering"]["header_field_name"] = !diff.empty(); } void http_header_field_manipulation(std::string /*input*/, Settings options, Callback> callback, Var reactor, Var logger) { Var entry(new Entry); (*entry)["tampering"] = Entry::object(); (*entry)["tampering"]["total"] = nullptr; (*entry)["tampering"]["request_line_capitalization"] = nullptr; (*entry)["tampering"]["header_name_diff"] = nullptr; (*entry)["tampering"]["header_field_name"] = nullptr; (*entry)["failure"] = nullptr; options["http/url"] = options["backend"]; std::string body = ""; // spec says this is always a GET, so no body std::string random_host = random_str(15) + ".com"; std::string random_ua = random_choice(constants::COMMON_USER_AGENTS); http::Headers headers = { {randomly_capitalize("host"), random_host}, {randomly_capitalize("user-agent"), random_ua}, {randomly_capitalize("accept"), "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}, {randomly_capitalize("accept-encoding"), "gzip,deflate,sdch"}, {randomly_capitalize("accept-language"), "en-US,en;q=0.8"}, {randomly_capitalize("accept-charset"), "ISO-8859-1,utf-8;q=0.7,*;q=0.3"}}; templates::http_request( entry, options, headers, body, [=](Error err, Var response) { if (err) { logger->debug( "http_header_field_manipulation: http-request error: %s", err.explain().c_str()); (*entry)["failure"] = err.as_ooni_error(); } if (!response) { logger->warn("null response"); } else { try { compare_headers_response(headers, response, entry, logger); } catch (const std::exception &exc) { (*entry)["failure"] = exc.what(); logger->warn("exception in " "compare_headers_response(): %s", exc.what()); } } callback(entry); }, reactor, logger); } } // namespace ooni } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ooni/http_invalid_request_line.cpp000066400000000000000000000134011315356162600302260ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/common/utils.hpp" #include namespace mk { namespace ooni { static const int timeout = 5; static void send_receive_invalid_request_line(net::Endpoint endpoint, std::string request_line, Callback> cb, Settings settings, Var reactor, Var logger) { settings["host"] = endpoint.hostname; settings["port"] = endpoint.port; Var entry{new report::Entry{ {"tampering", nullptr}, {"received", nullptr}, {"sent", nullptr}, {"failure", nullptr} }}; templates::tcp_connect(settings, [=](Error err, Var txp) { if (err) { logger->warn("http_invalid_request_line: error connecting"); (*entry)["failure"] = err.as_ooni_error(); cb(entry); return; } Var received_data(new std::string); txp->on_data([=](net::Buffer data) { logger->debug("http_invalid_request_line: on_data: %s", data.peek().c_str()); *received_data += data.read(); }); txp->write(request_line); // We assume to have received all the data after a timeout // of 5 seconds. reactor->call_later(timeout, [=]() { if (*received_data != request_line) { logger->warn("Tampering detected: '%s' != '%s'", received_data->c_str(), request_line.c_str()); (*entry)["tampering"] = true; } else { logger->debug("Tampering not detected: '%s' == '%s'", received_data->c_str(), request_line.c_str()); (*entry)["tampering"] = false; } (*entry)["sent"] = request_line; (*entry)["received"] = *received_data; txp->close([=]() { cb(entry); }); }); }, reactor, logger); } void http_invalid_request_line(Settings options, Callback> cb, Var reactor, Var logger) { Var entry(new report::Entry); (*entry)["tampering"] = nullptr; (*entry)["received"] = report::Entry::array(); (*entry)["sent"] = report::Entry::array(); (*entry)["tampering_list"] = report::Entry::array(); (*entry)["failure_list"] = report::Entry::array(); Var tests_run(new int(0)); ErrorOr endpoint = mk::net::parse_endpoint(options["backend"], 80); if (!endpoint) { logger->warn("Invalid helper endpoint: %s (backend = '%s')", endpoint.as_error().explain().c_str(), options["backend"].c_str()); (*entry)["failure"] = endpoint.as_error().as_ooni_error(); cb(entry); return; } logger->info("Using helper: %s", options["backend"].c_str()); auto handle_response = [=](Var inner) { *tests_run += 1; (*entry)["tampering_list"].push_back((*inner)["tampering"]); (*entry)["received"].push_back((*inner)["received"]); (*entry)["sent"].push_back((*inner)["sent"]); (*entry)["failure_list"].push_back((*inner)["failure"]); if (*tests_run == 4) { for (auto &x : (*entry)["failure_list"]) { if (x != nullptr) { (*entry)["failure"] = ParallelOperationError().as_ooni_error(); break; } } for (auto &x : (*entry)["tampering_list"]) { if (x != nullptr) { (*entry)["tampering"] = x; if ((*entry)["tampering"] == true) { break; } } } cb(entry); } }; // test_random_invalid_method // randomSTR(4) + " / HTTP/1.1\n\r" std::string test_random_invalid_method(mk::random_str_uppercase(4)); test_random_invalid_method += " / HTTP/1.1\n\r"; send_receive_invalid_request_line( *endpoint, test_random_invalid_method, handle_response, options, reactor, logger); // test_random_invalid_field_count // ' '.join(randomStr(5) for x in range(4)) + '\n\r' std::string test_random_invalid_field_count(mk::random_str_uppercase(5)); for (int i = 0; i < 3; i++) { test_random_invalid_field_count += " " + mk::random_str_uppercase(5); } test_random_invalid_field_count += "\n\r"; send_receive_invalid_request_line( *endpoint, test_random_invalid_field_count, handle_response, options, reactor, logger); // test_random_big_request_method // randomStr(1024) + ' / HTTP/1.1\n\r' std::string test_random_big_request_method(mk::random_str_uppercase(1024)); test_random_big_request_method += " / HTTP/1.1\n\r"; send_receive_invalid_request_line( *endpoint, test_random_big_request_method, handle_response, options, reactor, logger); // test_random_invalid_version_number // 'GET / HTTP/' + randomStr(3) std::string test_random_invalid_version_number("GET / HTTP/"); test_random_invalid_version_number += mk::random_str_uppercase(3); send_receive_invalid_request_line( *endpoint, test_random_invalid_version_number, handle_response, options, reactor, logger); } } // namespace ooni } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ooni/meek_fronted_requests.cpp000066400000000000000000000057351315356162600273720ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/common/utils.hpp" #include "private/ooni/constants.hpp" #include namespace mk { namespace ooni { using namespace mk::report; void meek_fronted_requests(std::string input, Settings options, Callback> callback, Var reactor, Var logger) { Var entry(new Entry); std::string expected_body, outer_host, inner_host; if (options["expected_body"].empty()) { expected_body = constants::MEEK_SERVER_RESPONSE; } else { expected_body = options["expected_body"]; } std::list outer_inner = split(input, ":"); if (outer_inner.size() != 2) { logger->warn("Couldn't split input: %s", input.c_str()); (*entry)["failure"] = ValueError().as_ooni_error(); callback(entry); return; } // XXX: We should make sure that we remove leading and trailing whitespaces outer_host = outer_inner.front(); inner_host = outer_inner.back(); // url parsing methods require a schema outer_host.insert(0, "https://"); inner_host.insert(0, "https://"); ErrorOr outer_url = mk::http::parse_url_noexcept(outer_host); ErrorOr inner_url = mk::http::parse_url_noexcept(inner_host); if (!outer_url || !inner_url) { logger->warn("Invalid url: %s or %s", outer_host.c_str(), inner_host.c_str()); (*entry)["failure"] = ValueError().as_ooni_error(); callback(entry); return; } options["http/url"] = "https://" + outer_url->address; http::Headers headers = { {"Host", inner_url->address} }; std::string body = ""; // spec says this is always a GET, so no body logger->debug("Connecting to outer host %s and requesting inner url %s.", outer_url->address.c_str(), inner_url->address.c_str()); templates::http_request(entry, options, headers, body, [=](Error err, Var response) { if (err) { logger->debug( "meek_fronted_requests: http-request error: %s", err.explain().c_str()); (*entry)["failure"] = err.as_ooni_error(); } if (!!response) { (*entry)["success"] = (response->body == expected_body); } callback(entry); }, reactor, logger); } } // namespace ooni } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ooni/orchestrate.cpp000066400000000000000000000172111315356162600253100ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include "private/ooni/orchestrate_impl.hpp" namespace mk { namespace ooni { namespace orchestrate { /* * URLs */ std::string production_registry_url() { return MK_OONI_PRODUCTION_PROTEUS_REGISTRY_URL; } std::string testing_registry_url() { return MK_OONI_TESTING_PROTEUS_REGISTRY_URL; } std::string production_events_url() { return MK_OONI_PRODUCTION_PROTEUS_EVENTS_URL; } std::string testing_events_url() { return MK_OONI_TESTING_PROTEUS_EVENTS_URL; } /* * Auth */ /*static*/ std::string Auth::make_password() { return mk::random_printable(64); } Error Auth::load(const std::string &filepath) noexcept { ErrorOr maybe_data = slurp(filepath); if (!maybe_data) { return maybe_data.as_error(); } return loads(*maybe_data); } Error Auth::loads(const std::string &s) noexcept { return json_parse_process_and_filter_errors(s, [&](auto json) { auth_token = json.at("auth_token"); expiry_time = json.at("expiry_time"); logged_in = json.at("logged_in"); username = json.at("username"); password = json.at("password"); }); } Error Auth::dump(const std::string &filepath) noexcept { return overwrite_file(filepath, dumps()); } std::string Auth::dumps() noexcept { auto json = nlohmann::json{{"auth_token", auth_token}, {"expiry_time", expiry_time}, {"logged_in", logged_in}, {"username", username}, {"password", password}}; return json.dump(4); } bool Auth::is_valid(Var logger) const noexcept { if (!logged_in) { logger->debug("orchestrator: not logged in"); return false; } if (auth_token.empty()) { logger->warn("orchestrator: auth_token is empty"); return false; } tm expiry_temp{}; logger->debug("orchestrator: expiry_time: '%s'", expiry_time.c_str()); Error error = parse_iso8601_utc(expiry_time, &expiry_temp); if (error) { logger->warn("orchestrator: cannot parse expiry_time"); return false; } auto expiry_time_s = std::mktime(&expiry_temp); if (expiry_time_s == (time_t)-1) { logger->warn("orchestrator: std::mktime() failed"); return false; } logger->debug("orchestrator: expiry_time_s: %llu", (unsigned long long)expiry_time_s); auto now_localtime = std::time(nullptr); if (now_localtime == (time_t)-1) { logger->warn("orchestrator: std::time() failed"); return false; } logger->debug("orchestrator: now_localtime: %llu", (unsigned long long)now_localtime); tm now_temp{}; if (gmtime_r(&now_localtime, &now_temp) == nullptr) { logger->warn("orchestrator: std::gmtime_r() failed"); return false; } auto now_utc = std::mktime(&now_temp); if (now_utc == (time_t)-1) { logger->warn("orchestrator: std::mktime() failed"); return false; } logger->debug("orchestrator: now_utc: %llu", (unsigned long long)now_utc); auto diff = difftime(expiry_time_s, now_utc); if (diff < 0) { logger->debug("orchestrator: the auth_token is expired"); return false; } return true; } /* * Registry database */ nlohmann::json ClientMetadata::as_json() const { nlohmann::json j; // Keep the following sorted to ease comparison with class definition if (!available_bandwidth.empty()) { j["available_bandwidth"] = available_bandwidth; } if (!device_token.empty()) { j["token"] = device_token; } if (!language.empty()) { j["language"] = language; } if (!network_type.empty()) { j["network_type"] = network_type; } j["platform"] = platform; j["probe_asn"] = probe_asn; j["probe_cc"] = probe_cc; if (!probe_family.empty()) { j["probe_family"] = probe_family; } j["software_name"] = software_name; j["software_version"] = software_version; if (!supported_tests.empty()) { j["supported_tests"] = supported_tests; } return j; } void Client::register_probe(std::string &&password, Callback &&cb) const { // Copy the data contained by this object so we completely detach the // destiny of `this` and of the callback. AsyncRunner::global()->start_("orchestrate::register_probe", logger, [ password = std::move(password), meta = *this, cb = std::move(cb) ](Continuation<> && done) mutable { do_register_probe( std::move(password), meta, AsyncRunner::global()->reactor(), [ done = std::move(done), cb = std::move(cb) ](Error && error, Auth && auth) mutable { done([ error = std::move(error), cb = std::move(cb), auth = std::move(auth) ]() mutable { cb(std::move(error), std::move(auth)); }); }); }); } void Client::find_location( Callback &&cb) const { // Copy the data contained by this object so we completely detach the // destiny of `this` and of the callback. AsyncRunner::global()->start_( "orchestrate::find_location", logger, [ meta = *this, cb = std::move(cb) ](Continuation<> && done) mutable { do_find_location(meta, AsyncRunner::global()->reactor(), [ cb = std::move(cb), done = std::move(done) ](Error && error, std::string && asn, std::string && cc) { done([ cb = std::move(cb), error = std::move(error), asn = std::move(asn), cc = std::move(cc) ]() mutable { cb(std::move(error), std::move(asn), std::move(cc)); }); }); }); } void Client::update(Auth &&auth, Callback &&cb) const { // Copy the data contained by this object so we completely detach the // destiny of `this` and of the callback. AsyncRunner::global()->start_("orchestrate::update", logger, [ meta = *this, cb = std::move(cb), auth = std::move(auth) ](Continuation<> && done) mutable { do_update(std::move(auth), meta, AsyncRunner::global()->reactor(), [ cb = std::move(cb), done = std::move(done) ]( Error && error, Auth && auth) mutable { done([ cb = std::move(cb), error = std::move(error), auth = std::move(auth) ]() mutable { cb(std::move(error), std::move(auth)); }); }); }); } void Client::list_tasks(Auth &&, Callback &&> && /*callback)*/) const { throw NotImplementedError(); } /* * Events database */ void Task::get( Auth &&, Callback && /*callback*/) const { throw NotImplementedError(); } void Task::accept(Auth &&, Callback && /*callback*/) const { throw NotImplementedError(); } void Task::reject(Auth &&, Callback && /*callback*/) const { throw NotImplementedError(); } void Task::done(Auth &&, Callback && /*callback*/) const { throw NotImplementedError(); } } // namespace orchestrate } // namespace ooni } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ooni/resources.cpp000066400000000000000000000030321315356162600247730ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ooni/resources_impl.hpp" namespace mk { namespace ooni { namespace resources { void get_latest_release(Callback cb, Settings settings, Var reactor, Var logger) { get_latest_release_impl(cb, settings, reactor, logger); } void get_manifest_as_json( std::string latest, Callback cb, Settings settings, Var reactor, Var logger) { get_manifest_as_json_impl(latest, cb, settings, reactor, logger); } void get_resources_for_country(std::string version, nlohmann::json manifest, std::string country, Callback callback, Settings settings, Var reactor, Var logger) { get_resources_for_country_impl(version, manifest, country, callback, settings, reactor, logger); } void get_resources(std::string latest, std::string country, Callback callback, Settings settings, Var reactor, Var logger) { get_resources_impl(latest, country, callback, settings, reactor, logger); } } // namespace resources } // namespace mk } // namespace ooni measurement-kit-0.7.1/src/libmeasurement_kit/ooni/tcp_connect.cpp000066400000000000000000000026021315356162600252620ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include namespace mk { namespace ooni { using namespace mk::report; void tcp_connect(std::string input, Settings options, Callback> callback, Var reactor, Var logger) { Var entry(new Entry); (*entry)["connection"] = nullptr; // Note: unlike ooni-probe, here we also accept endpoints where the port // is not specified, defaulting to 80 in such case. ErrorOr maybe_epnt = net::parse_endpoint(input, 80); if (!maybe_epnt) { (*entry)["connection"] = maybe_epnt.as_error().as_ooni_error(); callback(entry); return; } options["host"] = maybe_epnt->hostname; options["port"] = maybe_epnt->port; templates::tcp_connect(options, [=](Error err, Var txp) { logger->debug("tcp_connect: Got response to TCP connect test"); if (err) { (*entry)["connection"] = err.as_ooni_error(); callback(entry); return; } txp->close([=]() { (*entry)["connection"] = "success"; callback(entry); }); }, reactor, logger); } } // namespace ooni } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ooni/templates.cpp000066400000000000000000000175141315356162600247710ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include #include "private/ooni/utils.hpp" namespace mk { namespace ooni { namespace templates { using namespace mk::report; void dns_query(Var entry, dns::QueryType query_type, dns::QueryClass query_class, std::string query_name, std::string nameserver, Callback> cb, Settings options, Var reactor, Var logger) { std::string engine = options.get("dns/engine", std::string{"system"}); bool not_system_engine = engine != "system"; uint16_t resolver_port = 0; std::string resolver_hostname; Var query_entry{new report::Entry}; if (not_system_engine) { ErrorOr maybe_epnt = net::parse_endpoint(nameserver, 53); if (!maybe_epnt) { reactor->call_soon([=]() { cb(maybe_epnt.as_error(), nullptr); }); return; } resolver_port = maybe_epnt->port; resolver_hostname = maybe_epnt->hostname; options["dns/nameserver"] = resolver_hostname; options["dns/port"] = resolver_port; options["dns/attempts"] = 1; (*query_entry)["resolver_hostname"] = resolver_hostname; (*query_entry)["resolver_port"] = resolver_port; } else { if (nameserver != "") { logger->warn("Explicit nameserver ignored with 'system' DNS engine"); } // ooniprobe sets them to null when they are not available (*query_entry)["resolver_hostname"] = nullptr; (*query_entry)["resolver_port"] = nullptr; } dns::query(query_class, query_type, query_name, [=](Error error, Var message) { logger->debug("dns_test: got response!"); (*query_entry)["engine"] = engine; (*query_entry)["failure"] = nullptr; (*query_entry)["answers"] = Entry::array(); if (query_type == dns::MK_DNS_TYPE_A) { (*query_entry)["query_type"] = "A"; (*query_entry)["hostname"] = query_name; } if (!error) { for (auto answer : message->answers) { if (query_type == dns::MK_DNS_TYPE_A) { (*query_entry)["answers"].push_back( {{"ttl", answer.ttl}, {"ipv4", answer.ipv4}, {"answer_type", "A"}}); } } } else { (*query_entry)["failure"] = error.as_ooni_error(); } // TODO add support for bytes received // (*query_entry)["bytes"] = response.get_bytes(); (*entry)["queries"].push_back(*query_entry); logger->debug("dns_test: callbacking"); cb(error, message); logger->debug("dns_test: callback called"); }, options, reactor); } void http_request(Var entry, Settings settings, http::Headers headers, std::string body, Callback> cb, Var reactor, Var logger) { (*entry)["agent"] = "agent"; (*entry)["socksproxy"] = nullptr; // Include the name of the agent, like ooni-probe does ErrorOr max_redirects = settings.get("http/max_redirects", 0); if (!!max_redirects && *max_redirects > 0) { (*entry)["agent"] = "redirect"; } if (settings.find("http/method") == settings.end()) { settings["http/method"] = "GET"; } /* * XXX probe ip passed down the stack to allow us to scrub it from the * entry; see issue #1110 for plans to make this better. */ std::string probe_ip = settings.get("real_probe_ip_", std::string{}); auto redact = [=](std::string s) { if (probe_ip != "" && !settings.get("save_real_probe_ip", false)) { s = mk::ooni::scrub(s, probe_ip); } return s; }; http::request( settings, headers, body, [=](Error error, Var response) { auto dump = [&](Var response) { Entry rr; if (!!error) { rr["failure"] = error.as_ooni_error(); } else { rr["failure"] = nullptr; } /* * Note: we should not assume that, if the response is set, * then also the request will be set. The response should * be allocated in all cases because that's what is returned * by the callback, while the request may not be allocated * when we fail before filling a response (i.e. when we * cannot connect). For sure, the HTTP code should be made * less unpredictable, but that's not a good excuse for not * performing sanity checks also at this level. * * See . */ if (!!response && !!response->request) { /* * Note: `probe_ip` comes from an external service, hence * we MUST call `represent_string` _after_ `redact()`. */ for (auto pair : response->headers) { rr["response"]["headers"][pair.first] = represent_string(redact(pair.second)); } rr["response"]["body"] = represent_string(redact(response->body)); rr["response"]["response_line"] = represent_string(redact(response->response_line)); rr["response"]["code"] = response->status_code; auto request = response->request; // Note: we checked above that we can deref `request` for (auto pair : request->headers) { rr["request"]["headers"][pair.first] = represent_string(redact(pair.second)); } rr["request"]["body"] = represent_string(redact(request->body)); rr["request"]["url"] = request->url.str(); rr["request"]["method"] = request->method; rr["request"]["tor"] = {{ "exit_ip", nullptr }, { "exit_name", nullptr }, { "is_tor", false }}; } return rr; }; if (!!response) { for (Var x = response; !!x; x = x->previous) { (*entry)["requests"].push_back(dump(x)); } } else { (*entry)["requests"].push_back(dump(response)); } cb(error, response); }, reactor, logger); } void tcp_connect(Settings options, Callback> cb, Var reactor, Var logger) { ErrorOr port = options["port"].as_noexcept(); if (!port) { cb(port.as_error(), nullptr); return; } if (options["host"] == "") { cb(MissingRequiredHostError(), nullptr); return; } net::connect(options["host"], *port, cb, options, reactor, logger); } } // namespace templates } // namespace ooni } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ooni/utils.cpp000066400000000000000000000122621315356162600241260ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/ooni/utils_impl.hpp" #include "private/common/utils.hpp" namespace mk { namespace ooni { void ip_lookup(Callback callback, Settings settings, Var reactor, Var logger) { ip_lookup_impl(callback, settings, reactor, logger); } void resolver_lookup(Callback callback, Settings settings, Var reactor, Var logger) { resolver_lookup_impl(callback, settings, reactor, logger); } /* static */ Var GeoipCache::thread_local_instance() { static thread_local Var singleton(new GeoipCache); return singleton; } Var GeoipCache::get(std::string path, bool &did_open) { if (instances.find(path) != instances.end()) { did_open = false; return instances.at(path); } did_open = true; if (instances.size() > max_size) { instances.erase(std::prev(instances.end())); } instances[path] = Var(new GeoipDatabase(path)); return instances[path]; } ErrorOr GeoipDatabase::with_open_database_do( std::function()> action, Var logger) { if (!db) { db.reset(GeoIP_open(path.c_str(), GEOIP_MEMORY_CACHE), [](GeoIP *pointer) { if (pointer) { GeoIP_delete(pointer); } }); if (!db) { logger->warn("cannot open geoip database: %s", path.c_str()); return GeoipDatabaseOpenError(); } // FALLTHROUGH } return action(); } ErrorOr GeoipDatabase::resolve_country_code( std::string ip, Var logger) { return with_open_database_do([=]() -> ErrorOr { GeoIPLookup gl; memset(&gl, 0, sizeof(gl)); const char *result; result = GeoIP_country_code_by_name_gl(db.get(), ip.c_str(), &gl); if (result == nullptr) { return GeoipCountryCodeLookupError(); } std::string country_code = result; return country_code; }, logger); } ErrorOr GeoipDatabase::resolve_country_name( std::string ip, Var logger) { return with_open_database_do([=]() -> ErrorOr { GeoIPLookup gl; memset(&gl, 0, sizeof(gl)); const char *result; result = GeoIP_country_name_by_name_gl(db.get(), ip.c_str(), &gl); if (result == nullptr) { return GeoipCountryNameLookupError(); } std::string country_name = result; return country_name; }, logger); } ErrorOr GeoipDatabase::resolve_city_name( std::string ip, Var logger) { return with_open_database_do([=]() -> ErrorOr { GeoIPRecord *gir = GeoIP_record_by_name(db.get(), ip.c_str()); if (gir == nullptr) { return GeoipCityLookupError(); } std::string result; if (gir->city != nullptr) { result = gir->city; } GeoIPRecord_delete(gir); return result; }, logger); } ErrorOr GeoipDatabase::resolve_asn(std::string ip, Var logger) { return with_open_database_do([=]() -> ErrorOr { GeoIPLookup gl; memset(&gl, 0, sizeof(gl)); char *res = GeoIP_name_by_name_gl(db.get(), ip.c_str(), &gl); if (res == nullptr) { return GeoipAsnLookupError(); } std::string asn = res; asn = split(asn).front(); // We only want ASXX free(res); return asn; }, logger); } std::string extract_html_title(std::string body) { std::regex TITLE_REGEXP("([\\s\\S]*?)", std::regex::icase); std::smatch match; if (std::regex_search(body, match, TITLE_REGEXP) && match.size() > 1) { return match.str(1); } return ""; } bool is_private_ipv4_addr(const std::string &ipv4_addr) { std::regex IPV4_PRIV_ADDR( "(^127\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})|" "(^192\\.168\\.[0-9]{1,3}\\.[0-9]{1,3})|" "(^10\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})|" "(^172\\.1[6-9]\\.[0-9]{1,3}\\.[0-9]{1,3})|" "(^172\\.2[0-9]\\.[0-9]{1,3}\\.[0-9]{1,3})|" "(^172\\.3[0-1]\\.[0-9]{1,3}\\.[0-9]{1,3})|" "localhost" ); std::smatch match; if (std::regex_search(ipv4_addr, match, IPV4_PRIV_ADDR) && match.size() > 1) { return true; } return false; } report::Entry represent_string(const std::string &s) { Error error = is_valid_utf8_string(s); if (error != NoError()) { return report::Entry{{"format", "base64"}, {"data", base64_encode(s)}}; } return s; } std::string scrub(std::string s, std::string real_probe_ip) { size_t p = 0; while ((p = s.find(real_probe_ip, p)) != std::string::npos) { s = s.replace(p, real_probe_ip.size(), "[REDACTED]"); } return s; } } // namespace ooni } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/ooni/web_connectivity.cpp000066400000000000000000000611531315356162600263440ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/common/utils.hpp" #include "private/ooni/constants.hpp" #include "private/ooni/utils.hpp" #include #include #include #define BODY_PROPORTION_FACTOR 0.7 namespace mk { namespace ooni { using namespace mk::report; typedef std::vector> SocketList; static void compare_http_requests(Var entry, Var response, Entry control, Var logger) { // The response may be null if HTTP fails due to network errors if (!response) { logger->warn("skip comparison due to null response"); return; } std::string exp_body = response->body; int exp_length = exp_body.size(); int ctrl_length = control["body_length"]; // Verifiy if the body lengths match a certain proportion factor. float body_proportion = 0; if (ctrl_length == exp_length) { body_proportion = 1; } else if (ctrl_length == 0 || exp_length == 0) { body_proportion = 0; } else { body_proportion = (float)std::min(ctrl_length, exp_length) / (float)std::max(ctrl_length, exp_length); } logger->debug("web_connectivity: body proportion %f", body_proportion); if (body_proportion > BODY_PROPORTION_FACTOR) { (*entry)["body_length_match"] = true; } else { (*entry)["body_length_match"] = false; } (*entry)["body_proportion"] = body_proportion; // Verify that the status codes match logger->debug("web_connectivity: comparing status codes"); // We ignore status code matching when the server returns an error in the // control. (*entry)["status_code_match"] = true; if (((int)control["status_code"]) / 100 != 5) { if (((unsigned)control["status_code"]) == response->status_code) { (*entry)["status_code_match"] = true; } else { (*entry)["status_code_match"] = false; } } // Check if the headers match logger->debug("web_connectivity: checking headers"); std::set lowercase_ctrl_headers; std::set lowercase_exp_headers; for (Entry::iterator it = control["headers"].begin(); it != control["headers"].end(); ++it) { std::string lower_header(it.key()); std::transform(lower_header.begin(), lower_header.end(), lower_header.begin(), [](unsigned char c) { return std::tolower(c); }); lowercase_ctrl_headers.insert(lower_header); } for (auto it = response->headers.begin(); it != response->headers.end(); ++it) { std::string lower_header(it->first); std::transform(lower_header.begin(), lower_header.end(), lower_header.begin(), [](unsigned char c) { return std::tolower(c); }); lowercase_exp_headers.insert(lower_header); } if (lowercase_ctrl_headers == lowercase_exp_headers) { (*entry)["headers_match"] = true; } else { std::set intersection; std::set uncommon_intersection; std::set_intersection( lowercase_exp_headers.begin(), lowercase_exp_headers.end(), lowercase_ctrl_headers.begin(), lowercase_ctrl_headers.end(), std::inserter(intersection, intersection.begin())); std::set_difference(intersection.begin(), intersection.end(), constants::COMMON_SERVER_HEADERS.begin(), constants::COMMON_SERVER_HEADERS.end(), std::inserter(uncommon_intersection, uncommon_intersection.begin())); if (uncommon_intersection.size() > 0) { (*entry)["headers_match"] = true; } else { (*entry)["headers_match"] = false; } } // Check if the HTML titles match logger->debug("web_connectivity: checking HTML titles"); std::string experiment_title = extract_html_title(response->body); std::vector exp_title_words; std::vector ctrl_title_words; exp_title_words = split>(experiment_title, " "); ctrl_title_words = split>(control["title"], " "); size_t idx = 0; (*entry)["title_match"] = (experiment_title == control["title"]); for (auto exp_word : exp_title_words) { if (exp_word.length() < 5) { idx++; continue; } if (idx >= ctrl_title_words.size()) { break; } (*entry)["title_match"] = (bool)(exp_word == ctrl_title_words[idx]); break; } } static void compare_dns_queries(Var entry, std::vector experiment_addresses, Entry control, Settings options) { Var logger = Logger::global(); // When the controls fails in the same way as the experiment we consider the // DNS queries to be consistent. // XXX ensure the failure messages are aligned between ooniprobe and MK if ((*entry)["dns_experiment_failure"] != nullptr) { std::string exp_failure = (*entry)["dns_experiment_failure"]; std::string ctrl_failure = control["failure"]; if (exp_failure == ctrl_failure) { (*entry)["dns_consistency"] = "consistent"; } else { (*entry)["dns_consistency"] = "inconsistent"; } return; } std::set exp_addresses(experiment_addresses.begin(), experiment_addresses.end()); std::set ctrl_addresses; for (std::string addr : control["addrs"]) { ctrl_addresses.insert(addr); } if (exp_addresses == ctrl_addresses) { (*entry)["dns_consistency"] = "consistent"; return; } for (auto exp_addr : exp_addresses) { if (is_private_ipv4_addr(exp_addr) == true) { (*entry)["dns_consistency"] = "inconsistent"; return; } } std::set common_addresses; std::set_intersection( exp_addresses.begin(), exp_addresses.end(), ctrl_addresses.begin(), ctrl_addresses.end(), std::inserter(common_addresses, common_addresses.begin())); if (common_addresses.size() > 0) { (*entry)["dns_consistency"] = "consistent"; return; } std::set exp_asns; std::set ctrl_asns; std::string asn_p = options.get("geoip_asn_path", std::string{}); auto ip_location = GeoipCache::thread_local_instance()->get(asn_p); for (auto exp_addr : exp_addresses) { ErrorOr asn = ip_location->resolve_asn(exp_addr); if (asn && asn.as_value() != "AS0") { exp_asns.insert(asn.as_value()); } } for (auto ctrl_addr : ctrl_addresses) { ErrorOr asn = ip_location->resolve_asn(ctrl_addr); if (asn && asn.as_value() != "AS0") { ctrl_asns.insert(asn.as_value()); } } std::set common_asns; std::set_intersection(exp_asns.begin(), exp_asns.end(), ctrl_asns.begin(), ctrl_asns.end(), std::inserter(common_asns, common_asns.begin())); if (common_asns.size() > 0) { (*entry)["dns_consistency"] = "consistent"; return; } (*entry)["dns_consistency"] = "inconsistent"; } static bool compare_tcp_connect(Var entry, Entry control) { bool success = true; int idx = 0; for (auto result : (*entry)["tcp_connect"]) { bool ctrl_status; bool exp_status = result["status"]["success"]; // XXX this is wasteful std::string ip = result["ip"]; std::ostringstream ss; ss << ip; ss << ":"; ss << result["port"]; try { ctrl_status = control.at(ss.str())["status"]; } catch (const std::out_of_range &) { continue; } if (ctrl_status == true && exp_status == false) { (*entry)["tcp_connect"][idx]["status"]["blocked"] = true; success = false; } else { (*entry)["tcp_connect"][idx]["status"]["blocked"] = false; } idx++; } return success; } static void compare_control_experiment(std::string input, Var entry, Var response, std::vector addresses, Settings options, Var logger) { if ((*entry)["control_failure"] != nullptr) { logger->warn( "web_connectivity: skipping control comparison due to failure"); return; } logger->debug("web_connectivity: control is like %s", (*entry)["control"].dump().c_str()); if ((*entry)["http_experiment_failure"] == nullptr && (*entry)["control"]["http_request"]["failure"] == nullptr) { logger->debug("web_connectivity: comparing http_requests"); compare_http_requests(entry, response, (*entry)["control"]["http_request"], logger); } logger->debug("web_connectivity: comparing dns_queries"); compare_dns_queries(entry, addresses, (*entry)["control"]["dns"], options); logger->debug("web_connectivity: comparing tcp_connect"); bool tcp_connect_success = compare_tcp_connect(entry, (*entry)["control"]["tcp_connect"]); std::string exp_http_failure; std::string ctrl_http_failure; std::string dns_consistency = (*entry)["dns_consistency"]; logger->debug("web_connectivity: exp,ctrl http failure determination"); if ((*entry)["http_experiment_failure"] != nullptr) { exp_http_failure = split((*entry)["http_experiment_failure"]).front(); } if ((*entry)["control"]["http_request"]["failure"] != nullptr) { ctrl_http_failure = split((*entry)["control"]["http_request"]["failure"]).front(); } logger->debug("web_connectivity: checking if we got expected web page"); logger->debug("%s", (*entry).dump().c_str()); bool got_expected_web_page = false; if (exp_http_failure == "" && ctrl_http_failure == "") { got_expected_web_page = ((((bool)(*entry)["body_length_match"]) == true || ((bool)(*entry)["headers_match"]) == true || ((bool)(*entry)["title_match"]) == true) && ((bool)(*entry)["status_code_match"]) != false); } logger->debug("web_connectivity: determining blocking reason"); if (dns_consistency == "consistent" && tcp_connect_success == false && exp_http_failure != "") { (*entry)["blocking"] = "tcp_ip"; } else if (dns_consistency == "consistent" && tcp_connect_success == true && got_expected_web_page == false && exp_http_failure == "" && ctrl_http_failure == "") { (*entry)["blocking"] = "http-diff"; } else if (dns_consistency == "consistent" && tcp_connect_success == true && exp_http_failure != "" && ctrl_http_failure == "") { if (exp_http_failure == "dns_lookup_error") { (*entry)["blocking"] = "dns"; } else { (*entry)["blocking"] = "http-failure"; } } else if (dns_consistency == "inconsistent" && got_expected_web_page == false) { // Note this slightly differs from the OONI logic // because the got_expected_page is more strict in MK (*entry)["blocking"] = "dns"; } else if (dns_consistency == "consistent" && got_expected_web_page == false && (exp_http_failure == "" && ctrl_http_failure == "") && ((*entry)["control"]["dns"]["failure"] != nullptr || ctrl_http_failure != exp_http_failure)) { (*entry)["blocking"] = "dns"; } if ((*entry)["blocking"] != nullptr) { std::string blocking = (*entry)["blocking"]; logger->info("web_connectivity: BLOCKING detected due to: %s on %s", blocking.c_str(), input.c_str()); (*entry)["accessible"] = false; } else { logger->info("web_connectivity: no blocking detected"); (*entry)["accessible"] = true; (*entry)["blocking"] = false; } } static void control_request(http::Headers headers_to_pass_along, Var entry, SocketList socket_list, std::string url, Callback callback, Settings settings, Var reactor, Var logger) { // Implementation note: this function uses (and modifies) the settings // passed by the caller because such object is passed by copy and we // need to add options to a number of options already set by the caller // and it would not be wise to remember to copy them one by one (also // considering that from time to time we add new options) http::Headers headers; Entry request; request["tcp_connect"] = Entry::array(); for (auto socket : socket_list) { // Formats the sockets as IP:PORT std::ostringstream ss; if (is_private_ipv4_addr(socket.first) == true) { continue; } ss << socket.first; ss << ":"; ss << socket.second; request["tcp_connect"].push_back(ss.str()); } request["http_request"] = url; // XXX in OONI headers are like `key: [value,...]` whereas in MK // they are like `key: value`. Adapt to OONI format. Entry true_headers; for (auto pair: headers_to_pass_along) { true_headers[pair.first].push_back(pair.second); } request["http_request_headers"] = true_headers; std::string body = request.dump(); settings["http/url"] = settings["backend"]; settings["http/method"] = "POST"; headers["Content-Type"] = "application/json"; if (settings["backend/type"] == "cloudfront") { // TODO set the appropriate headers to support cloud-fronting. } logger->info("Using backend %s", settings["backend"].c_str()); logger->log(MK_LOG_DEBUG2, "Body %s", body.c_str()); mk::dump_settings(settings, "web_connectivity", logger); http::request(settings, headers, body, [=](Error error, Var response) { if (!error) { try { (*entry)["control"] = Entry::parse(response->body); callback(NoError()); return; } catch (const std::invalid_argument &) { (*entry)["control_failure"] = "json_parse_error"; callback(JsonParseError()); return; } } (*entry)["control_failure"] = error.as_ooni_error(); callback(error); return; }, reactor, logger); } static void experiment_http_request( Var entry, std::string url, Callback> cb, Settings options, Var reactor, Var logger) { http::Headers headers = constants::COMMON_CLIENT_HEADERS; std::string body; options["http/url"] = url; /* * Only for web-connectivity: * * - we want to allow any SSL protocol such that we can scan a * more wide range of servers * * - we allow SSL dirty shutdowns to gather more evidence */ options["net/allow_ssl23"] = true; options["net/ssl_allow_dirty_shutdown"] = true; logger->debug("Requesting url %s", url.c_str()); templates::http_request(entry, options, headers, body, [=](Error err, Var response) { if (err) { (*entry)["http_experiment_failure"] = err.as_ooni_error(); cb(err, headers, response); return; } cb(NoError(), headers, response); }, reactor, logger); } static void experiment_tcp_connect(Var entry, SocketList sockets, Callback cb, Var reactor, Var logger) { int socket_count = sockets.size(); Var sockets_tested(new int(0)); // XXX this is very ghetto if (socket_count == 0) { cb(NoError()); return; } auto handle_connect = [=](std::string ip, int port) { return [=](Error err, Var txp) { *sockets_tested += 1; bool close_txp = true; Entry result = { {"ip", ip}, {"port", port}, {"status", {{"success", nullptr}, {"failure", nullptr}, {"blocked", nullptr}}}, }; if (!!err) { logger->info("web_connectivity: failed to connect to %s:%d", ip.c_str(), port); result["status"]["success"] = false; result["status"]["failure"] = err.as_ooni_error(); close_txp = false; } else { logger->info("web_connectivity: success to connect to %s:%d", ip.c_str(), port); result["status"]["success"] = true; result["status"]["blocked"] = false; } (*entry)["tcp_connect"].push_back(result); if (socket_count == *sockets_tested) { if (close_txp == true) { txp->close([=] { cb(NoError()); }); } else { cb(NoError()); } } else { if (close_txp == true) { // XXX optimistic closure txp->close([=] {}); } } }; }; for (auto socket : sockets) { std::string address = socket.first; int port = socket.second; Settings connect_options; connect_options["host"] = address; connect_options["port"] = port; connect_options["net/timeout"] = 10.0; templates::tcp_connect(connect_options, handle_connect(address, port), reactor, logger); } } static void experiment_dns_query( Var entry, std::string hostname, std::string nameserver, Callback> callback, Settings options, Var reactor, Var logger) { if (net::is_ip_addr(hostname)) { // Don't perform DNS resolutions if it's an IP address // XXX This means we are not filling the entry std::vector addresses; addresses.push_back(hostname); callback(NoError(), addresses); return; } templates::dns_query( entry, "A", "IN", hostname, nameserver, [=](Error err, Var message) { std::vector addresses; if (err) { callback(err, addresses); return; } for (auto answer : message->answers) { if (answer.ipv4 != "") { addresses.push_back(answer.ipv4); } else if (answer.hostname != "") { addresses.push_back(answer.ipv4); } else { /* Not yet implemented */ ; } } callback(NoError(), addresses); }, options, reactor, logger); } void web_connectivity(std::string input, Settings options, Callback> callback, Var reactor, Var logger) { options["http/max_redirects"] = 20; Var entry(new Entry); // This is set from ooni test // (*entry)["client_resolver"] = nullptr; (*entry)["retries"] = nullptr; (*entry)["dns_consistency"] = nullptr; (*entry)["body_length_match"] = nullptr; (*entry)["body_proportion"] = 0.0; (*entry)["headers_match"] = nullptr; (*entry)["status_code_match"] = nullptr; (*entry)["title_match"] = nullptr; (*entry)["accessible"] = nullptr; (*entry)["blocking"] = nullptr; (*entry)["control_failure"] = nullptr; (*entry)["http_experiment_failure"] = nullptr; (*entry)["dns_experiment_failure"] = nullptr; (*entry)["tcp_connect"] = Entry::array(); (*entry)["control"] = Entry({}); if (!mk::startswith(input, "http://") && !mk::startswith(input, "https://")) { // Similarly to ooni-probe also accept a list of endpoints input = "http://" + input; } ErrorOr url = mk::http::parse_url_noexcept(input); if (!url) { logger->warn("Invalid test url."); (*entry)["failure"] = url.as_error().as_ooni_error(); callback(entry); return; } std::string hostname = url->address; std::string nameserver = options["nameserver"]; if (nameserver != "") { logger->warn("web_connectivity: you're using the deprecated " "'nameserver' option"); } logger->info("web_connectivity: starting dns_query for %s", hostname.c_str()); // TODO: is this correct here to continue on errors? experiment_dns_query( entry, hostname, nameserver, [=](Error err, std::vector addresses) { if (err) { logger->warn("web_connectivity: dns-query error: %s", err.explain().c_str()); } logger->info("web_connectivity: starting tcp_connect"); SocketList socket_list; for (auto addr : addresses) { socket_list.push_back(std::make_pair(addr, url->port)); } experiment_tcp_connect( entry, socket_list, [=](Error err) { if (err) { logger->warn("web_connectivity: tcp-connect error: %s", err.explain().c_str()); } logger->info( "web_connectivity: starting http_request to %s", input.c_str()); experiment_http_request( entry, input, [=](Error err, http::Headers request_headers, Var response) { if (err) { logger->warn( "web_connectivity: http-request error: %s", err.explain().c_str()); } logger->info( "web_connectivity: doing control request"); control_request( request_headers, entry, socket_list, input, [=](Error err) { if (err) { logger->warn("web_connectivity: " "control-request error: " "%s", err.explain().c_str()); } logger->info("web_connectivity: comparing " "control with experiment"); compare_control_experiment( input, entry, response, addresses, options, logger); callback(entry); }, options, reactor, logger); // end control_request }, options, reactor, logger); // end http_request }, reactor, logger); // end tcp_connect }, options, reactor, logger); // end dns_query } } // namespace ooni } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/portable/000077500000000000000000000000001315356162600231235ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/portable/citrus_utf8.c000066400000000000000000000210471315356162600255520ustar00rootroot00000000000000/* $OpenBSD: citrus_utf8.c,v 1.18 2016/09/07 17:15:06 schwarze Exp $ */ /*- * Copyright (c) 2002-2004 Tim J. Robbins * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include "private/portable/citrus_adapt.h" size_t _citrus_utf8_ctype_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, mbstate_t * __restrict ps) { struct _utf8_state *us; int ch, i, mask, want; wchar_t lbound, wch; us = (struct _utf8_state *)ps; if (us->want < 0 || us->want > _CITRUS_UTF8_MB_CUR_MAX) { errno = EINVAL; return -1; } if (s == NULL) { s = ""; n = 1; pwc = NULL; } if (n == 0) return -2; if (us->want == 0 && ((ch = (unsigned char)*s) & ~0x7f) == 0) { /* Fast path for plain ASCII characters. */ if (pwc != NULL) *pwc = ch; return ch != '\0' ? 1 : 0; } if (us->want == 0) { /* * Determine the number of bytes that make up this character * from the first byte, and a mask that extracts the * interesting bits of the first byte. We already know * the character is at least two bytes long. * * We also specify a lower bound for the character code to * detect redundant, non-"shortest form" encodings. For * example, the sequence C0 80 is _not_ a legal representation * of the null character. This enforces a 1-to-1 mapping * between character codes and their multibyte representations. */ ch = (unsigned char)*s; if ((ch & 0x80) == 0) { mask = 0x7f; want = 1; lbound = 0; } else if ((ch & 0xe0) == 0xc0) { mask = 0x1f; want = 2; lbound = 0x80; } else if ((ch & 0xf0) == 0xe0) { mask = 0x0f; want = 3; lbound = 0x800; } else if ((ch & 0xf8) == 0xf0) { mask = 0x07; want = 4; lbound = 0x10000; } else { /* * Malformed input; input is not UTF-8. * See RFC 3629. */ errno = EILSEQ; return -1; } } else { want = us->want; lbound = us->lbound; } /* * Decode the byte sequence representing the character in chunks * of 6 bits, most significant first. */ if (us->want == 0) wch = (unsigned char)*s++ & mask; else wch = us->ch; for (i = (us->want == 0) ? 1 : 0; i < want && (size_t)i < n; i++) { if ((*s & 0xc0) != 0x80) { /* * Malformed input; bad byte in the middle * of a character. */ errno = EILSEQ; return -1; } wch <<= 6; wch |= *s++ & 0x3f; } if (i < want) { /* Incomplete multibyte sequence. */ us->want = want - i; us->lbound = lbound; us->ch = wch; return -2; } if (wch < lbound) { /* * Malformed input; redundant encoding. */ errno = EILSEQ; return -1; } if (wch >= 0xd800 && wch <= 0xdfff) { /* * Malformed input; invalid code points. */ errno = EILSEQ; return -1; } if (wch > 0x10ffff) { /* * Malformed input; invalid code points. */ errno = EILSEQ; return -1; } if (pwc != NULL) *pwc = wch; us->want = 0; return wch == L'\0' ? 0 : want; } int _citrus_utf8_ctype_mbsinit(const mbstate_t * __restrict ps) { return ((const struct _utf8_state *)ps)->want == 0; } size_t _citrus_utf8_ctype_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t nmc, size_t len, mbstate_t * __restrict ps) { struct _utf8_state *us; size_t i, o, r; us = (struct _utf8_state *)ps; if (dst == NULL) { /* * The fast path in the loop below is not safe if an ASCII * character appears as anything but the first byte of a * multibyte sequence. Check now to avoid doing it in the loop. */ if (nmc > 0 && us->want > 0 && (unsigned char)(*src)[0] < 0x80) { errno = EILSEQ; return -1; } for (i = o = 0; i < nmc; i += r, o++) { if ((unsigned char)(*src)[i] < 0x80) { /* Fast path for plain ASCII characters. */ if ((*src)[i] == '\0') return o; r = 1; } else { r = _citrus_utf8_ctype_mbrtowc(NULL, *src + i, nmc - i, ps); if (r == (size_t)-1) return r; if (r == (size_t)-2) return o; if (r == 0) return o; } } return o; } /* * The fast path in the loop below is not safe if an ASCII * character appears as anything but the first byte of a * multibyte sequence. Check now to avoid doing it in the loop. */ if (len > 0 && nmc > 0 && us->want > 0 && (unsigned char)(*src)[0] < 0x80) { errno = EILSEQ; return -1; } for (i = o = 0; i < nmc && o < len; i += r, o++) { if ((unsigned char)(*src)[i] < 0x80) { /* Fast path for plain ASCII characters. */ dst[o] = (wchar_t)(unsigned char)(*src)[i]; if ((*src)[i] == '\0') { *src = NULL; return o; } r = 1; } else { r = _citrus_utf8_ctype_mbrtowc(dst + o, *src + i, nmc - i, ps); if (r == (size_t)-1) { *src += i; return r; } if (r == (size_t)-2) { *src += nmc; return o; } if (r == 0) { *src = NULL; return o; } } } *src += i; return o; } size_t _citrus_utf8_ctype_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) { struct _utf8_state *us; unsigned char lead; int i, len; us = (struct _utf8_state *)ps; if (us->want != 0) { errno = EINVAL; return -1; } if (s == NULL) return 1; if (wc < 0 || (wc > 0xd7ff && wc < 0xe000) || wc > 0x10ffff) { errno = EILSEQ; return -1; } /* * Determine the number of bytes needed to represent this character. * We always output the shortest sequence possible. Also specify the * first few bits of the first byte, which contains the information * about the sequence length. */ if (wc <= 0x7f) { /* Fast path for plain ASCII characters. */ *s = (char)wc; return 1; } else if (wc <= 0x7ff) { lead = 0xc0; len = 2; } else if (wc <= 0xffff) { lead = 0xe0; len = 3; } else { lead = 0xf0; len = 4; } /* * Output the bytes representing the character in chunks * of 6 bits, least significant last. The first byte is * a special case because it contains the sequence length * information. */ for (i = len - 1; i > 0; i--) { s[i] = (wc & 0x3f) | 0x80; wc >>= 6; } *s = (wc & 0xff) | lead; return len; } size_t _citrus_utf8_ctype_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, size_t len, mbstate_t * __restrict ps) { struct _utf8_state *us; char buf[_CITRUS_UTF8_MB_CUR_MAX]; size_t i, o, r; us = (struct _utf8_state *)ps; if (us->want != 0) { errno = EINVAL; return -1; } if (dst == NULL) { for (i = o = 0; i < nwc; i++, o += r) { wchar_t wc = (*src)[i]; if (wc >= 0 && wc < 0x80) { /* Fast path for plain ASCII characters. */ if (wc == 0) return o; r = 1; } else { r = _citrus_utf8_ctype_wcrtomb(buf, wc, ps); if (r == (size_t)-1) return r; } } return o; } for (i = o = 0; i < nwc && o < len; i++, o += r) { wchar_t wc = (*src)[i]; if (wc >= 0 && wc < 0x80) { /* Fast path for plain ASCII characters. */ dst[o] = (wchar_t)wc; if (wc == 0) { *src = NULL; return o; } r = 1; } else if (len - o >= _CITRUS_UTF8_MB_CUR_MAX) { /* Enough space to translate in-place. */ r = _citrus_utf8_ctype_wcrtomb(dst + o, wc, ps); if (r == (size_t)-1) { *src += i; return r; } } else { /* May not be enough space; use temp buffer. */ r = _citrus_utf8_ctype_wcrtomb(buf, wc, ps); if (r == (size_t)-1) { *src += i; return r; } if (r > len - o) break; memcpy(dst + o, buf, r); } } *src += i; return o; } measurement-kit-0.7.1/src/libmeasurement_kit/portable/strtonum.c000066400000000000000000000041061315356162600251630ustar00rootroot00000000000000/* $OpenBSD: strtonum.c,v 1.8 2015/09/13 08:31:48 guenther Exp $ */ /* * Copyright (c) 2004 Ted Unangst and Todd Miller * All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifndef HAVE_STRTONUM #define INVALID 1 #define TOOSMALL 2 #define TOOLARGE 3 static inline long long mkp_strtonum_(const char *numstr, long long minval, long long maxval, const char **errstrp) { long long ll = 0; int error = 0; char *ep; struct errval { const char *errstr; int err; } ev[4] = { { NULL, 0 }, { "invalid", EINVAL }, { "too small", ERANGE }, { "too large", ERANGE }, }; ev[0].err = errno; errno = 0; if (minval > maxval) { error = INVALID; } else { ll = strtoll(numstr, &ep, 10); if (numstr == ep || *ep != '\0') error = INVALID; else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) error = TOOSMALL; else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) error = TOOLARGE; } if (errstrp != NULL) *errstrp = ev[error].errstr; errno = ev[error].err; if (error) ll = 0; return (ll); } /*DEF_WEAK(strtonum);*/ # define strtonum mkp_strtonum_ #endif long long mkp_strtonum(const char *numstr, long long minval, long long maxval, const char **errstrp) { return strtonum(numstr, minval, maxval, errstrp); } measurement-kit-0.7.1/src/libmeasurement_kit/report/000077500000000000000000000000001315356162600226265ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/report/base_reporter.cpp000066400000000000000000000046331315356162600261740ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/common/utils.hpp" #include namespace mk { namespace report { /* static */ Var BaseReporter::make() { return Var(new BaseReporter); } BaseReporter::~BaseReporter() {} Continuation BaseReporter::do_open_(Continuation cc) { return [=](Callback cb) { if (openned_) { // Make the operation idempotent by not failing it, but still pass // a child error to tell the caller report was already openned cb(NoError(ReportAlreadyOpenError())); return; } cc([=](Error error) { if (error) { cb(error); return; } openned_ = true; cb(NoError()); }); }; } Continuation BaseReporter::do_write_entry_(Entry entry, Continuation cc) { return [=](Callback cb) { if (!openned_) { cb(ReportNotOpenError()); return; } if (closed_) { cb(ReportAlreadyClosedError()); return; } // On success we save the serialization of the previous entry such // that submitting more than once the same entry is idempontent std::string serio = entry.dump(); if (serio == prev_entry_) { cb(NoError(DuplicateEntrySubmitError())); return; } cc([=](Error error) { if (error) { cb(error); return; } prev_entry_ = serio; // Only on success to allow resubmit cb(NoError()); }); }; } Continuation BaseReporter::do_close_(Continuation cc) { return [=](Callback cb) { if (closed_) { // Make the operation idempotent by not failing it, but still pass // a child error to tell the caller report was already openned cb(NoError(ReportAlreadyClosedError())); return; } cc([=](Error error) { if (error) { cb(error); return; } closed_ = true; cb(NoError()); }); }; } } // namespace report } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/report/entry.cpp000066400000000000000000000031741315356162600245000ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include namespace mk { namespace report { /* static */ Entry Entry::array() { Entry entry; // Manually construct an empty array by pushing // a value and then removing it entry.push_back(17.0); entry.erase(0); return entry; } /* static */ Entry Entry::object() { Entry entry; // Manually construct an empty object by pushing // a value and then removing it entry["foo"] = "bar"; entry.erase("foo"); return entry; } Entry &Entry::operator=(std::initializer_list t) { nlohmann::json::operator=(t); return *this; } void Entry::push_back(Entry value) { try { nlohmann::json::push_back(value); } catch (const std::domain_error &) { throw JsonDomainError(); } } void Entry::push_back(std::initializer_list j) { try { nlohmann::json::push_back(j); } catch (const std::domain_error &) { throw JsonDomainError(); } } std::string Entry::dump(const int indent) const { return nlohmann::json::dump(indent); } Entry Entry::parse(const std::string &s) { return static_cast(nlohmann::json::parse(s)); } bool Entry::operator==(std::nullptr_t right) const noexcept { return static_cast(*this) == right; } bool Entry::operator!=(std::nullptr_t right) const noexcept { return static_cast(*this) != right; } } // namespace report } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/report/file_reporter.cpp000066400000000000000000000033371315356162600262010ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include namespace mk { namespace report { static Error map_error(std::ostream &file) { if (file.eof()) { return ReportEofError(); } if (file.bad()) { return ReportIoError(); } if (file.fail()) { return ReportLogicalError(); } return GenericError(); } /* static */ Var FileReporter::make(std::string s) { Var reporter(new FileReporter); reporter->filename = s; return reporter.as(); } Continuation FileReporter::open(Report &) { return do_open_([=](Callback cb) { if (filename == "-") { cb(NoError()); return; } file.open(filename); if (!file.good()) { cb(map_error(file)); return; } cb(NoError()); }); } Continuation FileReporter::write_entry(Entry entry) { return do_write_entry_(entry, [=](Callback cb) { std::ostream &frf = (filename == "-") ? std::cout : file; frf << entry.dump() << std::endl; if (!frf.good()) { cb(map_error(frf)); return; } cb(NoError()); }); } Continuation FileReporter::close() { return do_close_([=](Callback cb) { if (filename == "-") { cb(NoError()); return; } file.close(); if (!file.good()) { cb(map_error(file)); return; } cb(NoError()); }); } } // namespace report } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/report/ooni_reporter.cpp000066400000000000000000000104421315356162600262210ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include #include namespace mk { namespace report { OoniReporter::OoniReporter(Settings s, Var r, Var l) { settings = s; reactor = r; logger = l; if (settings.find("collector_base_url") == settings.end()) { // Note: by default we use the production collector URL and we need // to remember to switch to the testing one in tests. settings["collector_base_url"] = ooni::collector::production_collector_url(); } logger->info("Results collector: %s", settings["collector_base_url"].c_str()); } /* static */ Var OoniReporter::make(Settings settings, Var reactor, Var logger) { Var reporter(new OoniReporter(settings, reactor, logger)); return reporter.as(); } Continuation OoniReporter::open(Report &report) { return do_open_([=](Callback cb) { logger->info("Opening report; please be patient..."); ooni::collector::connect_and_create_report( report.get_dummy_entry(), [=](Error error, std::string rid) { logger->debug("Opening report... %d", error.code); if (not error) { logger->info("Report ID: %s", rid.c_str()); report_id = rid; } cb(error); }, settings, reactor, logger); }); } Continuation OoniReporter::write_entry(Entry entry) { // Register action for when we will be asked to write the entry return do_write_entry_(entry, [=](Callback cb) { if (report_id == "") { logger->warn("ooni_reporter: missing report ID"); cb(MissingReportIdError()); return; } logger->info("Submitting test results; please be patient..."); ooni::collector::connect_and_update_report(report_id, entry, [=](Error e) { logger->debug( "Submitting entry... %d", e.code); if (!e) { logger->info("Results " "successfully " "submitted"); } cb(e); }, settings, reactor, logger); }); } Continuation OoniReporter::close() { return do_close_([=](Callback cb) { if (report_id == "") { logger->warn("ooni_reporter: missing report ID"); cb(MissingReportIdError()); return; } logger->info("Closing report; please be patient..."); ooni::collector::connect_and_close_report(report_id, [=](Error e) { logger->debug( "Closing report... %d", e.code); if (!e) { logger->info("Report " "successfully closed"); } cb(e); }, settings, reactor, logger); }); } std::string OoniReporter::get_report_id() { return report_id; } } // namespace report } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/report/report.cpp000066400000000000000000000066241315356162600246550ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "private/common/fmap.hpp" #include "private/common/parallel.hpp" #include "private/common/utils.hpp" #include namespace mk { namespace report { Report::Report() { memset(&test_start_time, 0, sizeof (test_start_time)); } void Report::add_reporter(Var reporter) { reporters_.push_back(reporter); } void Report::fill_entry(Entry &entry) const { entry["test_name"] = test_name; entry["test_version"] = test_version; entry["test_start_time"] = *mk::timestamp(&test_start_time); // header["options"] = options; entry["probe_ip"] = probe_ip; entry["probe_asn"] = probe_asn; entry["probe_cc"] = probe_cc; entry["software_name"] = options.get("software_name", software_name); entry["software_version"] = options.get("software_version", software_version); entry["data_format_version"] = data_format_version; entry["annotations"]["platform"] = options.get("platform", std::string{mk_platform()}); entry["annotations"]["engine_name"] = "libmeasurement_kit"; entry["annotations"]["engine_version"] = MK_VERSION; entry["annotations"]["engine_version_full"] = MK_VERSION_FULL; } Entry Report::get_dummy_entry() const { Entry entry; fill_entry(entry); return entry; } #define FMAP mk::fmap, Continuation> void Report::open(Callback callback) { mk::parallel(FMAP(reporters_, [=](Var r) { return r->open(*this); }), callback); } void Report::write_entry(Entry entry, Callback callback, Var logger) { if (report_id == "") { auto count = 0; for (auto &reporter : reporters_) { auto rid = reporter->get_report_id(); if (rid != "") { report_id = rid; ++count; } } /* * XXX For now we trust the last reporter that provides us with a * non-zero-length report-id. The reason for doing the full scan * over the existing reporters and for checking is to be ready for * an hypothetical moment where more than one reporter will give * back a good report-id (only ooni_reporter does that). */ if (count > 1) { callback(MultipleReportIdsError()); return; } if (report_id != "") { logger->debug("report: found report-id: '%s'", report_id.c_str()); } } /* * Override the report id with the one found above (if any). Note that * memoization to prevent submitting multiple times in case of a partial * failure and retry will be performed by write_entry() below. */ if (report_id != "") { entry["report_id"] = report_id; logger->debug("report: force adding to entry report-id: %s", entry["report_id"].dump().c_str()); } mk::parallel(FMAP(reporters_, [=](Var r) { return r->write_entry(entry); }), callback); } void Report::close(Callback callback) { mk::parallel(FMAP(reporters_, [](Var r) { return r->close(); }), callback); } #undef FMAP // So long, and thanks for the fish } // namespace report } // namespace mk measurement-kit-0.7.1/src/libmeasurement_kit/traceroute/000077500000000000000000000000001315356162600234705ustar00rootroot00000000000000measurement-kit-0.7.1/src/libmeasurement_kit/traceroute/android.cpp000066400000000000000000000302541315356162600256200ustar00rootroot00000000000000/*- * Part of measurement-kit . * Measurement-kit is free software. See AUTHORS and LICENSE for more * information on the copying conditions. * ========================================================================= * Based on Portolan code contributed by its authors. * See . * * Portions Copyright (c) 2015, Adriano Faggiani, Enrico Gregori, * Luciano Lenzini, Valerio Luconi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /// Android implementation of prober // This is meant to run on Android but can run on all Linux systems #if (!defined __linux__ || !defined ENABLE_TRACEROUTE) void mk_traceroute_android_unused(); void mk_traceroute_android_unused() {} #else #include "private/net/utils.hpp" #include "private/common/utils.hpp" #include #include #include #include #include #include namespace mk { namespace traceroute { AndroidProber::AndroidProber(bool a, int port, Var r, Var l) : use_ipv4_(a), reactor(r), port_(port), logger(l) {} void AndroidProber::init() { if (sockfd_ >= 0) { return; } sockaddr_storage ss; socklen_t sslen; int level_sock, opt_recverr, level_proto, opt_recvttl, family; const int val = 1; logger->debug("AndroidProber(%d, %d, %p) => %p", use_ipv4_, port_, (void *)reactor.get(), (void *)this); if (use_ipv4_) { level_sock = SOL_IP; opt_recverr = IP_RECVERR; level_proto = IPPROTO_IP; opt_recvttl = IP_RECVTTL; family = AF_INET; } else { level_sock = SOL_IPV6; opt_recverr = IPV6_RECVERR; level_proto = IPPROTO_IPV6; opt_recvttl = IPV6_RECVHOPLIMIT; family = AF_INET6; } sockfd_ = mk::net::socket_create(family, SOCK_DGRAM, 0, logger); if (sockfd_ == -1) { cleanup(); error_cb_(SocketCreateError()); return; } if (setsockopt(sockfd_, level_sock, opt_recverr, &val, sizeof(val)) != 0 || setsockopt(sockfd_, level_proto, opt_recvttl, &val, sizeof(val)) != 0 || setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) != 0) { cleanup(); error_cb_(SetsockoptError()); return; } if (mk::net::storage_init(&ss, &sslen, family, NULL, port_, logger) != 0) { cleanup(); error_cb_(StorageInitError()); return; } if (bind(sockfd_, (sockaddr *)&ss, sslen) != 0) { cleanup(); error_cb_(BindError()); return; } } void AndroidProber::send_probe(std::string addr, int port, int ttl, std::string payload, double timeout) { int ipproto, ip_ttl, family; sockaddr_storage ss; socklen_t sslen; init(); logger->debug("send_probe(%s, %d, %d, %lu)", addr.c_str(), port, ttl, payload.length()); if (sockfd_ < 0) { error_cb_(SocketAlreadyClosedError()); // already close()d return; } // Note: until we figure out exactly how to deal with overlapped // probes enforce to traceroute hop by hop only if (probe_pending_) { error_cb_(ProbeAlreadyPendingError()); return; } if (use_ipv4_) { ipproto = IPPROTO_IP; ip_ttl = IP_TTL; family = PF_INET; } else { ipproto = IPPROTO_IPV6; ip_ttl = IPV6_UNICAST_HOPS; family = PF_INET6; } if (setsockopt(sockfd_, ipproto, ip_ttl, &ttl, sizeof(ttl)) != 0) { error_cb_(SetsockoptError()); return; } if (mk::net::storage_init(&ss, &sslen, family, addr.c_str(), port, logger) != 0) { error_cb_(StorageInitError()); return; } if (clock_gettime(CLOCK_MONOTONIC, &start_time_) != 0) { error_cb_(ClockGettimeError()); return; } // Note: cast to ssize_t safe because payload length is bounded // We may want however to increase the maximum accepted length if (payload.length() > 512) { error_cb_(PayloadTooLongError()); return; } if (sendto(sockfd_, payload.data(), payload.length(), 0, (sockaddr *)&ss, sslen) != (ssize_t)payload.length()) { mk::warn("sendto() failed: errno %d", errno); error_cb_(SendtoError()); return; } // Note: we bind this, which makes this object non copyable or movable reactor->pollfd(sockfd_, MK_POLLIN, [this](Error err, short flags) { event_callback(err, flags); }, timeout); probe_pending_ = true; } ProbeResult AndroidProber::on_socket_readable() { int expected_level, expected_type_recverr, expected_type_ttl; uint8_t expected_origin; sock_extended_err *socket_error; unsigned char buff[512]; char controlbuff[512]; ProbeResult r; msghdr msg; cmsghdr *cmsg; iovec iov; timespec arr_time; sockaddr_storage storage; socklen_t solen; logger->debug("on_socket_readable()"); if (!probe_pending_) throw NoProbePendingError(); probe_pending_ = false; r.is_ipv4 = use_ipv4_; if (clock_gettime(CLOCK_MONOTONIC, &arr_time) != 0) throw ClockGettimeError(); r.rtt = calculate_rtt(arr_time, start_time_); logger->debug("rtt = %lf", r.rtt); memset(buff, 0, sizeof(buff)); iov.iov_base = buff; iov.iov_len = sizeof(buff); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; memset(controlbuff, 0, sizeof(controlbuff)); msg.msg_control = controlbuff; msg.msg_controllen = sizeof(controlbuff); msg.msg_flags = 0; if ((r.recv_bytes = recvmsg(sockfd_, &msg, MSG_ERRQUEUE)) < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // Defensive logger->debug("it seems we received a valid reply packet back"); memset(&storage, 0, sizeof(storage)); solen = sizeof(storage); if ((r.recv_bytes = recvfrom(sockfd_, buff, sizeof(buff), 0, (sockaddr *)&storage, &solen)) < 0) { throw std::runtime_error("recv() failed"); } logger->debug("recv_bytes = %lu", r.recv_bytes); r.valid_reply = true; logger->debug("valid_reply = %d", r.valid_reply); r.reply = std::string((const char *)buff, r.recv_bytes); logger->debug("reply = <%lu bytes>", r.reply.length()); r.interface_ip = get_source_addr(use_ipv4_, &storage); logger->debug("interface_ip = %s", r.interface_ip.c_str()); return r; } throw std::runtime_error("recvmsg() failed"); } logger->debug("recv_bytes = %lu", r.recv_bytes); if (use_ipv4_) { expected_level = SOL_IP; expected_type_recverr = IP_RECVERR; expected_type_ttl = IP_TTL; expected_origin = SO_EE_ORIGIN_ICMP; } else { expected_level = IPPROTO_IPV6; expected_type_recverr = IPV6_RECVERR; expected_type_ttl = IPV6_HOPLIMIT; expected_origin = SO_EE_ORIGIN_ICMP6; } for (cmsg = CMSG_FIRSTHDR(&msg); (cmsg); cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level != expected_level) { throw std::runtime_error("Unexpected socket level"); } if (cmsg->cmsg_type != expected_type_recverr && cmsg->cmsg_type != expected_type_ttl) { mk::warn("Received unexpected cmsg_type: %d", cmsg->cmsg_type); continue; } if (cmsg->cmsg_type == expected_type_ttl) { r.ttl = get_ttl(CMSG_DATA(cmsg)); logger->debug("ttl = %d", r.ttl); continue; } // Be robust to refactoring if (cmsg->cmsg_type != expected_type_recverr) throw std::runtime_error("Assertion Failed."); socket_error = (sock_extended_err *)CMSG_DATA(cmsg); if (socket_error->ee_origin != expected_origin) { mk::warn("Received unexpected ee_type: %d", cmsg->cmsg_type); continue; } r.icmp_type = socket_error->ee_type; logger->debug("icmp_type = %d", r.icmp_type); r.icmp_code = socket_error->ee_code; logger->debug("icmp_code = %d", r.icmp_code); r.interface_ip = get_source_addr(use_ipv4_, socket_error); logger->debug("interface_ip = %s", r.interface_ip.c_str()); } return r; } std::string AndroidProber::get_source_addr(const sockaddr_in *sin) { char ip[INET_ADDRSTRLEN]; if (inet_ntop(AF_INET, &sin->sin_addr, ip, INET_ADDRSTRLEN) == NULL) throw std::runtime_error("inet_ntop failed"); return std::string(ip); } std::string AndroidProber::get_source_addr(const sockaddr_in6 *sin6) { char ip[INET6_ADDRSTRLEN]; if (inet_ntop(AF_INET6, &sin6->sin6_addr, ip, INET6_ADDRSTRLEN) == NULL) throw std::runtime_error("inet_ntop failed"); return std::string(ip); } std::string AndroidProber::get_source_addr(bool use_ipv4, const sockaddr_storage *ss) { if (use_ipv4) { return get_source_addr((sockaddr_in *)ss); } return get_source_addr((sockaddr_in6 *)ss); } std::string AndroidProber::get_source_addr(bool use_ipv4, sock_extended_err *se) { if (use_ipv4) { const sockaddr_in *sin = (const sockaddr_in *)SO_EE_OFFENDER(se); return get_source_addr(sin); } else { const sockaddr_in6 *sin6 = (const sockaddr_in6 *)SO_EE_OFFENDER(se); return get_source_addr(sin6); } } double AndroidProber::calculate_rtt(struct timespec end, struct timespec start) { const long NSEC_PER_SEC = 1000000000; const long MICROSEC_PER_SEC = 1000000; timespec temp; if ((end.tv_nsec - start.tv_nsec) < 0) { temp.tv_sec = end.tv_sec - start.tv_sec - 1; temp.tv_nsec = NSEC_PER_SEC + end.tv_nsec - start.tv_nsec; } else { temp.tv_sec = end.tv_sec - start.tv_sec; temp.tv_nsec = end.tv_nsec - start.tv_nsec; } long tmp = NSEC_PER_SEC * temp.tv_sec; tmp += temp.tv_nsec; double rtt_ms = (double)tmp / MICROSEC_PER_SEC; if (rtt_ms < 0) rtt_ms = -1.0; // XXX return rtt_ms; } void AndroidProber::event_callback(Error err, short flags) { logger->debug("event_callback(%d, %d)", err.code, flags); if (err == net::TimeoutError()) { on_timeout(); timeout_cb_(); } else if (!err && (flags & MK_POLLIN) != 0) { ProbeResult result; try { result = on_socket_readable(); } catch (Error &error) { error_cb_(error); return; } result_cb_(result); } else { throw std::runtime_error("Unexpected event error"); } } void AndroidProber::cleanup() { logger->debug("cleanup(): %p", (void *)this); if (sockfd_ >= 0) { ::close(sockfd_); sockfd_ = -1; } } } // namespace traceroute } // namespace mk #endif // __linux__ measurement-kit-0.7.1/src/libmeasurement_kit/traceroute/interface.cpp000066400000000000000000000077041315356162600261440ustar00rootroot00000000000000/*- * Part of measurement-kit . * Measurement-kit is free software. See AUTHORS and LICENSE for more * information on the copying conditions. * ========================================================================= * Based on Portolan code contributed by its authors. * See . * * Portions Copyright (c) 2015, Adriano Faggiani, Enrico Gregori, * Luciano Lenzini, Valerio Luconi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /// Implementation of traceroute interface // Disable for non Linux until we figure out how to build on iOS #ifndef __linux__ void mk_traceroute_interface_unused(); void mk_traceroute_interface_unused() {} #else #include #include // Defines n_short etc on MacOSX #include #include namespace mk { namespace traceroute { struct ProbeResultMapping { unsigned char type; unsigned char code; ProbeResultMeaning meaning; }; #define PRM_ ProbeResultMeaning // For readability static ProbeResultMapping MAPPINGv4[] = { {ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, PRM_::TTL_EXCEEDED}, {ICMP_UNREACH, ICMP_UNREACH_PORT, PRM_::PORT_IS_CLOSED}, {ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, PRM_::PROTO_NOT_IMPL}, {ICMP_UNREACH, ICMP_UNREACH_NET, PRM_::NO_ROUTE_TO_HOST}, {ICMP_UNREACH, ICMP_UNREACH_HOST, PRM_::ADDRESS_UNREACH}, {255, 255, PRM_::OTHER}, }; static ProbeResultMapping MAPPINGv6[] = { {ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT, PRM_::TTL_EXCEEDED}, {ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, PRM_::PORT_IS_CLOSED}, {ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE, PRM_::NO_ROUTE_TO_HOST}, {ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, PRM_::ADDRESS_UNREACH}, {ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN, PRM_::ADMIN_FILTER}, {255, 255, PRM_::OTHER}, }; ProbeResultMeaning ProbeResult::get_meaning() { if (valid_reply) { mk::debug("type %d code %d meaning %lld (got reply packet)", icmp_type, icmp_code, (long long)PRM_::GOT_REPLY_PACKET); return PRM_::GOT_REPLY_PACKET; } for (auto m = is_ipv4 ? &MAPPINGv4[0] : &MAPPINGv6[0]; m->meaning != PRM_::OTHER; ++m) { if (m->type == icmp_type && m->code == icmp_code) { mk::debug("type %d code %d meaning %lld", icmp_type, icmp_code, (long long)m->meaning); return m->meaning; } } mk::debug("type %d code %d meaning %lld (other)", icmp_type, icmp_code, (long long)PRM_::OTHER); return PRM_::OTHER; } ProberInterface::~ProberInterface() {} #undef PRM_ } // namespace traceroute } // namespace mk #endif measurement-kit-0.7.1/src/measurement_kit/000077500000000000000000000000001315356162600206245ustar00rootroot00000000000000measurement-kit-0.7.1/src/measurement_kit/cmd/000077500000000000000000000000001315356162600213675ustar00rootroot00000000000000measurement-kit-0.7.1/src/measurement_kit/cmd/dash.cpp000066400000000000000000000036411315356162600230160ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "../cmdline.hpp" #include namespace dash { #define USAGE \ "usage: measurement_kit [options] dash [-b constant_bitrate] [-U uuid] " \ "[hostname]" int main(std::list> &initializers, int argc, char **argv) { nettests::DashTest test; for (int ch; (ch = getopt(argc, argv, "b:U:")) != -1;) { switch (ch) { case 'b': test.set_options("constant_bitrate", optarg); break; case 'U': test.set_options("uuid", optarg); break; default: fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } } argc -= optind, argv += optind; if (argc > 1) { fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } if (argc == 1) { test.set_options("hostname", argv[0]); } common_init(initializers, test) .on_entry([](std::string s) { nlohmann::json doc = nlohmann::json::parse(s); auto simple = doc["test_keys"]["simple"]; printf("\nTest summary\n"); printf("------------\n"); double median_bitrate = simple["median_bitrate"]; double min_playout_delay = simple["min_playout_delay"]; double connect_latency = simple["connect_latency"]; printf("Connect latency: %.2f ms\n", 1000.0 * connect_latency); printf("Median bitrate: %.2f kbit/s\n", median_bitrate); printf("Min. playout delay: %.3f s\n", min_playout_delay); printf("\n"); }) .run(); return 0; } } // namespace dash measurement-kit-0.7.1/src/measurement_kit/cmd/dns_injection.cpp000066400000000000000000000023231315356162600247210ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "../cmdline.hpp" namespace dns_injection { #define USAGE \ "usage: measurement_kit [options] dns_injection [-f input_file]\n" \ " [-r invalid_resolver_ip]" int main(std::list> &initializers, int argc, char **argv) { std::string backend = "8.8.8.1"; mk::nettests::DnsInjectionTest test; for (int ch; (ch = getopt(argc, argv, "f:r:")) != -1;) { switch (ch) { case 'f': test.add_input_filepath(optarg); break; case 'r': backend = optarg; break; default: fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } } argc -= optind, argv += optind; if (argc != 0) { fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } common_init(initializers, test.set_options("backend", backend)).run(); return 0; } } // namespace dns_injection measurement-kit-0.7.1/src/measurement_kit/cmd/http_header_field_manipulation.cpp000066400000000000000000000017501315356162600303100ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "../cmdline.hpp" namespace http_header_field_manipulation { #define USAGE "usage: measurement_kit [options] http_header_field_manipulation [-b backend]\n" int main(std::list> &initializers, int argc, char **argv) { mk::nettests::HttpHeaderFieldManipulationTest test; for (int ch; (ch = getopt(argc, argv, "b:")) != -1; ) { switch (ch) { case 'b': test.set_options("backend", optarg); break; default: fprintf(stderr, "%s\n", USAGE); exit(1); } } argc -= optind, argv += optind; if (argc != 0) { fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } common_init(initializers, test).run(); return 0; } } // namespace http_header_field_manipulation measurement-kit-0.7.1/src/measurement_kit/cmd/http_invalid_request_line.cpp000066400000000000000000000027511315356162600273440ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "../cmdline.hpp" namespace http_invalid_request_line { #define USAGE \ "usage: measurement_kit [options] http_invalid_request_line\n" \ " [-b backend_hostname] [-p port]" int main(std::list> &initializers, int argc, char **argv) { std::string backend_hostname; std::string backend_port; mk::nettests::HttpInvalidRequestLineTest test; for (int ch; (ch = getopt(argc, argv, "b:p:")) != -1;) { switch (ch) { case 'b': backend_hostname = optarg; break; case 'p': backend_port = optarg; break; default: fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } } argc -= optind, argv += optind; if (argc != 0) { fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } if (backend_hostname != "") { std::string backend = backend_hostname; if (backend_port != "") { backend += ":"; backend += backend_port; } test.set_options("backend", backend); } common_init(initializers, test).run(); return 0; } } // namespace http_invalid_request_line measurement-kit-0.7.1/src/measurement_kit/cmd/meek_fronted_requests.cpp000066400000000000000000000022231315356162600264670ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "../cmdline.hpp" namespace meek_fronted_requests { #define USAGE \ "usage: measurement_kit [options] meek_fronted_requests\n" \ " [-B expected_body] -f input_file\n" int main(std::list> &initializers, int argc, char **argv) { mk::nettests::MeekFrontedRequestsTest test; int ch; while ((ch = getopt(argc, argv, "B:f:")) != -1) { switch (ch) { case 'B': test.set_options("expected_body", optarg); break; case 'f': test.add_input_filepath(optarg); break; default: fprintf(stderr, "%s\n", USAGE); exit(1); } } argc -= optind, argv += optind; if (argc != 0) { fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } common_init(initializers, test).run(); return 0; } } // namespace meek_fronted_requests measurement-kit-0.7.1/src/measurement_kit/cmd/multi_ndt.cpp000066400000000000000000000061471315356162600241020ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "../cmdline.hpp" #include #include namespace multi_ndt { #define USAGE \ "usage: measurement_kit [options] multi_ndt [-u] [-m metro]\n" int main(std::list> &initializers, int argc, char **argv) { MultiNdtTest test; for (int ch; (ch = getopt(argc, argv, "m:u")) != -1;) { switch (ch) { case 'm': test.set_options("mlabns/policy", "metro"); test.set_options("mlabns/metro", optarg); break; case 'u': // By default only the download phase is performed test.set_options("single_test_suite", MK_NDT_DOWNLOAD | MK_NDT_UPLOAD); break; default: fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } } argc -= optind, argv += optind; if (argc != 0) { fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } ndt_init(initializers, test.on_entry([](std::string s) { // Note: `on_entry()` filters all exceptions on our behalf nlohmann::json doc = nlohmann::json::parse(s); auto simple = doc["test_keys"]["simple"]; printf("\nTest summary\n"); printf("------------\n"); std::string fastest = simple["fastest_test"]; double download = simple["download"]; double ping = simple["ping"]; printf("Fastest test: %s\n", fastest.c_str()); printf("Download speed: %.2f kbit/s\n", download); printf("Ping: %.2f ms\n", ping); printf("\nAdvanced info (from single stream test)\n"); printf("---------------------------------------\n"); auto adv = doc["test_keys"]["advanced"]; double AvgRTT = adv["avg_rtt"]; double MinRTT = adv["min_rtt"]; double MaxRTT = adv["max_rtt"]; printf("RTT (avg/min/max): %.1f/%.1f/%.1f ms\n", AvgRTT, MinRTT, MaxRTT); double CongestionLimited = adv["congestion_limited"]; double ReceiverLimited = adv["receiver_limited"]; double SenderLimited = adv["sender_limited"]; printf("Limited (congestion/receiver/sender): %.2f/%.2f/%.2f\n", CongestionLimited, ReceiverLimited, SenderLimited); double OutOfOrder = adv["out_of_order"]; printf("OutOfOrder: %lf (%.3lf%%)\n", OutOfOrder, OutOfOrder * 100.0); unsigned long MSS = adv["mss"]; printf("MSS: %lu byte\n", MSS); unsigned long FastRetran = adv["fast_retran"]; unsigned long Timeouts = adv["timeouts"]; printf("Congestion: FastRetran: %lu; Timeo: %lu\n", FastRetran, Timeouts); double PacketLoss = adv["packet_loss"]; printf("Loss: %lf (%.3lf%%)\n", PacketLoss, PacketLoss * 100.0); printf("\n"); })).run(); return 0; } } // namespace multi_ndt measurement-kit-0.7.1/src/measurement_kit/cmd/ndt.cpp000066400000000000000000000076011315356162600226640ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "../cmdline.hpp" #include #include namespace ndt { #define USAGE \ "usage: measurement_kit [options] ndt [-m metro] [-N tool] [-p port]\n" \ " [-T phase] [host]\n" \ "\n" \ "Available tool names for mlab-ns: ndt, neubot (default: ndt)\n" \ "Available phases: download, download-ext, none, upload\n" \ " (default: -T download -T upload)\n" int main(std::list> &initializers, int argc, char **argv) { NdtTest test; int test_suite = 0; int use_default_test_suite = true; for (int ch; (ch = getopt(argc, argv, "m:N:p:T:")) != -1;) { switch (ch) { case 'm': test.set_options("mlabns/policy", "metro"); test.set_options("mlabns/metro", optarg); break; case 'N': test.set_options("mlabns_tool_name", optarg); break; case 'p': test.set_options("port", optarg); break; case 'T': use_default_test_suite = false; if (strcmp(optarg, "download") == 0) { test_suite |= MK_NDT_DOWNLOAD; } else if (strcmp(optarg, "download-ext") == 0) { test_suite |= MK_NDT_DOWNLOAD_EXT; } else if (strcmp(optarg, "none") == 0) { test_suite = 0; } else if (strcmp(optarg, "upload") == 0) { test_suite |= MK_NDT_UPLOAD; } else { fprintf(stderr, "invalid parameter for -T option: %s", optarg); exit(1); } break; default: fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } } argc -= optind, argv += optind; if (argc > 1) { fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } // If the user expressed preference force test suite, otherwise the // code would use the default test suite (download|upload). if (!use_default_test_suite) { test.set_options("test_suite", test_suite); } if (argc == 1) { test.set_options("address", argv[0]); } ndt_init(initializers, test) .on_entry([](std::string s) { nlohmann::json doc = nlohmann::json::parse(s); auto simple = doc["test_keys"]["simple"]; auto advanced = doc["test_keys"]["advanced"]; printf("\nTest summary\n"); printf("------------\n"); double download = simple["download"]; double upload = simple["upload"]; printf("Upload speed: %.2f kbit/s\n", upload); printf("Download speed: %.2f kbit/s\n", download); double packet_loss = advanced["packet_loss"]; double out_of_order = advanced["out_of_order"]; double max_rtt = advanced["max_rtt"]; double avg_rtt = advanced["avg_rtt"]; double min_rtt = advanced["min_rtt"]; long mss = advanced["mss"]; long timeouts = advanced["timeouts"]; printf("Packet loss rate: %.2f%%\n", packet_loss * 100.0); printf("Out of order: %.2f%%\n", out_of_order * 100.0); printf("RTT (min/avg/max): %.2f/%.2f/%.2f ms\n", min_rtt, avg_rtt, max_rtt); printf("MSS: %ld\n", mss); printf("Timeouts: %ld\n", timeouts); printf("\n"); }) .run(); return 0; } } // namespace ndt measurement-kit-0.7.1/src/measurement_kit/cmd/tcp_connect.cpp000066400000000000000000000017771315356162600244060ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "../cmdline.hpp" namespace tcp_connect { #define USAGE \ "usage: measurement_kit [options] tcp_connect [-f input_file]" int main(std::list> &initializers, int argc, char **argv) { mk::nettests::TcpConnectTest test; for (int ch; (ch = getopt(argc, argv, "f:")) != -1;) { switch (ch) { case 'f': test.add_input_filepath(optarg); break; default: fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } } argc -= optind, argv += optind; if (argc != 0) { fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } common_init(initializers, test).run(); return 0; } } // namespace tcp_connect measurement-kit-0.7.1/src/measurement_kit/cmd/web_connectivity.cpp000066400000000000000000000025401315356162600254470ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #include "../cmdline.hpp" namespace web_connectivity { #define USAGE \ "usage: measurement_kit [options] web_connectivity [-b backend]\n" \ " [-f input_file] [-t timeout] [-u url]\n" int main(std::list> &initializers, int argc, char **argv) { mk::nettests::WebConnectivityTest test; for (int ch; (ch = getopt(argc, argv, "b:f:t:u:")) != -1;) { switch (ch) { case 'b': test.set_options("backend", optarg); break; case 'f': test.add_input_filepath(optarg); break; case 't': test.set_options("max_runtime", optarg); break; case 'u': test.add_input(optarg); break; default: fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } } argc -= optind, argv += optind; if (argc != 0) { fprintf(stderr, "%s\n", USAGE); exit(1); /* NOTREACHED */ } common_init(initializers, test).run(); return 0; } } // namespace web_connectivity measurement-kit-0.7.1/src/measurement_kit/cmdline.hpp000066400000000000000000000045761315356162600227640ustar00rootroot00000000000000// Part of measurement-kit . // Measurement-kit is free software. See AUTHORS and LICENSE for more // information on the copying conditions. #ifndef SRC_MEASUREMENT_KIT_CMDLINE_HPP #define SRC_MEASUREMENT_KIT_CMDLINE_HPP #include #include #include "portable/err.h" #include "portable/getopt.h" #include "portable/unistd.h" using namespace mk; using namespace mk::nettests; #define MK_CMDLINE_SUBCOMMANDS \ XX(dash) \ XX(dns_injection) \ XX(http_header_field_manipulation) \ XX(http_invalid_request_line) \ XX(meek_fronted_requests) \ XX(multi_ndt) \ XX(ndt) \ XX(tcp_connect) \ XX(web_connectivity) #define XX(_namespace_) \ namespace _namespace_ { \ int main(std::list> &initializers, int argc, \ char **argv); \ } MK_CMDLINE_SUBCOMMANDS #undef XX BaseTest &common_init(std::list>, BaseTest &); BaseTest &ndt_init(std::list>, BaseTest &); class OptionSpec { public: OptionSpec(int short_name, const char *long_name, bool requires_argument, const char *argument_name, const char *description) : short_name(short_name), long_name(long_name), requires_argument(requires_argument), argument_name(argument_name), description(description) {} int short_name = 0; const char *long_name = nullptr; bool requires_argument = false; const char *argument_name = nullptr; const char *description = nullptr; }; std::vector