From bc1cb0b00374ffc0cea8addf5246f332076030c5 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 10:07:43 +0300 Subject: [PATCH 01/39] Delete all extra classes --- project/headers/ChatRoom.h | 27 --------------------------- project/headers/MongoConnector.h | 28 ---------------------------- project/headers/RoomManager.h | 26 -------------------------- project/src/ChatRoom.cpp | 4 ---- project/src/MongoConnector.cpp | 4 ---- project/src/RoomManager.cpp | 4 ---- 6 files changed, 93 deletions(-) delete mode 100644 project/headers/ChatRoom.h delete mode 100644 project/headers/MongoConnector.h delete mode 100644 project/headers/RoomManager.h delete mode 100644 project/src/ChatRoom.cpp delete mode 100644 project/src/MongoConnector.cpp delete mode 100644 project/src/RoomManager.cpp diff --git a/project/headers/ChatRoom.h b/project/headers/ChatRoom.h deleted file mode 100644 index 92beefb..0000000 --- a/project/headers/ChatRoom.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Created by ivan on 4/15/20. -// - -#ifndef CODESHARE_CHATROOM_H -#define CODESHARE_CHATROOM_H - -#include - -#include - -class ChatRoom { -public: - ChatRoom(); - std::string getText(); - std::string addUser(); - -private: - std::string sharedText; - bool createDbTask(); - -protected: - std::string roomUUID; - -}; - -#endif //CODESHARE_CHATROOM_H diff --git a/project/headers/MongoConnector.h b/project/headers/MongoConnector.h deleted file mode 100644 index a0d6baa..0000000 --- a/project/headers/MongoConnector.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Created by ivan on 4/15/20. -// - -#ifndef CODESHARE_MONGOCONNECTOR_H -#define CODESHARE_MONGOCONNECTOR_H - -#include - -class MongoConnector { -public: - MongoConnector(std::string db, std::string coll) : dbName(db), collName(coll); - std::string getCurrText(); - bool saveDiff(); - -private: - std::string dbName; - std::string collName; - - mongocxx::instance instance; - mongocxx::client client; - mongocxx::database database; - mongocxx::collection collection; - - bool createTextTable(std::string tableName); -}; - -#endif //CODESHARE_MONGOCONNECTOR_H diff --git a/project/headers/RoomManager.h b/project/headers/RoomManager.h deleted file mode 100644 index c7fd552..0000000 --- a/project/headers/RoomManager.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Created by ivan on 4/15/20. -// - -#ifndef CODESHARE_ROOMMANAGER_H -#define CODESHARE_ROOMMANAGER_H - -#include -#include - -#include - - -class RoomManager { -public: - RoomManager(); - ChatRoom* createRoom(); - ChatRoom* getRoom(int id); - bool connectToRoom(int id); - void deleteRoom(int id); - -private: - std::vector roomsContainer; -}; - -#endif //CODESHARE_ROOMMANAGER_H diff --git a/project/src/ChatRoom.cpp b/project/src/ChatRoom.cpp deleted file mode 100644 index 4a9a025..0000000 --- a/project/src/ChatRoom.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// -// Created by ivan on 4/15/20. -// - diff --git a/project/src/MongoConnector.cpp b/project/src/MongoConnector.cpp deleted file mode 100644 index 4a9a025..0000000 --- a/project/src/MongoConnector.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// -// Created by ivan on 4/15/20. -// - diff --git a/project/src/RoomManager.cpp b/project/src/RoomManager.cpp deleted file mode 100644 index 4a9a025..0000000 --- a/project/src/RoomManager.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// -// Created by ivan on 4/15/20. -// - From 9557d52d79af1e2c5b5c3330013378140b54e193 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 10:28:52 +0300 Subject: [PATCH 02/39] Add gitignore to project --- .gitignore | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a2be81 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# macOS files +.DS_Store + +# build folder +/build \ No newline at end of file From 860a28b0e5153a071e02dc620faa28f84fcdfa53 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 10:29:36 +0300 Subject: [PATCH 03/39] Create class Acceptor to make mock tests --- project/headers/Acceptor.hpp | 18 ++++++++++++++++++ project/src/Acceptor.cpp | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 project/headers/Acceptor.hpp create mode 100644 project/src/Acceptor.cpp diff --git a/project/headers/Acceptor.hpp b/project/headers/Acceptor.hpp new file mode 100644 index 0000000..ee67339 --- /dev/null +++ b/project/headers/Acceptor.hpp @@ -0,0 +1,18 @@ +#ifndef PROJECT_INCLUDE_ACCEPTOR_H_ +#define PROJECT_INCLUDE_ACCEPTOR_H_ + +#include + +class Acceptor { +public: + Acceptor(); + virtual ~Acceptor() = default; + virtual void open(); + virtual void close(); + virtual void listen(); + virtual void setOption(); +private: + int state; +}; + +#endif // PROJECT_INCLUDE_ACCEPTOR_H_ \ No newline at end of file diff --git a/project/src/Acceptor.cpp b/project/src/Acceptor.cpp new file mode 100644 index 0000000..d4f6129 --- /dev/null +++ b/project/src/Acceptor.cpp @@ -0,0 +1,18 @@ +#include "Acceptor.hpp" + + Acceptor::Acceptor() { + state = 0; + } + + void Acceptor::open() { + std::cout << "open" << std::endl; + } + void Acceptor::close() { + std::cout << "close" << std::endl; + } + void Acceptor::listen() { + std::cout << "listen" << std::endl; + } + void Acceptor::setOption() { + std::cout << "setOption" << std::endl; + } \ No newline at end of file From de5bcc4237f742da286efc2e1bb62ced7a1fe447 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 10:29:52 +0300 Subject: [PATCH 04/39] add file with mock tests --- project/tests/mock_tests.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 project/tests/mock_tests.cpp diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp new file mode 100644 index 0000000..b0e3a7a --- /dev/null +++ b/project/tests/mock_tests.cpp @@ -0,0 +1,8 @@ +#include +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +int main(int argc, char** argv) { + ::testing::InitGoogleMock(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file From bd293625dc64aeca8cab7fa0c9ee1b10ae9e1a4f Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 10:30:19 +0300 Subject: [PATCH 05/39] change CMakeLists to work with Acceptor and GMock --- CMakeLists.txt | 18 +++++--- project/tests/CMakeLists.txt | 90 ++++++++++++++++++++++++++++++------ 2 files changed, 89 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c52c2c9..b8bd901 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,16 +2,22 @@ cmake_minimum_required(VERSION 3.11) project(CodeShare) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror=pedantic") -set(CMAKE_C_STANDARD 99) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++0x -Wall -ggdb3") include_directories(project/headers) +set(LIB_SOURCE_FILES + project/src/Acceptor.cpp +) + +add_library(project_lib STATIC ${LIB_SOURCE_FILES}) + enable_testing() -add_executable(CodeShare project/src/main.cpp - project/src/ChatRoom.cpp project/headers/ChatRoom.h - project/src/RoomManager.cpp project/headers/RoomManager.h - project/src/MongoConnector.cpp project/headers/MongoConnector.h) +add_executable(CodeShare project/src/main.cpp) + +target_link_libraries(CodeShare project_lib) add_subdirectory(project/tests) diff --git a/project/tests/CMakeLists.txt b/project/tests/CMakeLists.txt index 5426f1c..0e31f36 100644 --- a/project/tests/CMakeLists.txt +++ b/project/tests/CMakeLists.txt @@ -1,26 +1,90 @@ cmake_minimum_required(VERSION 3.11) - project(test) -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_C_STANDARD 99) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++0x -Wall -ggdb3") - find_package(GTest REQUIRED) find_package(Threads REQUIRED) include_directories("${GTEST_INCLUDE_DIRS}") -add_executable(Tests - ../src/ChatRoom.cpp - ../src/RoomManager.cpp - ../src/MongoConnector.cpp - ) +# The code below is taken on the Internet to find the GMock +# it's the only way I can solve my problem + +function(_gmock_append_debugs _endvar _library) + if(${_library} AND ${_library}_DEBUG) + set(_output optimized ${${_library}} debug ${${_library}_DEBUG}) + else() + set(_output ${${_library}}) + endif() + set(${_endvar} ${_output} PARENT_SCOPE) +endfunction() + +function(_gmock_find_library _name) + find_library(${_name} + NAMES ${ARGN} + HINTS + $ENV{GMOCK_ROOT} + ${GMOCK_ROOT} + PATH_SUFFIXES ${_gmock_libpath_suffixes} + ) + mark_as_advanced(${_name}) +endfunction() + + +if(NOT DEFINED GMOCK_MSVC_SEARCH) + set(GMOCK_MSVC_SEARCH MD) +endif() + +set(_gmock_libpath_suffixes lib) +if(MSVC) + if(GMOCK_MSVC_SEARCH STREQUAL "MD") + list(APPEND _gmock_libpath_suffixes + msvc/gmock-md/Debug + msvc/gmock-md/Release) + elseif(GMOCK_MSVC_SEARCH STREQUAL "MT") + list(APPEND _gmock_libpath_suffixes + msvc/gmock/Debug + msvc/gmock/Release) + endif() +endif() + +find_path(GMOCK_INCLUDE_DIR gmock/gmock.h + HINTS + $ENV{GMOCK_ROOT}/include + ${GMOCK_ROOT}/include +) +mark_as_advanced(GMOCK_INCLUDE_DIR) + +if(MSVC AND GMOCK_MSVC_SEARCH STREQUAL "MD") + # The provided /MD project files for Google Mock add -md suffixes to the + # library names. + _gmock_find_library(GMOCK_LIBRARY gmock-md gmock) + _gmock_find_library(GMOCK_LIBRARY_DEBUG gmock-mdd gmockd) + _gmock_find_library(GMOCK_MAIN_LIBRARY gmock_main-md gmock_main) + _gmock_find_library(GMOCK_MAIN_LIBRARY_DEBUG gmock_main-mdd gmock_maind) +else() + _gmock_find_library(GMOCK_LIBRARY gmock) + _gmock_find_library(GMOCK_LIBRARY_DEBUG gmockd) + _gmock_find_library(GMOCK_MAIN_LIBRARY gmock_main) + _gmock_find_library(GMOCK_MAIN_LIBRARY_DEBUG gmock_maind) +endif() + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMock DEFAULT_MSG GMOCK_LIBRARY GMOCK_INCLUDE_DIR GMOCK_MAIN_LIBRARY) + +if(GMOCK_FOUND) + set(GMOCK_INCLUDE_DIRS ${GMOCK_INCLUDE_DIR}) + _gmock_append_debugs(GMOCK_LIBRARIES GMOCK_LIBRARY) + _gmock_append_debugs(GMOCK_MAIN_LIBRARIES GMOCK_MAIN_LIBRARY) + set(GMOCK_BOTH_LIBRARIES ${GMOCK_LIBRARIES} ${GMOCK_MAIN_LIBRARIES}) +endif() + +# end of search code + +add_executable(tests mock_tests.cpp) -set_target_properties(Tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") +set_target_properties(tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") -target_link_libraries(Tests ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} pc_catalog) +target_link_libraries(tests ${GTEST_BOTH_LIBRARIES} ${GMOCK_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(tests project_lib) add_test( NAME BaseTest From 290fd43ec9f3dc6eeaa3d1b19842e47ccb5ae5bd Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 14:34:01 +0300 Subject: [PATCH 06/39] add empty class Server --- CMakeLists.txt | 7 +++++-- project/headers/Server.hpp | 22 ++++++++++++++++++++++ project/src/Acceptor.cpp | 31 ++++++++++++++++--------------- project/src/Server.cpp | 11 +++++++++++ project/tests/mock_tests.cpp | 25 +++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 project/headers/Server.hpp create mode 100644 project/src/Server.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b8bd901..f34ecf0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,15 +8,18 @@ set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++0x -Wall -ggdb3") include_directories(project/headers) +set(SOURCE_DIR project/src/) + set(LIB_SOURCE_FILES - project/src/Acceptor.cpp + ${SOURCE_DIR}Acceptor.cpp + ${SOURCE_DIR}Server.cpp ) add_library(project_lib STATIC ${LIB_SOURCE_FILES}) enable_testing() -add_executable(CodeShare project/src/main.cpp) +add_executable(CodeShare ${SOURCE_DIR}main.cpp) target_link_libraries(CodeShare project_lib) diff --git a/project/headers/Server.hpp b/project/headers/Server.hpp new file mode 100644 index 0000000..0291909 --- /dev/null +++ b/project/headers/Server.hpp @@ -0,0 +1,22 @@ +#ifndef PROJECT_INCLUDE_SERVER_H_ +#define PROJECT_INCLUDE_SERVER_H_ + +#include +#include "Acceptor.hpp" + +template +class Server { +public: + Server(T* acceptor) { + acceptor_ = acceptor; + } + void run() { + acceptor_->setOption(0); + acceptor_->open(); + acceptor_->listen(); + } +private: + T* acceptor_; +}; + +#endif // PROJECT_INCLUDE_SERVER_H_ \ No newline at end of file diff --git a/project/src/Acceptor.cpp b/project/src/Acceptor.cpp index d4f6129..bd1e7a4 100644 --- a/project/src/Acceptor.cpp +++ b/project/src/Acceptor.cpp @@ -1,18 +1,19 @@ #include "Acceptor.hpp" - Acceptor::Acceptor() { - state = 0; - } +Acceptor::Acceptor() { + state = 0; +} - void Acceptor::open() { - std::cout << "open" << std::endl; - } - void Acceptor::close() { - std::cout << "close" << std::endl; - } - void Acceptor::listen() { - std::cout << "listen" << std::endl; - } - void Acceptor::setOption() { - std::cout << "setOption" << std::endl; - } \ No newline at end of file +void Acceptor::open() { + std::cout << "open" << std::endl; +} + +void Acceptor::close() { + std::cout << "close" << std::endl; +} +void Acceptor::listen() { + std::cout << "listen" << std::endl; +} +void Acceptor::setOption(int option) { + std::cout << "option is " << option << std::endl; +} \ No newline at end of file diff --git a/project/src/Server.cpp b/project/src/Server.cpp new file mode 100644 index 0000000..d720302 --- /dev/null +++ b/project/src/Server.cpp @@ -0,0 +1,11 @@ +#include "Server.hpp" + +// template +// Server::Server(T* acceptor) { +// acceptor_ = acceptor; +// } + +// template +// void Server::run() { +// acceptor_->open(); +// } \ No newline at end of file diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index b0e3a7a..dbaec16 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -1,6 +1,31 @@ #include #include "gtest/gtest.h" #include "gmock/gmock.h" +#include "Acceptor.hpp" +#include "Server.hpp" + +using ::testing::AtLeast; +using ::testing::DoAll; +using ::testing::Return; +using ::testing::SetArgReferee; + +class MockAcceptor : public Acceptor { +public: + MOCK_METHOD1(setOption, bool(int option)); + MOCK_METHOD0(open, void()); + MOCK_METHOD0(listen, void()); +}; + +TEST(ServerTest, runWithOpen) { + MockAcceptor acceptor; + int option = 0; + EXPECT_CALL(acceptor, setOption(option)).Times(AtLeast(1)); + EXPECT_CALL(acceptor, open()).Times(AtLeast(1)); + EXPECT_CALL(acceptor, listen()).Times(AtLeast(1)); + + Server server(&acceptor); + server.run(); +} int main(int argc, char** argv) { ::testing::InitGoogleMock(&argc, argv); From 4f3aa6ffd8b6dba3ae20893c1b1d25f82ff71d11 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 14:34:24 +0300 Subject: [PATCH 07/39] Change Acceptors functions --- project/headers/Acceptor.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/project/headers/Acceptor.hpp b/project/headers/Acceptor.hpp index ee67339..662d7bd 100644 --- a/project/headers/Acceptor.hpp +++ b/project/headers/Acceptor.hpp @@ -6,11 +6,10 @@ class Acceptor { public: Acceptor(); - virtual ~Acceptor() = default; - virtual void open(); - virtual void close(); - virtual void listen(); - virtual void setOption(); + void open(); + void close(); + void listen(); + void setOption(int option); private: int state; }; From 10b48d30835a48a7767f7c5d1c64429a462a0267 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 14:48:37 +0300 Subject: [PATCH 08/39] Change T for AcceptorType --- project/headers/Server.hpp | 8 +++----- project/tests/mock_tests.cpp | 1 + 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/project/headers/Server.hpp b/project/headers/Server.hpp index 0291909..acf85c5 100644 --- a/project/headers/Server.hpp +++ b/project/headers/Server.hpp @@ -4,19 +4,17 @@ #include #include "Acceptor.hpp" -template +template class Server { public: - Server(T* acceptor) { - acceptor_ = acceptor; - } + Server(AcceptorType* acceptor) : acceptor_(acceptor) {} void run() { acceptor_->setOption(0); acceptor_->open(); acceptor_->listen(); } private: - T* acceptor_; + AcceptorType* acceptor_; }; #endif // PROJECT_INCLUDE_SERVER_H_ \ No newline at end of file diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index dbaec16..e8793b7 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -1,6 +1,7 @@ #include #include "gtest/gtest.h" #include "gmock/gmock.h" + #include "Acceptor.hpp" #include "Server.hpp" From a9dd6c80843ba1865a8131d9a113ce22cb343e01 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 16:08:15 +0300 Subject: [PATCH 09/39] Add class Connection for communicating between clien and server --- CMakeLists.txt | 1 + project/headers/Connection.hpp | 18 ++++++++++++++++++ project/src/Connection.cpp | 19 +++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 project/headers/Connection.hpp create mode 100644 project/src/Connection.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f34ecf0..43ee3e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCE_DIR project/src/) set(LIB_SOURCE_FILES ${SOURCE_DIR}Acceptor.cpp ${SOURCE_DIR}Server.cpp + ${SOURCE_DIR}Connection.cpp ) add_library(project_lib STATIC ${LIB_SOURCE_FILES}) diff --git a/project/headers/Connection.hpp b/project/headers/Connection.hpp new file mode 100644 index 0000000..7b5801b --- /dev/null +++ b/project/headers/Connection.hpp @@ -0,0 +1,18 @@ +#ifndef PROJECT_INCLUDE_CONNECTION_H_ +#define PROJECT_INCLUDE_CONNECTION_H_ + +#include +#include + +class Connection { +public: + Connection(); + void start(); + void stop(); +private: + std::vector buffer; + void read(); + void write(); +}; + +#endif // PROJECT_INCLUDE_CONNECTION_H_ \ No newline at end of file diff --git a/project/src/Connection.cpp b/project/src/Connection.cpp new file mode 100644 index 0000000..248dc01 --- /dev/null +++ b/project/src/Connection.cpp @@ -0,0 +1,19 @@ +#include "Connection.hpp" + +Connection::Connection() {} + +void Connection::start() { + std::cout << "start" << std::endl; +} + +void Connection::stop() { + std::cout << "stop" << std::endl; +} + +void Connection::read() { + std::cout << "read" << std::endl; +} + +void Connection::write() { + std::cout << "write" << std::endl; +} \ No newline at end of file From c35c4acde2541f5280f49a65d5ebdd2403357f83 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 16:08:52 +0300 Subject: [PATCH 10/39] Add ConnectioManager to manage clients connection --- CMakeLists.txt | 1 + project/headers/ConnectionManager.hpp | 26 ++++++++++++++++++++++++++ project/src/ConnectionManager.cpp | 2 ++ 3 files changed, 29 insertions(+) create mode 100644 project/headers/ConnectionManager.hpp create mode 100644 project/src/ConnectionManager.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 43ee3e9..1d1df41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ set(LIB_SOURCE_FILES ${SOURCE_DIR}Acceptor.cpp ${SOURCE_DIR}Server.cpp ${SOURCE_DIR}Connection.cpp + ${SOURCE_DIR}ConnectionManager.cpp ) add_library(project_lib STATIC ${LIB_SOURCE_FILES}) diff --git a/project/headers/ConnectionManager.hpp b/project/headers/ConnectionManager.hpp new file mode 100644 index 0000000..45f8616 --- /dev/null +++ b/project/headers/ConnectionManager.hpp @@ -0,0 +1,26 @@ +#ifndef PROJECT_INCLUDE_CONNECTION_MANAGER_H_ +#define PROJECT_INCLUDE_CONNECTION_MANAGER_H_ + +#include +#include + +template +class ConnectionManager { +public: + ConnectionManager() {} + void start(ConnectionType* connection) { + connection->start(); + } + void stop(ConnectionType* connection) { + connection->stop(); + } + void stopAll() { + for (size_t i = 0; i < connections.size(); i++) { + connections[i].stop(); + } + } +private: + std::vector connections; +}; + +#endif // PROJECT_INCLUDE_CONNECTION_MANAGER_H_ \ No newline at end of file diff --git a/project/src/ConnectionManager.cpp b/project/src/ConnectionManager.cpp new file mode 100644 index 0000000..12acf98 --- /dev/null +++ b/project/src/ConnectionManager.cpp @@ -0,0 +1,2 @@ +#include "ConnectionManager.hpp" + From 5aa32a555b20b7580fa404999e463f1573f829cb Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 16:09:14 +0300 Subject: [PATCH 11/39] Add tests for ConnectionManager --- project/tests/mock_tests.cpp | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index e8793b7..5b194ff 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -4,6 +4,8 @@ #include "Acceptor.hpp" #include "Server.hpp" +#include "Connection.hpp" +#include "ConnectionManager.hpp" using ::testing::AtLeast; using ::testing::DoAll; @@ -12,12 +14,12 @@ using ::testing::SetArgReferee; class MockAcceptor : public Acceptor { public: - MOCK_METHOD1(setOption, bool(int option)); + MOCK_METHOD1(setOption, void(int option)); MOCK_METHOD0(open, void()); MOCK_METHOD0(listen, void()); }; -TEST(ServerTest, runWithOpen) { +TEST(ServerTest, runCallOpen) { MockAcceptor acceptor; int option = 0; EXPECT_CALL(acceptor, setOption(option)).Times(AtLeast(1)); @@ -28,6 +30,28 @@ TEST(ServerTest, runWithOpen) { server.run(); } +class MockConnection : public Connection { +public: + MOCK_METHOD0(start, void()); + MOCK_METHOD0(stop, void()); +}; + +TEST(ConnectionManagerTest, startCallConnectionStart) { + MockConnection connection; + EXPECT_CALL(connection, start()).Times(AtLeast(1)); + + ConnectionManager manager; + manager.start(&connection); +} + +TEST(ConnectionManagerTest, stopCallConnectionStop) { + MockConnection connection; + EXPECT_CALL(connection, stop()).Times(AtLeast(1)); + + ConnectionManager manager; + manager.stop(&connection); +} + int main(int argc, char** argv) { ::testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); From 1eeaeeaf1e5ce99e4a7ee4fd9bb8632c90df6868 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 17:31:51 +0300 Subject: [PATCH 12/39] Add RequestHandler class to handler client's requests --- CMakeLists.txt | 6 ++++++ project/headers/RequestHandler.hpp | 13 +++++++++++++ project/src/Connection.cpp | 2 +- project/src/RequestHandler.cpp | 7 +++++++ project/tests/mock_tests.cpp | 1 + 5 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 project/headers/RequestHandler.hpp create mode 100644 project/src/RequestHandler.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d1df41..4bbf0fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,11 @@ set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++0x -Wall -ggdb3") +if (APPLE) + set(CMAKE_CXX_ARCHIVE_CREATE " Scr ") + set(CMAKE_CXX_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") +endif() + include_directories(project/headers) set(SOURCE_DIR project/src/) @@ -15,6 +20,7 @@ set(LIB_SOURCE_FILES ${SOURCE_DIR}Server.cpp ${SOURCE_DIR}Connection.cpp ${SOURCE_DIR}ConnectionManager.cpp + ${SOURCE_DIR}RequestHandler.cpp ) add_library(project_lib STATIC ${LIB_SOURCE_FILES}) diff --git a/project/headers/RequestHandler.hpp b/project/headers/RequestHandler.hpp new file mode 100644 index 0000000..3de1816 --- /dev/null +++ b/project/headers/RequestHandler.hpp @@ -0,0 +1,13 @@ +#ifndef PROJECT_INCLUDE_REQUEST_HANDLER_H_ +#define PROJECT_INCLUDE_REQUEST_HANDLER_H_ + +#include +#include + +class RequestHandler { +public: + RequestHandler(); + void handleRequest(); +}; + +#endif // PROJECT_INCLUDE_REQUEST_HANDLER_H_ \ No newline at end of file diff --git a/project/src/Connection.cpp b/project/src/Connection.cpp index 248dc01..8bfac85 100644 --- a/project/src/Connection.cpp +++ b/project/src/Connection.cpp @@ -1,6 +1,6 @@ #include "Connection.hpp" -Connection::Connection() {} +Connection::Connection() = default; void Connection::start() { std::cout << "start" << std::endl; diff --git a/project/src/RequestHandler.cpp b/project/src/RequestHandler.cpp new file mode 100644 index 0000000..c31e540 --- /dev/null +++ b/project/src/RequestHandler.cpp @@ -0,0 +1,7 @@ +#include "RequestHandler.hpp" + +RequestHandler::RequestHandler() = default; + +void RequestHandler::handleRequest() { + std::cout << "handleRequest" << std::endl; +} \ No newline at end of file diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index 5b194ff..01ce31e 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -6,6 +6,7 @@ #include "Server.hpp" #include "Connection.hpp" #include "ConnectionManager.hpp" +#include "RequestHandler.hpp" using ::testing::AtLeast; using ::testing::DoAll; From 14a46e0c90984bf0aa88be4b906b0789e4c1b9ad Mon Sep 17 00:00:00 2001 From: aanufriev Date: Wed, 15 Apr 2020 17:51:22 +0300 Subject: [PATCH 13/39] Modify connection --- project/headers/Connection.hpp | 4 +++- project/headers/RequestHandler.hpp | 2 +- project/src/Connection.cpp | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/project/headers/Connection.hpp b/project/headers/Connection.hpp index 7b5801b..479c5be 100644 --- a/project/headers/Connection.hpp +++ b/project/headers/Connection.hpp @@ -1,16 +1,18 @@ #ifndef PROJECT_INCLUDE_CONNECTION_H_ #define PROJECT_INCLUDE_CONNECTION_H_ +#include "RequestHandler.hpp" #include #include class Connection { public: - Connection(); + Connection(RequestHandler handler = RequestHandler()); void start(); void stop(); private: std::vector buffer; + RequestHandler requestHandler; void read(); void write(); }; diff --git a/project/headers/RequestHandler.hpp b/project/headers/RequestHandler.hpp index 3de1816..cbd4d08 100644 --- a/project/headers/RequestHandler.hpp +++ b/project/headers/RequestHandler.hpp @@ -7,7 +7,7 @@ class RequestHandler { public: RequestHandler(); - void handleRequest(); + virtual void handleRequest(); }; #endif // PROJECT_INCLUDE_REQUEST_HANDLER_H_ \ No newline at end of file diff --git a/project/src/Connection.cpp b/project/src/Connection.cpp index 8bfac85..d097ce1 100644 --- a/project/src/Connection.cpp +++ b/project/src/Connection.cpp @@ -1,6 +1,6 @@ #include "Connection.hpp" -Connection::Connection() = default; +Connection::Connection(RequestHandler handler) : requestHandler(handler) {} void Connection::start() { std::cout << "start" << std::endl; @@ -12,6 +12,7 @@ void Connection::stop() { void Connection::read() { std::cout << "read" << std::endl; + requestHandler.handleRequest(); } void Connection::write() { From ccf6bc0024c21f83490116c1057848411fd8b16b Mon Sep 17 00:00:00 2001 From: aanufriev Date: Fri, 17 Apr 2020 13:36:50 +0300 Subject: [PATCH 14/39] Function handleRequest non-virtual now --- project/headers/RequestHandler.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/headers/RequestHandler.hpp b/project/headers/RequestHandler.hpp index cbd4d08..3de1816 100644 --- a/project/headers/RequestHandler.hpp +++ b/project/headers/RequestHandler.hpp @@ -7,7 +7,7 @@ class RequestHandler { public: RequestHandler(); - virtual void handleRequest(); + void handleRequest(); }; #endif // PROJECT_INCLUDE_REQUEST_HANDLER_H_ \ No newline at end of file From 995a8f46bfbf95fa799dcdb03a455c483f659c9d Mon Sep 17 00:00:00 2001 From: aanufriev Date: Fri, 17 Apr 2020 13:37:31 +0300 Subject: [PATCH 15/39] Add test for connection's start --- project/headers/Connection.hpp | 26 +++++++++++++++++++------- project/src/Connection.cpp | 28 ++++++++++++++-------------- project/src/Server.cpp | 8 ++++---- project/tests/mock_tests.cpp | 22 +++++++++++++++++++--- 4 files changed, 56 insertions(+), 28 deletions(-) diff --git a/project/headers/Connection.hpp b/project/headers/Connection.hpp index 479c5be..2dcd9f7 100644 --- a/project/headers/Connection.hpp +++ b/project/headers/Connection.hpp @@ -1,20 +1,32 @@ #ifndef PROJECT_INCLUDE_CONNECTION_H_ #define PROJECT_INCLUDE_CONNECTION_H_ -#include "RequestHandler.hpp" #include #include +template class Connection { public: - Connection(RequestHandler handler = RequestHandler()); - void start(); - void stop(); + Connection(HandlerType* handler) : requestHandler(handler) {} + + void start() { + read(); + } + + void stop() { + std::cout << "stop" << std::endl; + } private: std::vector buffer; - RequestHandler requestHandler; - void read(); - void write(); + HandlerType* requestHandler; + + void read() { + requestHandler->handleRequest(); + } + + void write() { + std::cout << "write" << std::endl; + } }; #endif // PROJECT_INCLUDE_CONNECTION_H_ \ No newline at end of file diff --git a/project/src/Connection.cpp b/project/src/Connection.cpp index d097ce1..9a6b677 100644 --- a/project/src/Connection.cpp +++ b/project/src/Connection.cpp @@ -1,20 +1,20 @@ #include "Connection.hpp" -Connection::Connection(RequestHandler handler) : requestHandler(handler) {} +// Connection::Connection(RequestHandler handler) : requestHandler(handler) {} -void Connection::start() { - std::cout << "start" << std::endl; -} +// void Connection::start() { +// std::cout << "start" << std::endl; +// } -void Connection::stop() { - std::cout << "stop" << std::endl; -} +// void Connection::stop() { +// std::cout << "stop" << std::endl; +// } -void Connection::read() { - std::cout << "read" << std::endl; - requestHandler.handleRequest(); -} +// void Connection::read() { +// std::cout << "read" << std::endl; +// requestHandler.handleRequest(); +// } -void Connection::write() { - std::cout << "write" << std::endl; -} \ No newline at end of file +// void Connection::write() { +// std::cout << "write" << std::endl; +// } \ No newline at end of file diff --git a/project/src/Server.cpp b/project/src/Server.cpp index d720302..9d95123 100644 --- a/project/src/Server.cpp +++ b/project/src/Server.cpp @@ -1,11 +1,11 @@ #include "Server.hpp" -// template -// Server::Server(T* acceptor) { +// template +// Server::Server(AcceptorType* acceptor) { // acceptor_ = acceptor; // } -// template -// void Server::run() { +// template +// void Server::run() { // acceptor_->open(); // } \ No newline at end of file diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index 01ce31e..2b3263d 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -31,14 +31,16 @@ TEST(ServerTest, runCallOpen) { server.run(); } -class MockConnection : public Connection { +class MockConnection : public Connection { public: + MockConnection(RequestHandler* handler): Connection(handler) {} MOCK_METHOD0(start, void()); MOCK_METHOD0(stop, void()); }; TEST(ConnectionManagerTest, startCallConnectionStart) { - MockConnection connection; + RequestHandler handler; + MockConnection connection(&handler); EXPECT_CALL(connection, start()).Times(AtLeast(1)); ConnectionManager manager; @@ -46,13 +48,27 @@ TEST(ConnectionManagerTest, startCallConnectionStart) { } TEST(ConnectionManagerTest, stopCallConnectionStop) { - MockConnection connection; + RequestHandler handler; + MockConnection connection(&handler); EXPECT_CALL(connection, stop()).Times(AtLeast(1)); ConnectionManager manager; manager.stop(&connection); } +class MockRequestHandler : public RequestHandler { +public: + MOCK_METHOD0(handleRequest, void()); +}; + +TEST(ConnectionTest, startCallHandleRequest) { + MockRequestHandler handler; + EXPECT_CALL(handler, handleRequest()).Times(AtLeast(1)); + + Connection connection(&handler); + connection.start(); +} + int main(int argc, char** argv) { ::testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); From 63fd2c7a99929b4a97343f8e49a2359c3be374e2 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Fri, 17 Apr 2020 13:39:04 +0300 Subject: [PATCH 16/39] Delete extra cpp files --- CMakeLists.txt | 3 --- project/src/Connection.cpp | 20 -------------------- project/src/ConnectionManager.cpp | 2 -- project/src/Server.cpp | 11 ----------- 4 files changed, 36 deletions(-) delete mode 100644 project/src/Connection.cpp delete mode 100644 project/src/ConnectionManager.cpp delete mode 100644 project/src/Server.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bbf0fe..b9a7525 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,9 +17,6 @@ set(SOURCE_DIR project/src/) set(LIB_SOURCE_FILES ${SOURCE_DIR}Acceptor.cpp - ${SOURCE_DIR}Server.cpp - ${SOURCE_DIR}Connection.cpp - ${SOURCE_DIR}ConnectionManager.cpp ${SOURCE_DIR}RequestHandler.cpp ) diff --git a/project/src/Connection.cpp b/project/src/Connection.cpp deleted file mode 100644 index 9a6b677..0000000 --- a/project/src/Connection.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "Connection.hpp" - -// Connection::Connection(RequestHandler handler) : requestHandler(handler) {} - -// void Connection::start() { -// std::cout << "start" << std::endl; -// } - -// void Connection::stop() { -// std::cout << "stop" << std::endl; -// } - -// void Connection::read() { -// std::cout << "read" << std::endl; -// requestHandler.handleRequest(); -// } - -// void Connection::write() { -// std::cout << "write" << std::endl; -// } \ No newline at end of file diff --git a/project/src/ConnectionManager.cpp b/project/src/ConnectionManager.cpp deleted file mode 100644 index 12acf98..0000000 --- a/project/src/ConnectionManager.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "ConnectionManager.hpp" - diff --git a/project/src/Server.cpp b/project/src/Server.cpp deleted file mode 100644 index 9d95123..0000000 --- a/project/src/Server.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "Server.hpp" - -// template -// Server::Server(AcceptorType* acceptor) { -// acceptor_ = acceptor; -// } - -// template -// void Server::run() { -// acceptor_->open(); -// } \ No newline at end of file From 08dd92fec00309104ed3a58ed6c95b489370ecdf Mon Sep 17 00:00:00 2001 From: aanufriev Date: Fri, 17 Apr 2020 15:14:12 +0300 Subject: [PATCH 17/39] Add argument to function handleRequest --- project/headers/Connection.hpp | 2 +- project/headers/RequestHandler.hpp | 2 +- project/src/RequestHandler.cpp | 2 +- project/tests/mock_tests.cpp | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/project/headers/Connection.hpp b/project/headers/Connection.hpp index 2dcd9f7..c68a9f9 100644 --- a/project/headers/Connection.hpp +++ b/project/headers/Connection.hpp @@ -21,7 +21,7 @@ class Connection { HandlerType* requestHandler; void read() { - requestHandler->handleRequest(); + requestHandler->handleRequest(0); } void write() { diff --git a/project/headers/RequestHandler.hpp b/project/headers/RequestHandler.hpp index 3de1816..bc9bae9 100644 --- a/project/headers/RequestHandler.hpp +++ b/project/headers/RequestHandler.hpp @@ -7,7 +7,7 @@ class RequestHandler { public: RequestHandler(); - void handleRequest(); + void handleRequest(int request); }; #endif // PROJECT_INCLUDE_REQUEST_HANDLER_H_ \ No newline at end of file diff --git a/project/src/RequestHandler.cpp b/project/src/RequestHandler.cpp index c31e540..d03455b 100644 --- a/project/src/RequestHandler.cpp +++ b/project/src/RequestHandler.cpp @@ -2,6 +2,6 @@ RequestHandler::RequestHandler() = default; -void RequestHandler::handleRequest() { +void RequestHandler::handleRequest(int request) { std::cout << "handleRequest" << std::endl; } \ No newline at end of file diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index 2b3263d..a016aa8 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -58,12 +58,13 @@ TEST(ConnectionManagerTest, stopCallConnectionStop) { class MockRequestHandler : public RequestHandler { public: - MOCK_METHOD0(handleRequest, void()); + MOCK_METHOD1(handleRequest, void(int request)); }; TEST(ConnectionTest, startCallHandleRequest) { MockRequestHandler handler; - EXPECT_CALL(handler, handleRequest()).Times(AtLeast(1)); + int request = 0; + EXPECT_CALL(handler, handleRequest(request)).Times(AtLeast(1)); Connection connection(&handler); connection.start(); From 14e4a8efbc87836b5c733689e10a7f67f5a1691d Mon Sep 17 00:00:00 2001 From: aanufriev Date: Fri, 17 Apr 2020 16:09:29 +0300 Subject: [PATCH 18/39] Add empty class RoomScheduler --- CMakeLists.txt | 1 + project/headers/RoomScheduler.hpp | 16 ++++++++++++++++ project/src/RoomScheduler.cpp | 11 +++++++++++ 3 files changed, 28 insertions(+) create mode 100644 project/headers/RoomScheduler.hpp create mode 100644 project/src/RoomScheduler.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b9a7525..3bfecbf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ set(SOURCE_DIR project/src/) set(LIB_SOURCE_FILES ${SOURCE_DIR}Acceptor.cpp ${SOURCE_DIR}RequestHandler.cpp + ${SOURCE_DIR}RoomScheduler.cpp ) add_library(project_lib STATIC ${LIB_SOURCE_FILES}) diff --git a/project/headers/RoomScheduler.hpp b/project/headers/RoomScheduler.hpp new file mode 100644 index 0000000..107631d --- /dev/null +++ b/project/headers/RoomScheduler.hpp @@ -0,0 +1,16 @@ +#ifndef PROJECT_INCLUDE_ROOM_SCHEDULER_H_ +#define PROJECT_INCLUDE_ROOM_SCHEDULER_H_ + +#include +#include + +class RoomScheduler { +public: + RoomScheduler(); + void createRoom(); + void getRoom(); + void connectToRoom(); + void deleteRoom(); +}; + +#endif // PROJECT_INCLUDE_ROOM_SCHEDULER_H_ \ No newline at end of file diff --git a/project/src/RoomScheduler.cpp b/project/src/RoomScheduler.cpp new file mode 100644 index 0000000..d4e2b27 --- /dev/null +++ b/project/src/RoomScheduler.cpp @@ -0,0 +1,11 @@ +#include "RoomScheduler.hpp" + +RoomScheduler::RoomScheduler() = default; + +void RoomScheduler::createRoom() {} + +void RoomScheduler::getRoom() {} + +void RoomScheduler::connectToRoom() {} + +void RoomScheduler::deleteRoom() {} \ No newline at end of file From 9f1473571fe2743a465bfb539bc6ece62ca63e64 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Fri, 17 Apr 2020 16:10:13 +0300 Subject: [PATCH 19/39] Delete RequestHandler.cpp and add realization to hpp file --- project/headers/RequestHandler.hpp | 22 +++++++++++++++++++--- project/src/RequestHandler.cpp | 7 ------- 2 files changed, 19 insertions(+), 10 deletions(-) delete mode 100644 project/src/RequestHandler.cpp diff --git a/project/headers/RequestHandler.hpp b/project/headers/RequestHandler.hpp index bc9bae9..345a5c7 100644 --- a/project/headers/RequestHandler.hpp +++ b/project/headers/RequestHandler.hpp @@ -2,12 +2,28 @@ #define PROJECT_INCLUDE_REQUEST_HANDLER_H_ #include -#include +template class RequestHandler { public: - RequestHandler(); - void handleRequest(int request); + RequestHandler(RoomSchedulerType* scheduler) : roomScheduler(scheduler) {} + void handleRequest(int request) { + switch (request) + { + case 0: + roomScheduler->createRoom(); + case 1: + roomScheduler->getRoom(); + case 2: + roomScheduler->connectToRoom(); + case 3: + roomScheduler->deleteRoom(); + default: + break; + } + } +private: + RoomSchedulerType *roomScheduler; }; #endif // PROJECT_INCLUDE_REQUEST_HANDLER_H_ \ No newline at end of file diff --git a/project/src/RequestHandler.cpp b/project/src/RequestHandler.cpp deleted file mode 100644 index d03455b..0000000 --- a/project/src/RequestHandler.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "RequestHandler.hpp" - -RequestHandler::RequestHandler() = default; - -void RequestHandler::handleRequest(int request) { - std::cout << "handleRequest" << std::endl; -} \ No newline at end of file From f77ea90ce380073939dbe3263713291b5803cef0 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Fri, 17 Apr 2020 16:10:31 +0300 Subject: [PATCH 20/39] Add RequestHandler's tests --- project/tests/mock_tests.cpp | 41 ++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index a016aa8..3b262fd 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -7,11 +7,9 @@ #include "Connection.hpp" #include "ConnectionManager.hpp" #include "RequestHandler.hpp" +#include "RoomScheduler.hpp" using ::testing::AtLeast; -using ::testing::DoAll; -using ::testing::Return; -using ::testing::SetArgReferee; class MockAcceptor : public Acceptor { public: @@ -31,15 +29,16 @@ TEST(ServerTest, runCallOpen) { server.run(); } -class MockConnection : public Connection { +class MockConnection : public Connection > { public: - MockConnection(RequestHandler* handler): Connection(handler) {} + MockConnection(RequestHandler* handler): Connection >(handler) {} MOCK_METHOD0(start, void()); MOCK_METHOD0(stop, void()); }; TEST(ConnectionManagerTest, startCallConnectionStart) { - RequestHandler handler; + RoomScheduler scheduler; + RequestHandler handler(&scheduler); MockConnection connection(&handler); EXPECT_CALL(connection, start()).Times(AtLeast(1)); @@ -48,7 +47,8 @@ TEST(ConnectionManagerTest, startCallConnectionStart) { } TEST(ConnectionManagerTest, stopCallConnectionStop) { - RequestHandler handler; + RoomScheduler scheduler; + RequestHandler handler(&scheduler); MockConnection connection(&handler); EXPECT_CALL(connection, stop()).Times(AtLeast(1)); @@ -56,13 +56,15 @@ TEST(ConnectionManagerTest, stopCallConnectionStop) { manager.stop(&connection); } -class MockRequestHandler : public RequestHandler { +class MockRequestHandler : public RequestHandler { public: + MockRequestHandler(RoomScheduler* scheduler) : RequestHandler(scheduler) {} MOCK_METHOD1(handleRequest, void(int request)); }; TEST(ConnectionTest, startCallHandleRequest) { - MockRequestHandler handler; + RoomScheduler scheduler; + MockRequestHandler handler(&scheduler); int request = 0; EXPECT_CALL(handler, handleRequest(request)).Times(AtLeast(1)); @@ -70,6 +72,27 @@ TEST(ConnectionTest, startCallHandleRequest) { connection.start(); } +class MockRoomScheduler : public RoomScheduler { +public: + MOCK_METHOD0(createRoom, void()); + MOCK_METHOD0(getRoom, void()); + MOCK_METHOD0(connectToRoom, void()); + MOCK_METHOD0(deleteRoom, void()); +}; + +TEST(RequestHandlerTest, handlerRequestCallRoomSchedulersMethods) { + MockRoomScheduler scheduler; + EXPECT_CALL(scheduler, createRoom()).Times(AtLeast(1)); + EXPECT_CALL(scheduler, getRoom()).Times(AtLeast(1)); + EXPECT_CALL(scheduler, connectToRoom()).Times(AtLeast(1)); + EXPECT_CALL(scheduler, deleteRoom()).Times(AtLeast(1)); + + RequestHandler handler(&scheduler); + for (int request = 0; request <= 3; request++) { + handler.handleRequest(request); + } +} + int main(int argc, char** argv) { ::testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); From 35f6292db763178164ac5733510befa801fc4235 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Fri, 17 Apr 2020 16:13:35 +0300 Subject: [PATCH 21/39] Forget to delete RequestHandler from CMakeLists --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bfecbf..45d410d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,6 @@ set(SOURCE_DIR project/src/) set(LIB_SOURCE_FILES ${SOURCE_DIR}Acceptor.cpp - ${SOURCE_DIR}RequestHandler.cpp ${SOURCE_DIR}RoomScheduler.cpp ) From 5d3446adc4ce23218079a1ab730101a257e73660 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Sun, 17 May 2020 13:35:29 +0300 Subject: [PATCH 22/39] Add boost asio to cmake --- CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 45d410d..1baed12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,4 +28,14 @@ add_executable(CodeShare ${SOURCE_DIR}main.cpp) target_link_libraries(CodeShare project_lib) +set(Boost_USE_STATIC_LIBS OFF) +set(Boost_USE_MULTITHREADED ON) +set(Boost_USE_STATIC_RUNTIME OFF) +find_package(Boost 1.63.0 COMPONENTS system) + +if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) + target_link_libraries(CodeShare ${Boost_LIBRARIES}) +endif() + add_subdirectory(project/tests) From b901f4c545c76afd728814e978f2ce4637829d12 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Sun, 17 May 2020 13:39:14 +0300 Subject: [PATCH 23/39] Change acceptor and split up acceptor mock test --- project/headers/Acceptor.hpp | 4 +++- project/src/Acceptor.cpp | 4 +--- project/tests/mock_tests.cpp | 25 ++++++++++++++++++++++--- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/project/headers/Acceptor.hpp b/project/headers/Acceptor.hpp index 662d7bd..45352a9 100644 --- a/project/headers/Acceptor.hpp +++ b/project/headers/Acceptor.hpp @@ -2,16 +2,18 @@ #define PROJECT_INCLUDE_ACCEPTOR_H_ #include +#include class Acceptor { public: - Acceptor(); + Acceptor(boost::asio::io_service& io_service); void open(); void close(); void listen(); void setOption(int option); private: int state; + boost::asio::ip::tcp::acceptor acceptor_; }; #endif // PROJECT_INCLUDE_ACCEPTOR_H_ \ No newline at end of file diff --git a/project/src/Acceptor.cpp b/project/src/Acceptor.cpp index bd1e7a4..47a8f57 100644 --- a/project/src/Acceptor.cpp +++ b/project/src/Acceptor.cpp @@ -1,8 +1,6 @@ #include "Acceptor.hpp" -Acceptor::Acceptor() { - state = 0; -} +Acceptor::Acceptor(boost::asio::io_service& io_service): acceptor_(io_service), state(0) {} void Acceptor::open() { std::cout << "open" << std::endl; diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index 3b262fd..5dedaa9 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -1,6 +1,7 @@ #include #include "gtest/gtest.h" #include "gmock/gmock.h" +#include "boost/asio.hpp" #include "Acceptor.hpp" #include "Server.hpp" @@ -13,22 +14,40 @@ using ::testing::AtLeast; class MockAcceptor : public Acceptor { public: + using Acceptor::Acceptor; MOCK_METHOD1(setOption, void(int option)); MOCK_METHOD0(open, void()); MOCK_METHOD0(listen, void()); }; TEST(ServerTest, runCallOpen) { - MockAcceptor acceptor; - int option = 0; - EXPECT_CALL(acceptor, setOption(option)).Times(AtLeast(1)); + boost::asio::io_service service; + MockAcceptor acceptor(service); EXPECT_CALL(acceptor, open()).Times(AtLeast(1)); + + Server server(&acceptor); + server.run(); +} + +TEST(ServerTest, runCallListen) { + boost::asio::io_service service; + MockAcceptor acceptor(service); EXPECT_CALL(acceptor, listen()).Times(AtLeast(1)); Server server(&acceptor); server.run(); } +TEST(ServerTest, runCallSetOption) { + boost::asio::io_service service; + MockAcceptor acceptor(service); + int option = 0; + EXPECT_CALL(acceptor, setOption(option)).Times(AtLeast(1)); + + Server server(&acceptor); + server.run(); +} + class MockConnection : public Connection > { public: MockConnection(RequestHandler* handler): Connection >(handler) {} From 8f450575f8ed022fc0a980dcd292f0d49ec38607 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Sun, 17 May 2020 13:46:30 +0300 Subject: [PATCH 24/39] Fix tab --- project/tests/mock_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index 5dedaa9..9b5b32c 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -113,6 +113,6 @@ TEST(RequestHandlerTest, handlerRequestCallRoomSchedulersMethods) { } int main(int argc, char** argv) { - ::testing::InitGoogleMock(&argc, argv); - return RUN_ALL_TESTS(); + ::testing::InitGoogleMock(&argc, argv); + return RUN_ALL_TESTS(); } \ No newline at end of file From 9f92998434840b18b9b3b94e4d70007276930d0f Mon Sep 17 00:00:00 2001 From: aanufriev Date: Sun, 17 May 2020 14:36:26 +0300 Subject: [PATCH 25/39] Add property endpoint to Acceptor and change some methods --- project/headers/Acceptor.hpp | 6 +++--- project/src/Acceptor.cpp | 9 +++++---- project/tests/mock_tests.cpp | 11 +++++++---- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/project/headers/Acceptor.hpp b/project/headers/Acceptor.hpp index 45352a9..d9fb9ac 100644 --- a/project/headers/Acceptor.hpp +++ b/project/headers/Acceptor.hpp @@ -6,14 +6,14 @@ class Acceptor { public: - Acceptor(boost::asio::io_service& io_service); + Acceptor(boost::asio::io_service& io_service, boost::asio::ip::tcp::endpoint& endpoint); void open(); void close(); void listen(); void setOption(int option); private: - int state; - boost::asio::ip::tcp::acceptor acceptor_; + boost::asio::ip::tcp::endpoint endpoint; + boost::asio::ip::tcp::acceptor acceptor_; }; #endif // PROJECT_INCLUDE_ACCEPTOR_H_ \ No newline at end of file diff --git a/project/src/Acceptor.cpp b/project/src/Acceptor.cpp index 47a8f57..b1ae5c4 100644 --- a/project/src/Acceptor.cpp +++ b/project/src/Acceptor.cpp @@ -1,16 +1,17 @@ #include "Acceptor.hpp" -Acceptor::Acceptor(boost::asio::io_service& io_service): acceptor_(io_service), state(0) {} +Acceptor::Acceptor(boost::asio::io_service& io_service, boost::asio::ip::tcp::endpoint& endpoint): endpoint(endpoint), acceptor_(io_service) {} void Acceptor::open() { - std::cout << "open" << std::endl; + acceptor_.open(endpoint.protocol()); } void Acceptor::close() { - std::cout << "close" << std::endl; + acceptor_.close(); } + void Acceptor::listen() { - std::cout << "listen" << std::endl; + acceptor_.listen(); } void Acceptor::setOption(int option) { std::cout << "option is " << option << std::endl; diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index 9b5b32c..d741b9a 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -22,7 +22,8 @@ class MockAcceptor : public Acceptor { TEST(ServerTest, runCallOpen) { boost::asio::io_service service; - MockAcceptor acceptor(service); + boost::asio::ip::tcp::endpoint endpoint; + MockAcceptor acceptor(service, endpoint); EXPECT_CALL(acceptor, open()).Times(AtLeast(1)); Server server(&acceptor); @@ -31,7 +32,8 @@ TEST(ServerTest, runCallOpen) { TEST(ServerTest, runCallListen) { boost::asio::io_service service; - MockAcceptor acceptor(service); + boost::asio::ip::tcp::endpoint endpoint; + MockAcceptor acceptor(service, endpoint); EXPECT_CALL(acceptor, listen()).Times(AtLeast(1)); Server server(&acceptor); @@ -40,8 +42,9 @@ TEST(ServerTest, runCallListen) { TEST(ServerTest, runCallSetOption) { boost::asio::io_service service; - MockAcceptor acceptor(service); - int option = 0; + boost::asio::ip::tcp::endpoint endpoint; + MockAcceptor acceptor(service, endpoint); + bool option = true; EXPECT_CALL(acceptor, setOption(option)).Times(AtLeast(1)); Server server(&acceptor); From 6334d5e71b60c99bd78380b0cc04e58900445762 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Sun, 17 May 2020 14:36:49 +0300 Subject: [PATCH 26/39] Change method setOption --- project/headers/Acceptor.hpp | 2 +- project/headers/Server.hpp | 2 +- project/src/Acceptor.cpp | 7 ++++--- project/tests/mock_tests.cpp | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/project/headers/Acceptor.hpp b/project/headers/Acceptor.hpp index d9fb9ac..bbda9db 100644 --- a/project/headers/Acceptor.hpp +++ b/project/headers/Acceptor.hpp @@ -10,7 +10,7 @@ class Acceptor { void open(); void close(); void listen(); - void setOption(int option); + void setOption(bool reuseAddress); private: boost::asio::ip::tcp::endpoint endpoint; boost::asio::ip::tcp::acceptor acceptor_; diff --git a/project/headers/Server.hpp b/project/headers/Server.hpp index acf85c5..05c9f1e 100644 --- a/project/headers/Server.hpp +++ b/project/headers/Server.hpp @@ -9,7 +9,7 @@ class Server { public: Server(AcceptorType* acceptor) : acceptor_(acceptor) {} void run() { - acceptor_->setOption(0); + acceptor_->setOption(true); acceptor_->open(); acceptor_->listen(); } diff --git a/project/src/Acceptor.cpp b/project/src/Acceptor.cpp index b1ae5c4..8381db4 100644 --- a/project/src/Acceptor.cpp +++ b/project/src/Acceptor.cpp @@ -13,6 +13,7 @@ void Acceptor::close() { void Acceptor::listen() { acceptor_.listen(); } -void Acceptor::setOption(int option) { - std::cout << "option is " << option << std::endl; -} \ No newline at end of file + +void Acceptor::setOption(bool reuseAddress) { + acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); +} diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index d741b9a..3731de7 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -15,7 +15,7 @@ using ::testing::AtLeast; class MockAcceptor : public Acceptor { public: using Acceptor::Acceptor; - MOCK_METHOD1(setOption, void(int option)); + MOCK_METHOD1(setOption, void(bool option)); MOCK_METHOD0(open, void()); MOCK_METHOD0(listen, void()); }; From 37bf281431a724f460f63e031f5418fd746d0ead Mon Sep 17 00:00:00 2001 From: aanufriev Date: Sun, 17 May 2020 17:05:23 +0300 Subject: [PATCH 27/39] Add property ioService to Server --- project/headers/Server.hpp | 6 +++++- project/tests/mock_tests.cpp | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/project/headers/Server.hpp b/project/headers/Server.hpp index 05c9f1e..b4427a4 100644 --- a/project/headers/Server.hpp +++ b/project/headers/Server.hpp @@ -7,13 +7,17 @@ template class Server { public: - Server(AcceptorType* acceptor) : acceptor_(acceptor) {} + Server(boost::asio::io_service* ioService, AcceptorType* acceptor) : ioService(ioService), acceptor_(acceptor) {} + void run() { acceptor_->setOption(true); acceptor_->open(); acceptor_->listen(); + + ioService->run(); } private: + boost::asio::io_service* ioService; AcceptorType* acceptor_; }; diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index 3731de7..58baff2 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -26,7 +26,7 @@ TEST(ServerTest, runCallOpen) { MockAcceptor acceptor(service, endpoint); EXPECT_CALL(acceptor, open()).Times(AtLeast(1)); - Server server(&acceptor); + Server server(&service, &acceptor); server.run(); } @@ -36,7 +36,7 @@ TEST(ServerTest, runCallListen) { MockAcceptor acceptor(service, endpoint); EXPECT_CALL(acceptor, listen()).Times(AtLeast(1)); - Server server(&acceptor); + Server server(&service, &acceptor); server.run(); } @@ -47,7 +47,7 @@ TEST(ServerTest, runCallSetOption) { bool option = true; EXPECT_CALL(acceptor, setOption(option)).Times(AtLeast(1)); - Server server(&acceptor); + Server server(&service, &acceptor); server.run(); } From f01d9a92c02acaa3bd93d0c3a6f6ff821088738a Mon Sep 17 00:00:00 2001 From: aanufriev Date: Sun, 17 May 2020 20:18:50 +0300 Subject: [PATCH 28/39] For readability --- project/src/Acceptor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/project/src/Acceptor.cpp b/project/src/Acceptor.cpp index 8381db4..f6fbada 100644 --- a/project/src/Acceptor.cpp +++ b/project/src/Acceptor.cpp @@ -15,5 +15,6 @@ void Acceptor::listen() { } void Acceptor::setOption(bool reuseAddress) { - acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + boost::asio::ip::tcp::acceptor::reuse_address option(reuseAddress); + acceptor_.set_option(option); } From 0473abcc1178aad7c9acbcf599ab4eba0a28890a Mon Sep 17 00:00:00 2001 From: aanufriev Date: Sun, 17 May 2020 20:19:29 +0300 Subject: [PATCH 29/39] Add properties to Server --- project/headers/Server.hpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/project/headers/Server.hpp b/project/headers/Server.hpp index b4427a4..2d66ed1 100644 --- a/project/headers/Server.hpp +++ b/project/headers/Server.hpp @@ -3,22 +3,38 @@ #include #include "Acceptor.hpp" +#include "Connection.hpp" +#include "RequestHandler.hpp" +#include "RoomScheduler.hpp" template class Server { public: - Server(boost::asio::io_service* ioService, AcceptorType* acceptor) : ioService(ioService), acceptor_(acceptor) {} + Server(boost::asio::io_service* ioService, AcceptorType* acceptor) : + ioService(ioService), + acceptor_(acceptor), + roomScheduler(), + newConnection(), + requestHandler(&roomScheduler) {} void run() { - acceptor_->setOption(true); acceptor_->open(); + acceptor_->setOption(true); acceptor_->listen(); ioService->run(); } + + void startAccept() { + newConnection.reset(new Connection >(&requestHandler)); + } + private: boost::asio::io_service* ioService; AcceptorType* acceptor_; + RoomScheduler roomScheduler; + std::shared_ptr > > newConnection; + RequestHandler requestHandler; }; #endif // PROJECT_INCLUDE_SERVER_H_ \ No newline at end of file From 1d7d9f841aaab7d617032565b44a758769b6ec6d Mon Sep 17 00:00:00 2001 From: aanufriev Date: Sun, 17 May 2020 20:22:43 +0300 Subject: [PATCH 30/39] Add bind func to Acceptor --- project/headers/Acceptor.hpp | 1 + project/headers/Server.hpp | 1 + project/src/Acceptor.cpp | 4 ++++ project/tests/mock_tests.cpp | 11 +++++++++++ 4 files changed, 17 insertions(+) diff --git a/project/headers/Acceptor.hpp b/project/headers/Acceptor.hpp index bbda9db..08d774b 100644 --- a/project/headers/Acceptor.hpp +++ b/project/headers/Acceptor.hpp @@ -9,6 +9,7 @@ class Acceptor { Acceptor(boost::asio::io_service& io_service, boost::asio::ip::tcp::endpoint& endpoint); void open(); void close(); + void bind(); void listen(); void setOption(bool reuseAddress); private: diff --git a/project/headers/Server.hpp b/project/headers/Server.hpp index 2d66ed1..c5d01f5 100644 --- a/project/headers/Server.hpp +++ b/project/headers/Server.hpp @@ -20,6 +20,7 @@ class Server { void run() { acceptor_->open(); acceptor_->setOption(true); + acceptor_->bind(); acceptor_->listen(); ioService->run(); diff --git a/project/src/Acceptor.cpp b/project/src/Acceptor.cpp index f6fbada..00dee21 100644 --- a/project/src/Acceptor.cpp +++ b/project/src/Acceptor.cpp @@ -10,6 +10,10 @@ void Acceptor::close() { acceptor_.close(); } +void Acceptor::bind() { + acceptor_.bind(endpoint); +} + void Acceptor::listen() { acceptor_.listen(); } diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index 58baff2..fbeb1f6 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -17,6 +17,7 @@ class MockAcceptor : public Acceptor { using Acceptor::Acceptor; MOCK_METHOD1(setOption, void(bool option)); MOCK_METHOD0(open, void()); + MOCK_METHOD0(bind, void()); MOCK_METHOD0(listen, void()); }; @@ -30,6 +31,16 @@ TEST(ServerTest, runCallOpen) { server.run(); } +TEST(ServerTest, runCallBind) { + boost::asio::io_service service; + boost::asio::ip::tcp::endpoint endpoint; + MockAcceptor acceptor(service, endpoint); + EXPECT_CALL(acceptor, bind()).Times(AtLeast(1)); + + Server server(&service, &acceptor); + server.run(); +} + TEST(ServerTest, runCallListen) { boost::asio::io_service service; boost::asio::ip::tcp::endpoint endpoint; From 63813b7c0b92d8616c6fe583a010eda89f7ec6f2 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Mon, 18 May 2020 20:16:01 +0300 Subject: [PATCH 31/39] Add method to take boost acceptor from class acceptor co call async_accept --- project/headers/Acceptor.hpp | 6 ++++++ project/src/Acceptor.cpp | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/project/headers/Acceptor.hpp b/project/headers/Acceptor.hpp index 08d774b..55cc4a7 100644 --- a/project/headers/Acceptor.hpp +++ b/project/headers/Acceptor.hpp @@ -8,10 +8,16 @@ class Acceptor { public: Acceptor(boost::asio::io_service& io_service, boost::asio::ip::tcp::endpoint& endpoint); void open(); + void close(); + void bind(); + void listen(); + void setOption(bool reuseAddress); + + boost::asio::ip::tcp::acceptor& origin(); private: boost::asio::ip::tcp::endpoint endpoint; boost::asio::ip::tcp::acceptor acceptor_; diff --git a/project/src/Acceptor.cpp b/project/src/Acceptor.cpp index 00dee21..80b333c 100644 --- a/project/src/Acceptor.cpp +++ b/project/src/Acceptor.cpp @@ -22,3 +22,7 @@ void Acceptor::setOption(bool reuseAddress) { boost::asio::ip::tcp::acceptor::reuse_address option(reuseAddress); acceptor_.set_option(option); } + +boost::asio::ip::tcp::acceptor&Acceptor::origin() { + return acceptor_; +} From 82fecd991ac329c04badf00226ba87e89e200652 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Mon, 18 May 2020 20:16:52 +0300 Subject: [PATCH 32/39] Add acceptHandler to server and change Connection --- project/headers/Connection.hpp | 7 ++++++- project/headers/Server.hpp | 24 ++++++++++++++++++------ project/tests/mock_tests.cpp | 27 +++++++++++++++------------ 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/project/headers/Connection.hpp b/project/headers/Connection.hpp index c68a9f9..3fe802c 100644 --- a/project/headers/Connection.hpp +++ b/project/headers/Connection.hpp @@ -7,7 +7,7 @@ template class Connection { public: - Connection(HandlerType* handler) : requestHandler(handler) {} + Connection(HandlerType* handler, boost::asio::io_service& ioService) : requestHandler(handler), socket_(ioService) {} void start() { read(); @@ -16,9 +16,14 @@ class Connection { void stop() { std::cout << "stop" << std::endl; } + + boost::asio::ip::tcp::socket& getSocket() { + return socket_; + } private: std::vector buffer; HandlerType* requestHandler; + boost::asio::ip::tcp::socket socket_; void read() { requestHandler->handleRequest(0); diff --git a/project/headers/Server.hpp b/project/headers/Server.hpp index c5d01f5..2f415f6 100644 --- a/project/headers/Server.hpp +++ b/project/headers/Server.hpp @@ -1,6 +1,8 @@ #ifndef PROJECT_INCLUDE_SERVER_H_ #define PROJECT_INCLUDE_SERVER_H_ +#include + #include #include "Acceptor.hpp" #include "Connection.hpp" @@ -10,32 +12,42 @@ template class Server { public: - Server(boost::asio::io_service* ioService, AcceptorType* acceptor) : + Server(boost::asio::io_service& ioService, AcceptorType* acceptor) : ioService(ioService), acceptor_(acceptor), roomScheduler(), newConnection(), requestHandler(&roomScheduler) {} - void run() { + void run(int port) { acceptor_->open(); acceptor_->setOption(true); acceptor_->bind(); acceptor_->listen(); - - ioService->run(); } void startAccept() { - newConnection.reset(new Connection >(&requestHandler)); + newConnection.reset(new Connection >(&requestHandler, ioService)); + + auto handler = boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error); + acceptor_->origin().async_accept(newConnection->getSocket(), handler); } private: - boost::asio::io_service* ioService; + boost::asio::io_service& ioService; AcceptorType* acceptor_; RoomScheduler roomScheduler; std::shared_ptr > > newConnection; RequestHandler requestHandler; + + void handleAccept(const boost::system::error_code& error) { + // дописать + if (!error) { + // вызывается метод connection manager + std::cout << "connectionManager method" << std::endl; + } + startAccept(); + } }; #endif // PROJECT_INCLUDE_SERVER_H_ \ No newline at end of file diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index fbeb1f6..38d0be7 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -27,8 +27,8 @@ TEST(ServerTest, runCallOpen) { MockAcceptor acceptor(service, endpoint); EXPECT_CALL(acceptor, open()).Times(AtLeast(1)); - Server server(&service, &acceptor); - server.run(); + Server server(service, &acceptor); + server.run(5000); } TEST(ServerTest, runCallBind) { @@ -37,8 +37,8 @@ TEST(ServerTest, runCallBind) { MockAcceptor acceptor(service, endpoint); EXPECT_CALL(acceptor, bind()).Times(AtLeast(1)); - Server server(&service, &acceptor); - server.run(); + Server server(service, &acceptor); + server.run(5000); } TEST(ServerTest, runCallListen) { @@ -47,8 +47,8 @@ TEST(ServerTest, runCallListen) { MockAcceptor acceptor(service, endpoint); EXPECT_CALL(acceptor, listen()).Times(AtLeast(1)); - Server server(&service, &acceptor); - server.run(); + Server server(service, &acceptor); + server.run(5000); } TEST(ServerTest, runCallSetOption) { @@ -58,13 +58,13 @@ TEST(ServerTest, runCallSetOption) { bool option = true; EXPECT_CALL(acceptor, setOption(option)).Times(AtLeast(1)); - Server server(&service, &acceptor); - server.run(); + Server server(service, &acceptor); + server.run(5000); } class MockConnection : public Connection > { public: - MockConnection(RequestHandler* handler): Connection >(handler) {} + using Connection::Connection; MOCK_METHOD0(start, void()); MOCK_METHOD0(stop, void()); }; @@ -72,7 +72,8 @@ class MockConnection : public Connection > { TEST(ConnectionManagerTest, startCallConnectionStart) { RoomScheduler scheduler; RequestHandler handler(&scheduler); - MockConnection connection(&handler); + boost::asio::io_service service; + MockConnection connection(&handler, service); EXPECT_CALL(connection, start()).Times(AtLeast(1)); ConnectionManager manager; @@ -82,7 +83,8 @@ TEST(ConnectionManagerTest, startCallConnectionStart) { TEST(ConnectionManagerTest, stopCallConnectionStop) { RoomScheduler scheduler; RequestHandler handler(&scheduler); - MockConnection connection(&handler); + boost::asio::io_service service; + MockConnection connection(&handler, service); EXPECT_CALL(connection, stop()).Times(AtLeast(1)); ConnectionManager manager; @@ -101,7 +103,8 @@ TEST(ConnectionTest, startCallHandleRequest) { int request = 0; EXPECT_CALL(handler, handleRequest(request)).Times(AtLeast(1)); - Connection connection(&handler); + boost::asio::io_service service; + Connection connection(&handler, service); connection.start(); } From 62864878a124b07db3441f3fe5dbec95d2617bdb Mon Sep 17 00:00:00 2001 From: aanufriev Date: Tue, 19 May 2020 17:36:26 +0300 Subject: [PATCH 33/39] Add implementation of ConnectionManager class --- project/headers/ConnectionManager.hpp | 16 ++++++++++++---- project/headers/Server.hpp | 9 +++++---- project/tests/mock_tests.cpp | 16 ++++++++++------ 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/project/headers/ConnectionManager.hpp b/project/headers/ConnectionManager.hpp index 45f8616..a28bdb4 100644 --- a/project/headers/ConnectionManager.hpp +++ b/project/headers/ConnectionManager.hpp @@ -2,25 +2,33 @@ #define PROJECT_INCLUDE_CONNECTION_MANAGER_H_ #include -#include +#include template class ConnectionManager { public: ConnectionManager() {} - void start(ConnectionType* connection) { + + void start(std::shared_ptr connection) { + std::cout << "start in ConManager" << std::endl; + connections.insert(connection); connection->start(); } - void stop(ConnectionType* connection) { + + void stop(std::shared_ptr connection) { + connections.erase(connection); connection->stop(); } + void stopAll() { for (size_t i = 0; i < connections.size(); i++) { connections[i].stop(); } + connections.clear(); } + private: - std::vector connections; + std::set > connections; }; #endif // PROJECT_INCLUDE_CONNECTION_MANAGER_H_ \ No newline at end of file diff --git a/project/headers/Server.hpp b/project/headers/Server.hpp index 2f415f6..ae1c3df 100644 --- a/project/headers/Server.hpp +++ b/project/headers/Server.hpp @@ -8,6 +8,7 @@ #include "Connection.hpp" #include "RequestHandler.hpp" #include "RoomScheduler.hpp" +#include "ConnectionManager.hpp" template class Server { @@ -17,7 +18,8 @@ class Server { acceptor_(acceptor), roomScheduler(), newConnection(), - requestHandler(&roomScheduler) {} + requestHandler(&roomScheduler), + connectionManager() {} void run(int port) { acceptor_->open(); @@ -39,12 +41,11 @@ class Server { RoomScheduler roomScheduler; std::shared_ptr > > newConnection; RequestHandler requestHandler; + ConnectionManager > > connectionManager; void handleAccept(const boost::system::error_code& error) { - // дописать if (!error) { - // вызывается метод connection manager - std::cout << "connectionManager method" << std::endl; + connectionManager.start(newConnection); } startAccept(); } diff --git a/project/tests/mock_tests.cpp b/project/tests/mock_tests.cpp index 38d0be7..8a6ba1b 100644 --- a/project/tests/mock_tests.cpp +++ b/project/tests/mock_tests.cpp @@ -73,22 +73,26 @@ TEST(ConnectionManagerTest, startCallConnectionStart) { RoomScheduler scheduler; RequestHandler handler(&scheduler); boost::asio::io_service service; - MockConnection connection(&handler, service); - EXPECT_CALL(connection, start()).Times(AtLeast(1)); + + MockConnection* connection = new MockConnection(&handler, service); + std::shared_ptr sharedConnection(connection); + EXPECT_CALL(*sharedConnection, start()).Times(AtLeast(1)); ConnectionManager manager; - manager.start(&connection); + manager.start(sharedConnection); } TEST(ConnectionManagerTest, stopCallConnectionStop) { RoomScheduler scheduler; RequestHandler handler(&scheduler); boost::asio::io_service service; - MockConnection connection(&handler, service); - EXPECT_CALL(connection, stop()).Times(AtLeast(1)); + + MockConnection* connection = new MockConnection(&handler, service); + std::shared_ptr sharedConnection(connection); + EXPECT_CALL(*sharedConnection, stop()).Times(AtLeast(1)); ConnectionManager manager; - manager.stop(&connection); + manager.stop(sharedConnection); } class MockRequestHandler : public RequestHandler { From 42aa89fb4d58968b8eb7da05fc208a52aa9ab125 Mon Sep 17 00:00:00 2001 From: aanufriev Date: Sat, 23 May 2020 14:59:21 +0300 Subject: [PATCH 34/39] Change func handle_read. Now it parses request and display field "value" from json in request's body --- project/headers/Connection.hpp | 44 ++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/project/headers/Connection.hpp b/project/headers/Connection.hpp index 3fe802c..fb15bb1 100644 --- a/project/headers/Connection.hpp +++ b/project/headers/Connection.hpp @@ -2,15 +2,22 @@ #define PROJECT_INCLUDE_CONNECTION_H_ #include -#include +#include +#include +#include template class Connection { public: - Connection(HandlerType* handler, boost::asio::io_service& ioService) : requestHandler(handler), socket_(ioService) {} + Connection(HandlerType* handler, boost::asio::io_service& ioService) : + requestHandler(handler), + socket_(ioService) {} void start() { - read(); + socket_.async_read_some(boost::asio::buffer(data_, maxLength), + boost::bind(&Connection::handle_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); } void stop() { @@ -21,9 +28,10 @@ class Connection { return socket_; } private: - std::vector buffer; HandlerType* requestHandler; boost::asio::ip::tcp::socket socket_; + enum { maxLength = 2048 }; + char data_[maxLength]; void read() { requestHandler->handleRequest(0); @@ -32,6 +40,34 @@ class Connection { void write() { std::cout << "write" << std::endl; } + + void handle_read(const boost::system::error_code& error, size_t bytes_transferred) { + if (!error) { + // boost::asio::async_write(socket_, boost::asio::buffer(data_, bytes_transferred), + // boost::bind(&Connection::handle_write, this,boost::asio::placeholders::error)); + boost::system::error_code ec; + boost::beast::http::request_parser parser; + parser.eager(true); + parser.put(boost::asio::buffer(data_, bytes_transferred), ec); + + boost::beast::http::request request = parser.get(); + auto body = request.body(); + + std::stringstream jsonEncoded(body); + boost::property_tree::ptree root; + boost::property_tree::read_json(jsonEncoded, root); + + std::cout << root.get("value") << std::endl; + } + } + + void handle_write(const boost::system::error_code& error) { + if (!error) { + socket_.async_read_some(boost::asio::buffer(data_, maxLength), + boost::bind(&Connection::handle_read, this, boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + } }; #endif // PROJECT_INCLUDE_CONNECTION_H_ \ No newline at end of file From 78a562349162bb07cec1e7f08ffe5f5da68030af Mon Sep 17 00:00:00 2001 From: aanufriev Date: Sat, 23 May 2020 20:17:03 +0300 Subject: [PATCH 35/39] Check method type and return json in response --- project/headers/Connection.hpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/project/headers/Connection.hpp b/project/headers/Connection.hpp index fb15bb1..c2a609f 100644 --- a/project/headers/Connection.hpp +++ b/project/headers/Connection.hpp @@ -45,6 +45,7 @@ class Connection { if (!error) { // boost::asio::async_write(socket_, boost::asio::buffer(data_, bytes_transferred), // boost::bind(&Connection::handle_write, this,boost::asio::placeholders::error)); + boost::system::error_code ec; boost::beast::http::request_parser parser; parser.eager(true); @@ -53,11 +54,21 @@ class Connection { boost::beast::http::request request = parser.get(); auto body = request.body(); - std::stringstream jsonEncoded(body); - boost::property_tree::ptree root; - boost::property_tree::read_json(jsonEncoded, root); + if (request.method() == boost::beast::http::verb::post) { + std::stringstream jsonEncoded(body); + boost::property_tree::ptree root; + boost::property_tree::read_json(jsonEncoded, root); + + std::cout << root.get("value") << std::endl; + } + + boost::property_tree::ptree responseData; + responseData.put("roomId", 1); + std::stringstream response; + boost::property_tree::write_json(response, responseData); - std::cout << root.get("value") << std::endl; + boost::asio::async_write(socket_, boost::asio::buffer(response.str()), + boost::bind(&Connection::handle_write, this,boost::asio::placeholders::error)); } } From f6df40f4c9893c9320e55337e8001c8cbbcfbcdf Mon Sep 17 00:00:00 2001 From: aanufriev Date: Mon, 25 May 2020 21:11:50 +0300 Subject: [PATCH 36/39] Add server start to main --- project/src/main.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/project/src/main.cpp b/project/src/main.cpp index a84fc6e..eaf3116 100644 --- a/project/src/main.cpp +++ b/project/src/main.cpp @@ -3,7 +3,20 @@ // #include +#include "boost/asio.hpp" + +#include "Acceptor.hpp" +#include "Server.hpp" int main() { - std::cout << "Welcome to CodeShare project!" << std::endl; + int port = 6666; + boost::asio::io_service ioService; + boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port); + + Acceptor acceptor(ioService, endpoint); + + Server server(ioService, &acceptor); + server.run(port); + server.startAccept(); + ioService.run(); } From a33dc8bd8745b4b743fdb3dbfd3f3fda2fcfb82d Mon Sep 17 00:00:00 2001 From: aanufriev Date: Tue, 26 May 2020 21:45:31 +0300 Subject: [PATCH 37/39] Add lib json.hpp to convert json to string and to parse json --- project/headers/json.hpp | 22712 +++++++++++++++++++++++++++++++++++++ 1 file changed, 22712 insertions(+) create mode 100644 project/headers/json.hpp diff --git a/project/headers/json.hpp b/project/headers/json.hpp new file mode 100644 index 0000000..93e9d12 --- /dev/null +++ b/project/headers/json.hpp @@ -0,0 +1,22712 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.7.0 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2013-2019 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 INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#define NLOHMANN_JSON_VERSION_MAJOR 3 +#define NLOHMANN_JSON_VERSION_MINOR 7 +#define NLOHMANN_JSON_VERSION_PATCH 0 + +#include // all_of, find, for_each +#include // assert +#include // and, not, or +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#include // istream, ostream +#include // random_access_iterator_tag +#include // unique_ptr +#include // accumulate +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include + + +#include + +// #include + + +#include // transform +#include // array +#include // and, not +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include + + +#include // exception +#include // runtime_error +#include // to_string + +// #include + + +#include // size_t + +namespace nlohmann +{ +namespace detail +{ +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // pair +// #include +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to + * the public domain worldwide. This software is distributed without + * any warranty. + * + * For details, see . + * SPDX-License-Identifier: CC0-1.0 + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 9) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 9 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(_MSC_VER) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(__COMPCERT__) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) [[deprecated("Since " #since)]] + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) [[deprecated("Since " #since "; use " #replacement)]] +#elif \ + JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,3,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) + #define JSON_HEDLEY_DEPRECATED(since) _declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(__cplusplus) && (__cplusplus >= 201703L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT [[nodiscard]] +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN [[noreturn]] +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(17,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) + #define JSON_HEDLEY_UNREACHABLE() __assume(0) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_UNREACHABLE() std::_nassert(0) + #else + #define JSON_HEDLEY_UNREACHABLE() _nassert(0) + #endif + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value +#elif defined(EXIT_FAILURE) + #define JSON_HEDLEY_UNREACHABLE() abort() +#else + #define JSON_HEDLEY_UNREACHABLE() + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() +#endif + +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && !defined(JSON_HEDLEY_ARM_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) + #define JSON_HEDLEY_ASSUME(expr) ((void) ((expr) ? 1 : (__builtin_unreachable(), 1))) +#else + #define JSON_HEDLEY_ASSUME(expr) ((void) (expr)) +#endif + + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if \ + JSON_HEDLEY_HAS_WARNING("-Wvariadic-macros") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR constexpr + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable(!!(expr)) +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(expr, value, probability) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1, probability) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0, probability) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#if !defined(JSON_HEDLEY_BUILTIN_UNPREDICTABLE) + #define JSON_HEDLEY_BUILTIN_UNPREDICTABLE(expr) __builtin_expect_with_probability(!!(expr), 1, 0.5) +#endif +#elif \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect(!!(expr), (expected)) : (((void) (expected)), !!(expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (((void) (expected)), !!(expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else + #define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) + #define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif JSON_HEDLEY_TI_VERSION_CHECK(7,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else + #define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) + #define JSON_HEDLEY_PRIVATE + #define JSON_HEDLEY_PUBLIC __declspec(dllexport) + #define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else + #if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_EABI__) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) + #define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) + #else + #define JSON_HEDLEY_PRIVATE + #define JSON_HEDLEY_PUBLIC + #endif + #define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + !defined(JSON_HEDLEY_PGI_VERSION) + #if \ + (__cplusplus >= 201703L) || \ + ((__cplusplus >= 201103L) && JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)) + #define JSON_HEDLEY_FALL_THROUGH [[fallthrough]] + #elif (__cplusplus >= 201103L) && JSON_HEDLEY_HAS_CPP_ATTRIBUTE(clang::fallthrough) + #define JSON_HEDLEY_FALL_THROUGH [[clang::fallthrough]] + #elif (__cplusplus >= 201103L) && JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) + #define JSON_HEDLEY_FALL_THROUGH [[gnu::fallthrough]] + #endif +#endif +#if !defined(JSON_HEDLEY_FALL_THROUGH) + #if JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(fallthrough,7,0,0) && !defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) + #elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough + #else + #define JSON_HEDLEY_FALL_THROUGH + #endif +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* Note the double-underscore. For internal use only; no API + * guarantees! */ +#if defined(JSON_HEDLEY__IS_CONSTEXPR) + #undef JSON_HEDLEY__IS_CONSTEXPR +#endif + +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY__IS_CONSTEXPR(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY__IS_CONSTEXPR(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(JSON_HEDLEY_SUNPRO_VERSION) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY__IS_CONSTEXPR(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY__IS_CONSTEXPR(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY__IS_CONSTEXPR(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY__IS_CONSTEXPR) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY__IS_CONSTEXPR(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY__IS_CONSTEXPR(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + JSON_HEDLEY_HAS_FEATURE(c_static_assert) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201703L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + (defined(__cplusplus) && JSON_HEDLEY_TI_VERSION_CHECK(8,3,0)) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) static_assert(expr, message) +#elif defined(__cplusplus) && (__cplusplus >= 201103L) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) static_assert(expr) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (*((T*) &(expr))) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_CPP_CAST(T, expr) static_cast(expr) +#else + #define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE_MSG(expr, msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((__diagnose_if__(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE_MSG(expr, msg) __attribute__((__diagnose_if__(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE_MSG(expr, msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#define JSON_HEDLEY_REQUIRE(expr) JSON_HEDLEY_REQUIRE_MSG(expr, #expr) + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #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__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 +#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 to disable exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + + +namespace nlohmann +{ +namespace detail +{ +//////////////// +// exceptions // +//////////////// + +/*! +@brief general exception of the @ref basic_json class + +This class is an extension of `std::exception` objects with a member @a id for +exception ids. It is used as the base class for all exceptions thrown by the +@ref basic_json class. This class can hence be used as "wildcard" to catch +exceptions. + +Subclasses: +- @ref parse_error for exceptions indicating a parse error +- @ref invalid_iterator for exceptions indicating errors with iterators +- @ref type_error for exceptions indicating executing a member function with + a wrong type +- @ref out_of_range for exceptions indicating access out of the defined range +- @ref other_error for exceptions indicating other library errors + +@internal +@note To have nothrow-copy-constructible exceptions, we internally use + `std::runtime_error` which can cope with arbitrary-length error messages. + Intermediate strings are built with static functions and then passed to + the actual constructor. +@endinternal + +@liveexample{The following code shows how arbitrary library exceptions can be +caught.,exception} + +@since version 3.0.0 +*/ +class exception : public std::exception +{ + public: + /// returns the explanatory string + JSON_HEDLEY_RETURNS_NON_NULL + const char* what() const noexcept override + { + return m.what(); + } + + /// the id of the exception + const int id; + + protected: + JSON_HEDLEY_NON_NULL(3) + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} + + static std::string name(const std::string& ename, int id_) + { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } + + private: + /// an exception object as storage for error messages + std::runtime_error m; +}; + +/*! +@brief exception indicating a parse error + +This exception is thrown by the library when a parse error occurs. Parse errors +can occur during the deserialization of JSON text, CBOR, MessagePack, as well +as when using JSON Patch. + +Member @a byte holds the byte index of the last read character in the input +file. + +Exceptions have ids 1xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. +json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. +json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. +json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. +json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. +json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. +json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. +json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. +json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. +json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. +json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. +json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. +json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). + +@note For an input with n bytes, 1 is the index of the first character and n+1 + is the index of the terminating null byte or the end of file. This also + holds true when reading a byte vector (CBOR or MessagePack). + +@liveexample{The following code shows how a `parse_error` exception can be +caught.,parse_error} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class parse_error : public exception +{ + public: + /*! + @brief create a parse error exception + @param[in] id_ the id of the exception + @param[in] pos the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + static parse_error create(int id_, const position_t& pos, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + what_arg; + return parse_error(id_, pos.chars_read_total, w.c_str()); + } + + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + what_arg; + return parse_error(id_, byte_, w.c_str()); + } + + /*! + @brief byte index of the parse error + + The byte index of the last read character in the input file. + + @note For an input with n bytes, 1 is the index of the first character and + n+1 is the index of the terminating null byte or the end of file. + This also holds true when reading a byte vector (CBOR or MessagePack). + */ + const std::size_t byte; + + private: + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } +}; + +/*! +@brief exception indicating errors with iterators + +This exception is thrown if iterators passed to a library function do not match +the expected semantics. + +Exceptions have ids 2xx. + +name / id | example message | description +----------------------------------- | --------------- | ------------------------- +json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. +json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. +json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. +json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. +json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. +json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. +json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. +json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. +json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. +json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). + +@liveexample{The following code shows how an `invalid_iterator` exception can be +caught.,invalid_iterator} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class invalid_iterator : public exception +{ + public: + static invalid_iterator create(int id_, const std::string& what_arg) + { + std::string w = exception::name("invalid_iterator", id_) + what_arg; + return invalid_iterator(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating executing a member function with a wrong type + +This exception is thrown in case of a type error; that is, a library function is +executed on a JSON value whose type does not match the expected semantics. + +Exceptions have ids 3xx. + +name / id | example message | description +----------------------------- | --------------- | ------------------------- +json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. +json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. +json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. +json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. +json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. +json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. +json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. +json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. +json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. +json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. +json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. +json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. +json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. +json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. +json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. +json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | +json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | + +@liveexample{The following code shows how a `type_error` exception can be +caught.,type_error} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class type_error : public exception +{ + public: + static type_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("type_error", id_) + what_arg; + return type_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating access out of the defined range + +This exception is thrown in case a library function is called on an input +parameter that exceeds the expected range, for instance in case of array +indices or nonexisting object keys. + +Exceptions have ids 4xx. + +name / id | example message | description +------------------------------- | --------------- | ------------------------- +json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. +json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. +json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. +json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. +json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. +json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. +json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. | +json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | +json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | + +@liveexample{The following code shows how an `out_of_range` exception can be +caught.,out_of_range} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class out_of_range : public exception +{ + public: + static out_of_range create(int id_, const std::string& what_arg) + { + std::string w = exception::name("out_of_range", id_) + what_arg; + return out_of_range(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating other library errors + +This exception is thrown in case of errors that cannot be classified with the +other exception types. + +Exceptions have ids 5xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range + +@liveexample{The following code shows how an `other_error` exception can be +caught.,other_error} + +@since version 3.0.0 +*/ +class other_error : public exception +{ + public: + static other_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("other_error", id_) + what_arg; + return other_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // not +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type + +namespace nlohmann +{ +namespace detail +{ +// 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; + +// implementation of C++14 index_sequence and affiliates +// source: https://stackoverflow.com/a/32223343 +template +struct index_sequence +{ + using type = index_sequence; + using value_type = std::size_t; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +template +struct merge_and_renumber; + +template +struct merge_and_renumber, index_sequence> + : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; + +template +struct make_index_sequence + : merge_and_renumber < typename make_index_sequence < N / 2 >::type, + typename make_index_sequence < N - N / 2 >::type > {}; + +template<> struct make_index_sequence<0> : index_sequence<> {}; +template<> struct make_index_sequence<1> : index_sequence<0> {}; + +template +using index_sequence_for = make_index_sequence; + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; + +template +constexpr T static_const::value; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // not +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval + +// #include + + +#include // random_access_iterator_tag + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; +} // namespace detail +} // namespace nlohmann + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + + +#include + +// #include + + +// http://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template