From 328bb7f8dcfaf56293c969564d0b7e7721f288c3 Mon Sep 17 00:00:00 2001 From: AstroAir Date: Mon, 14 Aug 2023 19:13:56 +0800 Subject: [PATCH 1/4] INDI Build on Windows --- CMakeLists.txt | 73 ++++- indiserver/indiserver.cpp | 16 +- libs/alignment/CMakeLists.txt | 2 +- libs/eventloop/eventloop.c | 10 +- libs/hid/CMakeLists.txt | 3 + libs/indibase/CMakeLists.txt | 6 +- .../connectionplugins/connectionserial.cpp | 90 ++++-- .../connectionplugins/connectiontcp.cpp | 24 +- libs/indibase/indidome.cpp | 100 ++++-- libs/indibase/indidriver.c | 37 ++- libs/indibase/indidriverio.c | 116 +++++-- libs/indibase/indidrivermain.c | 30 +- libs/indibase/indilogger.cpp | 14 + libs/indibase/inditelescope.cpp | 204 +++++++++--- libs/indicore/CMakeLists.txt | 25 +- libs/indicore/indicom.c | 32 ++ libs/indicore/indicom.h | 2 - libs/indicore/sharedblob.c | 297 ++++++++++++++---- libs/indicore/shm_open_anon.c | 4 +- tools/CMakeLists.txt | 6 +- tools/evalINDI.c | 40 ++- tools/getINDIproperty.c | 47 ++- tools/setINDIproperty.c | 38 ++- 23 files changed, 980 insertions(+), 236 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6c54c12ee..9ec688ce1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -255,9 +255,76 @@ endif(INDI_BUILD_WEBSOCKET) # # ################################################################################################## if(INDI_BUILD_DRIVERS) - if(WIN32 OR ANDROID) + if(ANDROID) message(WARNING "INDI drivers are only supported under Linux, BSD, MacOS, and Cygwin while current system is " ${CMAKE_SYSTEM_NAME}) - else(WIN32 OR ANDROID) + elseif(WIN32) + find_package(Threads REQUIRED) + find_package(ZLIB REQUIRED) + find_package(CFITSIO REQUIRED) + find_package(Nova REQUIRED) + find_package(USB1 REQUIRED) + find_package(CURL REQUIRED) + find_package(GSL REQUIRED) + find_package(JPEG REQUIRED) + find_library(M_LIB m) + + if(CMAKE_VERSION VERSION_LESS 3.12.0) + set(CURL ${CURL_LIBRARIES}) + else() + set(CURL CURL::libcurl) + endif() + + include_directories(${CFITSIO_INCLUDE_DIR}) + include_directories(${NOVA_INCLUDE_DIR}) + include_directories(${USB1_INCLUDE_DIRS}) + include_directories(${GSL_INCLUDE_DIRS}) + include_directories(${JPEG_INCLUDE_DIR}) + include_directories(${ZLIB_INCLUDE_DIR}) + include_directories(libs/indibase) + include_directories(libs/indibase/timer) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-usb.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-usb.h) + + add_subdirectory(libs/eventloop) + add_subdirectory(libs/dsp) + add_subdirectory(libs/fpack) + add_subdirectory(libs/hid) + + # ################################################# + # ########## INDI Driver Library ################## + # ################################################# + add_subdirectory(libs/indibase) + + # ################################################# + # ########## INDI Alignment Subsystem ############# + # ################################################# + # add_subdirectory(libs/alignment) + + # ################################################# + # ########## INDI Drivers ######################### + # ################################################# + # add_subdirectory(drivers) + install(FILES drivers.xml ${CMAKE_CURRENT_SOURCE_DIR}/drivers/focuser/indi_tcfs_sk.xml DESTINATION ${DATA_INSTALL_DIR}) + + # #################################### + # ########### INDI TOOLS ############# + # #################################### + add_subdirectory(tools) + + # #################################### + # ########### EXamples ############### + # #################################### + if(INDI_BUILD_CLIENT) + # add_subdirectory(examples) + else() + message(WARNING "Skipping build of examples since INDI POSIX client is not built") + endif() + + # ################################################################################ + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libindi.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libindi.pc @ONLY) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libindi.pc DESTINATION ${PKGCONFIG_INSTALL_PREFIX}) + + else() # 1. Dependencies find_package(Threads REQUIRED) find_package(ZLIB REQUIRED) @@ -362,7 +429,7 @@ if(INDI_BUILD_DRIVERS) else() message(STATUS "GTEST not found, not building tests") endif(GTEST_FOUND AND BUILD_TESTING) - endif(WIN32 OR ANDROID) + endif(ANDROID) endif(INDI_BUILD_DRIVERS) # ################################################################################################## diff --git a/indiserver/indiserver.cpp b/indiserver/indiserver.cpp index 12420ee37d..a88a9967de 100644 --- a/indiserver/indiserver.cpp +++ b/indiserver/indiserver.cpp @@ -69,7 +69,6 @@ #include #include #include -#include #include #include #include @@ -77,8 +76,12 @@ #include #include #include -#include #include + +#ifdef _WIN32 +#include +#include +#else #include #include #include @@ -88,10 +91,12 @@ #include #include #include -#include #include +#include +#include #ifdef MSG_ERRQUEUE -#include + #include +#endif #endif #include @@ -1091,7 +1096,9 @@ static void usage(void) exit(2); } +#ifdef _WIN32 /* turn off SIGPIPE on bad write so we can handle it inline */ +#else static void noSIGPIPE() { struct sigaction sa; @@ -1100,6 +1107,7 @@ static void noSIGPIPE() sigemptyset(&sa.sa_mask); (void)sigaction(SIGPIPE, &sa, NULL); } +#endif /* start the given local INDI driver process. * exit if trouble. diff --git a/libs/alignment/CMakeLists.txt b/libs/alignment/CMakeLists.txt index 786aecc474..66c17edab7 100644 --- a/libs/alignment/CMakeLists.txt +++ b/libs/alignment/CMakeLists.txt @@ -91,7 +91,7 @@ if(NOT WIN32) SET_TARGET_PROPERTIES(AlignmentClient PROPERTIES COMPILE_FLAGS "-fPIC") endif(NOT WIN32) -target_link_libraries(AlignmentClient indidevice indiclient) +target_link_libraries(AlignmentClient indiclient indidriver indidevice) set_target_properties(AlignmentClient PROPERTIES OUTPUT_NAME indiAlignmentClient) install(TARGETS AlignmentClient ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/libs/eventloop/eventloop.c b/libs/eventloop/eventloop.c index 0ac87a5b19..f4e3d9167d 100644 --- a/libs/eventloop/eventloop.c +++ b/libs/eventloop/eventloop.c @@ -1,4 +1,4 @@ -#if 0 +/* INDI Copyright (C) 2003 Elwood C. Downey @@ -16,7 +16,7 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -#endif +*/ /* suite of functions to implement an event driven program. * @@ -40,6 +40,12 @@ #include #include #include +#include +#if _WIN32 +#include +#else +#include +#endif #include "eventloop.h" diff --git a/libs/hid/CMakeLists.txt b/libs/hid/CMakeLists.txt index 8bd30d98a2..4be6945a33 100644 --- a/libs/hid/CMakeLists.txt +++ b/libs/hid/CMakeLists.txt @@ -49,4 +49,7 @@ endif() add_executable(indi_hid_test hidtest.cpp) target_link_libraries(indi_hid_test hid ${USB1_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${LIBS}) +if(WIN32) +target_link_libraries(indi_hid_test setupapi) +endif() install(TARGETS indi_hid_test RUNTIME DESTINATION bin) diff --git a/libs/indibase/CMakeLists.txt b/libs/indibase/CMakeLists.txt index 734872fa7f..3545d07a9e 100644 --- a/libs/indibase/CMakeLists.txt +++ b/libs/indibase/CMakeLists.txt @@ -49,7 +49,7 @@ if(LibXISF_FOUND) endif() # Add OggTheora, StreamManager, v4l2 -if(UNIX) +if(UNIX OR WIN32) find_package(OggTheora) if(OGGTHEORA_FOUND) @@ -219,6 +219,10 @@ set_property(TARGET ${PROJECT_NAME}_OBJECT PROPERTY POSITION_INDEPENDENT_CODE 1) target_compile_definitions(${PROJECT_NAME}_OBJECT PRIVATE "-DHAVE_LIBNOVA") +if(WIN32) +target_link_libraries(${PROJECT_NAME}_OBJECT setupapi wsock32 ws2_32 shlwapi iphlpapi) +endif() + target_sources(${PROJECT_NAME}_OBJECT PUBLIC ${${PROJECT_NAME}_HEADERS} diff --git a/libs/indibase/connectionplugins/connectionserial.cpp b/libs/indibase/connectionplugins/connectionserial.cpp index 4e2b2ef43e..dc47d581fd 100644 --- a/libs/indibase/connectionplugins/connectionserial.cpp +++ b/libs/indibase/connectionplugins/connectionserial.cpp @@ -30,6 +30,10 @@ #include #include +#ifdef _WIN32 +#include +#endif + namespace Connection { extern const char *CONNECTION_TAB; @@ -439,38 +443,72 @@ bool Serial::Refresh(bool silent) // 0 Serial Only, 1 By USB-ID, 2 Bluetooth auto searchPath = [&](std::string prefix, uint8_t searchType) - { - struct dirent **namelist; - std::vector detectedDevices; - int devCount = 0; - if (searchType == SERIAL_DEV) - devCount = scandir(prefix.c_str(), &namelist, serial_dev_file_select, alphasort); - else if (searchType == USB_ID_DEV) - devCount = scandir(prefix.c_str(), &namelist, usb_dev_file_select, alphasort); - else - devCount = scandir(prefix.c_str(), &namelist, bluetooth_dev_file_select, alphasort); - if (devCount > 0) { - while (devCount--) + struct dirent **namelist; + std::vector detectedDevices; + +#ifdef _WIN32 + WIN32_FIND_DATAA fileInfo; + HANDLE hFind = INVALID_HANDLE_VALUE; + std::string searchPattern; + + if (searchType == SERIAL_DEV) + searchPattern = prefix + "*"; + else if (searchType == USB_ID_DEV) + searchPattern = prefix + "usb*"; + else + searchPattern = prefix + "bluetooth*"; + + hFind = FindFirstFileA(searchPattern.c_str(), &fileInfo); + if (hFind != INVALID_HANDLE_VALUE) { - if (detectedDevices.size() < 10) + do { - std::string s(namelist[devCount]->d_name); - s.erase(s.find_last_not_of(" \n\r\t") + 1); - detectedDevices.push_back(prefix + s); - } - else + if (detectedDevices.size() < 10) + { + std::string deviceName(fileInfo.cFileName); + detectedDevices.push_back(prefix + deviceName); + } + else + { + LOGF_DEBUG("Ignoring devices over %d : %s", detectedDevices.size(), + fileInfo.cFileName); + } + } while (FindNextFileA(hFind, &fileInfo) != 0); + + FindClose(hFind); + } + +#else + int devCount = 0; + if (searchType == SERIAL_DEV) + devCount = scandir(prefix.c_str(), &namelist, serial_dev_file_select, alphasort); + else if (searchType == USB_ID_DEV) + devCount = scandir(prefix.c_str(), &namelist, usb_dev_file_select, alphasort); + else + devCount = scandir(prefix.c_str(), &namelist, bluetooth_dev_file_select, alphasort); + if (devCount > 0) + { + while (devCount--) { - LOGF_DEBUG("Ignoring devices over %d : %s", detectedDevices.size(), - namelist[devCount]->d_name); + if (detectedDevices.size() < 10) + { + std::string s(namelist[devCount]->d_name); + s.erase(s.find_last_not_of(" \n\r\t") + 1); + detectedDevices.push_back(prefix + s); + } + else + { + LOGF_DEBUG("Ignoring devices over %d : %s", detectedDevices.size(), + namelist[devCount]->d_name); + } + free(namelist[devCount]); } - free(namelist[devCount]); + free(namelist); } - free(namelist); - } - - return detectedDevices; - }; +#endif + return detectedDevices; + }; #ifdef __linux__ // Search for serial, usb, and bluetooth devices. diff --git a/libs/indibase/connectionplugins/connectiontcp.cpp b/libs/indibase/connectionplugins/connectiontcp.cpp index 73ffd59d96..b42a5c637f 100644 --- a/libs/indibase/connectionplugins/connectiontcp.cpp +++ b/libs/indibase/connectionplugins/connectiontcp.cpp @@ -23,7 +23,11 @@ #include "indistandardproperty.h" #include +#ifdef _WIN32 + +#else #include +#endif #include #include #include @@ -190,10 +194,26 @@ bool TCP::establishConnection(const std::string &hostname, const std::string &po return false; } - // Set the socket receiving and sending timeouts +#ifdef _WIN32 + if (setsockopt(m_SockFD, SOL_SOCKET, SO_RCVTIMEO, (const char*)&ts, sizeof(struct timeval)) < 0) + { + LOG_ERROR("Failed to set receive timeout."); + close(m_SockFD); + m_SockFD = -1; + return false; + } + + if (setsockopt(m_SockFD, SOL_SOCKET, SO_SNDTIMEO, (const char*)&ts, sizeof(struct timeval)) < 0) + { + LOG_ERROR("Failed to set send timeout."); + close(m_SockFD); + m_SockFD = -1; + return false; + } +#else setsockopt(m_SockFD, SOL_SOCKET, SO_RCVTIMEO, &ts, sizeof(struct timeval)); setsockopt(m_SockFD, SOL_SOCKET, SO_SNDTIMEO, &ts, sizeof(struct timeval)); - +#endif // Connect to the device if (::connect(m_SockFD, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { diff --git a/libs/indibase/indidome.cpp b/libs/indibase/indidome.cpp index 2356da0108..ed4704b8d1 100644 --- a/libs/indibase/indidome.cpp +++ b/libs/indibase/indidome.cpp @@ -35,10 +35,19 @@ #include #include #include -#include -#include #include #include +#include +#if __cplusplus >= 2017 +#include +#endif +#ifdef _WIN32 +#include +#include +#else +#include +#include +#endif #define DOME_SLAVING_TAB "Slaving" #define DOME_COORD_THRESHOLD \ @@ -77,6 +86,19 @@ Dome::~Dome() delete tcpConnection; } +#ifdef _WIN32 +std::string Dome::GetHomeDirectory() const +{ + PWSTR pszPath; + if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Profile, 0, NULL, &pszPath))) + { + std::wstring wstr(pszPath); + CoTaskMemFree(pszPath); + return std::string(wstr.begin(), wstr.end()); + } + return ""; +} +#else std::string Dome::GetHomeDirectory() const { // Check first the HOME environmental variable @@ -89,6 +111,7 @@ std::string Dome::GetHomeDirectory() const } return (HomeDir ? std::string(HomeDir) : ""); } +#endif bool Dome::initProperties() { @@ -1670,15 +1693,14 @@ bool Dome::InitPark() return true; } -const char * Dome::LoadParkXML() +const char* Dome::LoadParkXML() { - wordexp_t wexp; - FILE * fp; - LilXML * lp; + FILE* fp; + LilXML* lp; static char errmsg[512]; - XMLEle * parkxml; - XMLAtt * ap; + XMLEle* parkxml; + XMLAtt* ap; bool devicefound = false; ParkDeviceName = getDeviceName(); @@ -1687,18 +1709,18 @@ const char * Dome::LoadParkXML() ParkpositionXml = nullptr; ParkpositionAxis1Xml = nullptr; - if (wordexp(ParkDataFileName.c_str(), &wexp, 0)) + std::filesystem::path filePath(ParkDataFileName); + + if (!std::filesystem::exists(filePath)) { - wordfree(&wexp); - return "Badly formed filename."; + return "File does not exist."; } - if (!(fp = fopen(wexp.we_wordv[0], "r"))) + fp = std::fopen(filePath.string().c_str(), "r"); + if (!fp) { - wordfree(&wexp); return strerror(errno); } - wordfree(&wexp); lp = newLilXML(); @@ -1706,26 +1728,26 @@ const char * Dome::LoadParkXML() delXMLEle(ParkdataXmlRoot); ParkdataXmlRoot = readXMLFile(fp, lp, errmsg); - fclose(fp); + std::fclose(fp); delLilXML(lp); if (!ParkdataXmlRoot) return errmsg; - if (!strcmp(tagXMLEle(nextXMLEle(ParkdataXmlRoot, 1)), "parkdata")) + if (std::strcmp(tagXMLEle(nextXMLEle(ParkdataXmlRoot, 1)), "parkdata") == 0) return "Not a park data file"; parkxml = nextXMLEle(ParkdataXmlRoot, 1); while (parkxml) { - if (strcmp(tagXMLEle(parkxml), "device")) + if (std::strcmp(tagXMLEle(parkxml), "device") != 0) { parkxml = nextXMLEle(ParkdataXmlRoot, 0); continue; } ap = findXMLAtt(parkxml, "name"); - if (ap && (!strcmp(valuXMLAtt(ap), ParkDeviceName))) + if (ap && (std::strcmp(valuXMLAtt(ap), ParkDeviceName) == 0)) { devicefound = true; break; @@ -1793,24 +1815,39 @@ bool Dome::WriteParkData() if (LoadParkXML() != nullptr) LOG_DEBUG("Failed to refresh parking data."); - wordexp_t wexp; - FILE * fp; - char pcdata[30]; + std::string pcdata; ParkDeviceName = getDeviceName(); - if (wordexp(ParkDataFileName.c_str(), &wexp, 0)) + std::string expandedFileName; +#ifdef _WIN32 + { + std::vector buf(PATH_MAX); + DWORD len = ExpandEnvironmentStringsA(ParkDataFileName.c_str(), buf.data(), buf.size()); + if (len == 0 || len > buf.size()) + { + LOGF_INFO("WriteParkData: can not expand file name %s: Error occurred.", ParkDataFileName.c_str()); + return false; + } + expandedFileName = buf.data(); + } +#else { + wordexp_t wexp; + if (wordexp(ParkDataFileName.c_str(), &wexp, 0)) + { + wordfree(&wexp); + LOGF_INFO("WriteParkData: can not expand file name %s: Badly formed filename.", ParkDataFileName.c_str()); + return false; + } + expandedFileName = wexp.we_wordv[0]; wordfree(&wexp); - LOGF_INFO("WriteParkData: can not write file %s: Badly formed filename.", - ParkDataFileName.c_str()); - return false; } +#endif - if (!(fp = fopen(wexp.we_wordv[0], "w"))) + FILE* fp = fopen(expandedFileName.c_str(), "w"); + if (!fp) { - wordfree(&wexp); - LOGF_INFO("WriteParkData: can not write file %s: %s", ParkDataFileName.c_str(), - strerror(errno)); + LOGF_INFO("WriteParkData: can not write file %s: %s", expandedFileName.c_str(), strerror(errno)); return false; } @@ -1837,13 +1874,12 @@ bool Dome::WriteParkData() if (parkDataType != PARK_NONE) { - snprintf(pcdata, sizeof(pcdata), "%lf", Axis1ParkPosition); - editXMLEle(ParkpositionAxis1Xml, pcdata); + pcdata = std::to_string(Axis1ParkPosition); + editXMLEle(ParkpositionAxis1Xml, pcdata.c_str()); } prXMLEle(fp, ParkdataXmlRoot, 0); fclose(fp); - wordfree(&wexp); return true; } diff --git a/libs/indibase/indidriver.c b/libs/indibase/indidriver.c index 12801c7e3f..526fb94506 100644 --- a/libs/indibase/indidriver.c +++ b/libs/indibase/indidriver.c @@ -38,8 +38,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301 USA #include #include #include -#include +#ifdef _WIN32 +#include +#include +#define mkdir(dir) _mkdir(dir) +#endif #include +#include #include #include "userio.h" @@ -1022,7 +1027,9 @@ FILE *IUGetConfigFP(const char *filename, const char *dev, const char *mode, cha struct stat st; FILE *fp = NULL; - snprintf(configDir, MAXRBUF, "%s/.indi/", getenv("HOME")); + char *homeDir = getenv("HOME"); + + snprintf(configDir, MAXRBUF, "%s/.indi/", homeDir); if (filename) strncpy(configFileName, filename, MAXRBUF); @@ -1034,18 +1041,28 @@ FILE *IUGetConfigFP(const char *filename, const char *dev, const char *mode, cha snprintf(configFileName, MAXRBUF, "%s%s_config.xml", configDir, dev); } - if (stat(configDir, &st) != 0) + #ifdef _WIN32 + if (_stat(configDir, &st) != 0) + #else + if (stat(configDir, &st) != 0) + #endif { - if (mkdir(configDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) + #ifdef _WIN32 + if (mkdir(configDir) != 0) + #else + if (mkdir(configDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) + #endif { - snprintf(errmsg, MAXRBUF, "Unable to create config directory. Error %s: %s", configDir, strerror(errno)); + snprintf(errmsg, MAXRBUF, "Unable to create config directory. Error: %s", strerror(errno)); return NULL; } } - stat(configFileName, &st); - /* If file is owned by root and current user is NOT root then abort */ - if ( (st.st_uid == 0 && getuid() != 0) || (st.st_gid == 0 && getgid() != 0) ) + #ifdef _WIN32 + if (_stat(configFileName, &st) == 0 && (st.st_uid == 0 || st.st_gid == 0)) + #else + if (stat(configFileName, &st) == 0 && (st.st_uid == 0 || st.st_gid == 0)) + #endif { strncpy(errmsg, "Config file is owned by root! This will lead to serious errors. To fix this, run: sudo chown -R $USER:$USER ~/.indi", @@ -1053,11 +1070,11 @@ FILE *IUGetConfigFP(const char *filename, const char *dev, const char *mode, cha return NULL; } + // 打开配置文件 fp = fopen(configFileName, mode); if (fp == NULL) { - snprintf(errmsg, MAXRBUF, "Unable to open config file. Error loading file %s: %s", configFileName, - strerror(errno)); + snprintf(errmsg, MAXRBUF, "Unable to open config file. Error loading file %s: %s", configFileName, strerror(errno)); return NULL; } diff --git a/libs/indibase/indidriverio.c b/libs/indibase/indidriverio.c index 8670175a3b..2a2a6c2eb0 100644 --- a/libs/indibase/indidriverio.c +++ b/libs/indibase/indidriverio.c @@ -29,8 +29,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301 USA #include #include #include +#ifdef _WIN32 +#include +#include +#else #include #include +#endif #include #include @@ -51,7 +56,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301 USA static void driverio_flush(driverio * dio, const void * additional, size_t add_size); +#ifdef _WIN32 +static CRITICAL_SECTION stdout_mutex; +#else static pthread_mutex_t stdout_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif /* Return the buffer size required for storage (rounded to next OUTPUTBUFF_ALLOC) */ static unsigned int outBuffRequired(unsigned int storage) @@ -137,7 +146,67 @@ static void driverio_join(void * user, const char * xml, void * blob, size_t blo driverio_write(user, xml, strlen(xml)); } +#ifdef _WIN32 +static void driverio_flush(driverio* dio, const void* additional, size_t add_size) +{ + WSABUF iov[2]; + DWORD bytesSent; + WSAMSG wsa_msg; + + if (dio->outPos + add_size) + { + iov[0].buf = dio->outBuff; + iov[0].len = dio->outPos; + if (add_size) + { + iov[1].buf = (char*)additional; + iov[1].len = add_size; + } + + memset(&wsa_msg, 0, sizeof(wsa_msg)); + wsa_msg.name = NULL; + wsa_msg.namelen = 0; + wsa_msg.lpBuffers = iov; + wsa_msg.dwBufferCount = (add_size ? 2 : 1); + if (!dio->locked) + { + InitializeCriticalSection(&stdout_mutex); + dio->locked = 1; + } + + if (WSASendMsg(1, &wsa_msg, 0, &bytesSent, NULL, NULL) == SOCKET_ERROR) + { + fprintf(stderr, "WSASendMsg failed: %d\n", WSAGetLastError()); + exit(1); + } + else if (bytesSent != dio->outPos + add_size) + { + // This is not expected on blocking socket + fprintf(stderr, "short write\n"); + exit(1); + } + } + + if (dio->joins != NULL) + { + free(dio->joins); + } + dio->joins = NULL; + + if (dio->joinSizes != NULL) + { + free(dio->joinSizes); + } + dio->joinSizes = NULL; + + if (dio->outBuff != NULL) + { + free(dio->outBuff); + } + dio->outPos = 0; +} +#else static void driverio_flush(driverio * dio, const void * additional, size_t add_size) { struct msghdr msgh; @@ -267,7 +336,7 @@ static void driverio_flush(driverio * dio, const void * additional, size_t add_s dio->outPos = 0; } - +#endif static int driverio_is_unix = -1; @@ -276,27 +345,19 @@ static int is_unix_io() #ifndef ENABLE_INDI_SHARED_MEMORY return 0; #endif - if (driverio_is_unix != -1) - { - return driverio_is_unix; - } -#ifdef SO_DOMAIN - int domain; - socklen_t result = sizeof(domain); + int driverio_is_unix = -1; - if (getsockopt(1, SOL_SOCKET, SO_DOMAIN, (void*)&domain, &result) == -1) - { - driverio_is_unix = 0; - } - else if (result != sizeof(domain) || domain != AF_UNIX) +#ifdef _WIN32 + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { driverio_is_unix = 0; + return driverio_is_unix; } - else - { - driverio_is_unix = 1; - } + + driverio_is_unix = 0; + #else struct sockaddr_un sockName; socklen_t sockNameLen = sizeof(sockName); @@ -313,7 +374,9 @@ static int is_unix_io() { driverio_is_unix = 0; } + #endif + return driverio_is_unix; } @@ -332,28 +395,41 @@ static void driverio_init_unix(driverio * dio) dio->outPos = 0; } -static void driverio_finish_unix(driverio * dio) +static void driverio_finish_unix(driverio* dio) { driverio_flush(dio, NULL, 0); if (dio->locked) { +#ifdef _WIN32 + LeaveCriticalSection(&stdout_mutex); +#else pthread_mutex_unlock(&stdout_mutex); +#endif dio->locked = 0; } } -static void driverio_init_stdout(driverio * dio) +static void driverio_init_stdout(driverio* dio) { dio->userio = *userio_file(); dio->user = stdout; +#ifdef _WIN32 + InitializeCriticalSection(&stdout_mutex); + EnterCriticalSection(&stdout_mutex); +#else pthread_mutex_lock(&stdout_mutex); +#endif } -static void driverio_finish_stdout(driverio * dio) +static void driverio_finish_stdout(driverio* dio) { (void)dio; fflush(stdout); +#ifdef _WIN32 + LeaveCriticalSection(&stdout_mutex); +#else pthread_mutex_unlock(&stdout_mutex); +#endif } void driverio_init(driverio * dio) diff --git a/libs/indibase/indidrivermain.c b/libs/indibase/indidrivermain.c index dc9d5507b3..d52242a853 100644 --- a/libs/indibase/indidrivermain.c +++ b/libs/indibase/indidrivermain.c @@ -47,6 +47,11 @@ #include #include +#ifdef _WIN32 +#include +#include +#endif + #define MAXRBUF 2048 static void usage(void); @@ -249,24 +254,30 @@ static void waitPingReplyFromEventLoopThread(const char * uid) { pthread_mutex_unlock(&pingReplyMutex); } -static void waitPingReplyFromOtherThread(const char * uid) { +static void waitPingReplyFromOtherThread(const char* uid) { int fd = 0; fd_set rfd; - messageHandling = PROCEED_DEFERRED; + messageHandling = 0; pthread_mutex_lock(&pingReplyMutex); - while(!consumePingReply(uid)) - { + while (!consumePingReply(uid)) { pthread_mutex_unlock(&pingReplyMutex); FD_ZERO(&rfd); FD_SET(fd, &rfd); +#ifdef _WIN32 int ns = select(fd + 1, &rfd, NULL, NULL, NULL); - if (ns < 0) - { +#else + int ns = pselect(fd + 1, &rfd, NULL, NULL, NULL, NULL); +#endif + + if (ns < 0) { perror("select"); +#ifdef _WIN32 + WSACleanup(); +#endif exit(1); } @@ -275,7 +286,12 @@ static void waitPingReplyFromOtherThread(const char * uid) { pthread_mutex_lock(&pingReplyMutex); } pthread_mutex_unlock(&pingReplyMutex); - messageHandling = PROCEED_IMMEDIATE; + messageHandling = 1; + +#ifdef _WIN32 + WSACleanup(); +#endif + } void waitPingReply(const char * uid) { diff --git a/libs/indibase/indilogger.cpp b/libs/indibase/indilogger.cpp index 80c806b8a1..743794618a 100644 --- a/libs/indibase/indilogger.cpp +++ b/libs/indibase/indilogger.cpp @@ -369,6 +369,20 @@ unsigned int Logger::rank(unsigned int l) } } +#ifdef _WIN32 +#include +void timersub(const struct timeval *t1, const struct timeval *t2, struct timeval *res) +{ + res->tv_sec = t1->tv_sec - t2->tv_sec; + res->tv_usec = t1->tv_usec - t2->tv_usec; + if (res->tv_usec < 0) { + res->tv_sec--; + res->tv_usec += 1000000; + } +} + +#endif + void Logger::print(const char *devicename, const unsigned int verbosityLevel, const std::string &file, const int line, //const std::string& message, const char *message, ...) diff --git a/libs/indibase/inditelescope.cpp b/libs/indibase/inditelescope.cpp index 0277951551..94a9f75b26 100644 --- a/libs/indibase/inditelescope.cpp +++ b/libs/indibase/inditelescope.cpp @@ -28,13 +28,20 @@ #include #include -#include #include #include #include #include -#include #include +#include +#ifdef _WIN32 +#include +#include +#include +#else +#include +#include +#endif namespace INDI { @@ -2014,8 +2021,6 @@ bool Telescope::InitPark() const char *Telescope::LoadParkXML() { - wordexp_t wexp; - FILE *fp = nullptr; LilXML *lp = nullptr; static char errmsg[512]; @@ -2030,18 +2035,41 @@ const char *Telescope::LoadParkXML() ParkpositionAxis1Xml = nullptr; ParkpositionAxis2Xml = nullptr; +#ifdef _WIN32 + wchar_t drive[_MAX_DRIVE]; + wchar_t dir[_MAX_DIR]; + wchar_t filename[_MAX_FNAME]; + wchar_t extension[_MAX_EXT]; + wchar_t wfilename[MAX_PATH]; + if (MultiByteToWideChar(CP_UTF8, 0, ParkDataFileName.c_str(), -1, wfilename, MAX_PATH) == 0) + { + return "Badly formed filename."; + } + _wsplitpath_s(wfilename, drive, dir, filename, extension); + wchar_t wcPath[MAX_PATH]; + PathCombineW(wcPath, drive, dir); + std::wstring path(wcPath); + std::string newPath(path.begin(), path.end()); + FILE *fp = nullptr; + if (!(fp = fopen(newPath.c_str(), "r"))) + { + return strerror(errno); + } + #else + wordexp_t wexp; + FILE *fp = nullptr; if (wordexp(ParkDataFileName.c_str(), &wexp, 0)) { wordfree(&wexp); return "Badly formed filename."; } - if (!(fp = fopen(wexp.we_wordv[0], "r"))) { wordfree(&wexp); return strerror(errno); } wordfree(&wexp); + #endif lp = newLilXML(); @@ -2139,6 +2167,24 @@ const char *Telescope::LoadParkData() return "Failed to parse Park Position."; } +#ifdef _WIN32 +LPCWSTR ConvertToLPCWSTR(const char* str) +{ + int bufferSize = MultiByteToWideChar(CP_UTF8, 0, str, -1, nullptr, 0); + if (bufferSize == 0) + { + return nullptr; + } + wchar_t* buffer = new wchar_t[bufferSize]; + if (MultiByteToWideChar(CP_UTF8, 0, str, -1, buffer, bufferSize) == 0) + { + delete[] buffer; + return nullptr; + } + return buffer; +} +#endif + bool Telescope::PurgeParkData() { // We need to refresh parking data in case other devices parking states were updated since we @@ -2146,23 +2192,29 @@ bool Telescope::PurgeParkData() if (LoadParkXML() != nullptr) LOG_DEBUG("Failed to refresh parking data."); +#ifdef _WIN32 + wchar_t wcPath[MAX_PATH]; + if (!PathCombineW(wcPath, L".", ConvertToLPCWSTR(ParkDataFileName.c_str()))) + { + LOG_ERROR("Failed to purdge park data: Path combination failed."); + return false; + } + std::wstring wPath(wcPath); + std::string newPath(wPath.begin(), wPath.end()); + FILE *fp = nullptr; + if (!(fp = fopen(newPath.c_str(), "r"))) + { + LOGF_ERROR("Failed to purge park data: %s", strerror(errno)); + return false; + } +#else wordexp_t wexp; FILE *fp = nullptr; - LilXML *lp = nullptr; - static char errmsg[512]; - - XMLEle *parkxml = nullptr; - XMLAtt *ap = nullptr; - bool devicefound = false; - - ParkDeviceName = getDeviceName(); - if (wordexp(ParkDataFileName.c_str(), &wexp, 0)) { wordfree(&wexp); return false; } - if (!(fp = fopen(wexp.we_wordv[0], "r"))) { wordfree(&wexp); @@ -2170,6 +2222,16 @@ bool Telescope::PurgeParkData() return false; } wordfree(&wexp); +#endif + + LilXML *lp = nullptr; + static char errmsg[512]; + + XMLEle *parkxml = nullptr; + XMLAtt *ap = nullptr; + bool devicefound = false; + + ParkDeviceName = getDeviceName(); lp = newLilXML(); @@ -2215,22 +2277,28 @@ bool Telescope::PurgeParkData() delXMLEle(parkxml); - ParkstatusXml = nullptr; - ParkdeviceXml = nullptr; - ParkpositionXml = nullptr; + ParkstatusXml = nullptr; + ParkdeviceXml = nullptr; + ParkpositionXml = nullptr; ParkpositionAxis1Xml = nullptr; ParkpositionAxis2Xml = nullptr; - wordexp(ParkDataFileName.c_str(), &wexp, 0); +#ifdef _WIN32 + if (!(fp = fopen(newPath.c_str(), "w"))) + { + LOGF_INFO("WriteParkData: can not write file %s: %s", ParkDataFileName.c_str(), strerror(errno)); + return false; + } +#else if (!(fp = fopen(wexp.we_wordv[0], "w"))) { - wordfree(&wexp); LOGF_INFO("WriteParkData: can not write file %s: %s", ParkDataFileName.c_str(), strerror(errno)); return false; } +#endif + prXMLEle(fp, ParkdataXmlRoot, 0); fclose(fp); - wordfree(&wexp); return true; } @@ -2242,11 +2310,33 @@ bool Telescope::WriteParkData() if (LoadParkXML() != nullptr) LOG_DEBUG("Failed to refresh parking data."); +#ifdef _WIN32 + wchar_t drive[_MAX_DRIVE]; + wchar_t dir[_MAX_DIR]; + wchar_t filename[_MAX_FNAME]; + wchar_t extension[_MAX_EXT]; + wchar_t wfilename[MAX_PATH]; + if (MultiByteToWideChar(CP_UTF8, 0, ParkDataFileName.c_str(), -1, wfilename, MAX_PATH) == 0) + { + LOGF_INFO("WriteParkData: can not write file %s: Badly formed filename.", + ParkDataFileName.c_str()); + return false; + } + _wsplitpath_s(wfilename, drive, dir, filename, extension); + wchar_t wcPath[MAX_PATH]; + PathCombineW(wcPath, drive, dir); + std::wstring path(wcPath); + std::string newPath(path.begin(), path.end()); + FILE *fp = nullptr; + if (!(fp = fopen(newPath.c_str(), "w"))) + { + LOGF_INFO("WriteParkData: can not write file %s: %s", ParkDataFileName.c_str(), + strerror(errno)); + return false; + } +#else wordexp_t wexp; - FILE *fp; - char pcdata[30]; - ParkDeviceName = getDeviceName(); - + FILE *fp = nullptr; if (wordexp(ParkDataFileName.c_str(), &wexp, 0)) { wordfree(&wexp); @@ -2254,7 +2344,6 @@ bool Telescope::WriteParkData() ParkDataFileName.c_str()); return false; } - if (!(fp = fopen(wexp.we_wordv[0], "w"))) { wordfree(&wexp); @@ -2262,6 +2351,11 @@ bool Telescope::WriteParkData() strerror(errno)); return false; } + wordfree(&wexp); +#endif + + char pcdata[30]; + ParkDeviceName = getDeviceName(); if (!ParkdataXmlRoot) ParkdataXmlRoot = addXMLEle(nullptr, "parkdata"); @@ -2290,7 +2384,6 @@ bool Telescope::WriteParkData() prXMLEle(fp, ParkdataXmlRoot, 0); fclose(fp); - wordfree(&wexp); return true; } @@ -3034,15 +3127,49 @@ bool Telescope::UpdateScopeConfig() std::string Telescope::GetHomeDirectory() const { - // Check first the HOME environmental variable - const char *HomeDir = getenv("HOME"); + std::string homeDir; - // ...otherwise get the home directory of the current user. - if (!HomeDir) +#ifdef _WIN32 + wchar_t* wideBuffer = nullptr; + if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Profile, 0, nullptr, &wideBuffer))) + { + char utf8Buffer[MAX_PATH]; + WideCharToMultiByte(CP_UTF8, 0, wideBuffer, -1, utf8Buffer, sizeof(utf8Buffer), nullptr, nullptr); + CoTaskMemFree(wideBuffer); + homeDir = utf8Buffer; + } +#elif __linux__ + const char* homeEnv = getenv("HOME"); + if (homeEnv) + { + homeDir = homeEnv; + } + else { - HomeDir = getpwuid(getuid())->pw_dir; + struct passwd* pw = getpwuid(getuid()); + if (pw && pw->pw_dir) + { + homeDir = pw->pw_dir; + } } - return (HomeDir ? std::string(HomeDir) : ""); +#elif __APPLE__ + const char* homeEnv = getenv("HOME"); + if (homeEnv) + { + homeDir = homeEnv; + } + else + { + uid_t uid = getuid(); + struct passwd* pw = getpwuid(uid); + if (pw && pw->pw_dir) + { + homeDir = pw->pw_dir; + } + } +#endif + + return homeDir; } int Telescope::GetScopeConfigIndex() const @@ -3090,14 +3217,17 @@ void Telescope::sendTimeFromSystem() { char ts[32] = {0}; - std::time_t t = std::time(nullptr); - struct std::tm *utctimeinfo = std::gmtime(&t); + auto now = std::chrono::system_clock::now(); + std::time_t t = std::chrono::system_clock::to_time_t(now); + struct std::tm* utctimeinfo = std::gmtime(&t); strftime(ts, sizeof(ts), "%Y-%m-%dT%H:%M:%S", utctimeinfo); IUSaveText(&TimeT[0], ts); - struct std::tm *localtimeinfo = std::localtime(&t); - snprintf(ts, sizeof(ts), "%4.2f", (localtimeinfo->tm_gmtoff / 3600.0)); + auto local_time = std::chrono::system_clock::to_time_t(now); + auto utc_time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::from_time_t(t)); + double gmtoff = (std::difftime(local_time, utc_time) / 3600.0); + snprintf(ts, sizeof(ts), "%4.2f", gmtoff); IUSaveText(&TimeT[1], ts); TimeTP.s = IPS_OK; diff --git a/libs/indicore/CMakeLists.txt b/libs/indicore/CMakeLists.txt index 36651011cf..ffd4fada56 100644 --- a/libs/indicore/CMakeLists.txt +++ b/libs/indicore/CMakeLists.txt @@ -1,17 +1,18 @@ cmake_minimum_required(VERSION 3.13) project(indicore C CXX) -if(NOT WIN32) - find_package(Nova) -endif() +find_package(Nova) add_library(${PROJECT_NAME} OBJECT "") +if(WIN32) + +else() set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) check_symbol_exists(mremap sys/mman.h HAVE_MREMAP) check_symbol_exists(timespec_get time.h HAVE_TIMESPEC_GET) check_symbol_exists(clock_gettime time.h HAVE_CLOCK_GETTIME) - +endif() configure_file(indiapi.h.in indiapi.h @ONLY) # Headers @@ -43,15 +44,13 @@ list(APPEND ${PROJECT_NAME}_SOURCES indiuserio.c ) -if(UNIX) - list(APPEND ${PROJECT_NAME}_PRIVATE_HEADERS - sharedblob_parse.h - shm_open_anon.h) - list(APPEND ${PROJECT_NAME}_SOURCES - sharedblob.c - sharedblob_parse.cpp - shm_open_anon.c) -endif() +list(APPEND ${PROJECT_NAME}_PRIVATE_HEADERS + sharedblob_parse.h + shm_open_anon.h) +list(APPEND ${PROJECT_NAME}_SOURCES + sharedblob.c + sharedblob_parse.cpp + shm_open_anon.c) target_compile_definitions(${PROJECT_NAME} PUBLIC diff --git a/libs/indicore/indicom.c b/libs/indicore/indicom.c index c68537f4db..b9ff4bd82d 100644 --- a/libs/indicore/indicom.c +++ b/libs/indicore/indicom.c @@ -78,6 +78,7 @@ #ifdef _WIN32 #undef CX #undef CY +#include #endif #ifndef _WIN32 @@ -108,6 +109,36 @@ static int tty_sequence_number = 1; static int tty_clear_trailing_lf = 0; #if defined(HAVE_LIBNOVA) +#ifdef _WIN32 +int extractISOTime(const char *timestr, struct ln_date *iso_date) +{ + // Convert timestr to SYSTEMTIME + SYSTEMTIME st; + memset(&st, 0, sizeof(st)); + + sscanf_s(timestr, "%4d-%2d-%2dT%2d:%2d:%2d", + &st.wYear, &st.wMonth, &st.wDay, &st.wHour, &st.wMinute, &st.wSecond); + + // Convert SYSTEMTIME to FILETIME + FILETIME ft; + SystemTimeToFileTime(&st, &ft); + + // Convert FILETIME to time_t + ULARGE_INTEGER uli; + uli.LowPart = ft.dwLowDateTime; + uli.HighPart = ft.dwHighDateTime; + + time_t tt = (uli.QuadPart - 116444736000000000) / 10000000; + + // Convert time_t to struct tm + struct tm *utm = localtime(&tt); + if (!utm) + return -1; + + ln_get_date_from_tm(utm, iso_date); + return 0; +} +#else int extractISOTime(const char *timestr, struct ln_date *iso_date) { struct tm utm; @@ -127,6 +158,7 @@ int extractISOTime(const char *timestr, struct ln_date *iso_date) return (-1); } #endif +#endif /* sprint the variable a in sexagesimal format into out[]. * w is the number of spaces for the whole part. diff --git a/libs/indicore/indicom.h b/libs/indicore/indicom.h index 378c166964..f98693cf83 100644 --- a/libs/indicore/indicom.h +++ b/libs/indicore/indicom.h @@ -322,9 +322,7 @@ int f_scansexa(const char *str0, double *dp); * \param iso_date a pointer to a \e ln_date structure to store the extracted time and date (libnova). * \return 0 on success, -1 on failure. */ -#ifndef _WIN32 int extractISOTime(const char *timestr, struct ln_date *iso_date); -#endif void getSexComponents(double value, int *d, int *m, int *s); void getSexComponentsIID(double value, int *d, int *m, double *s); diff --git a/libs/indicore/sharedblob.c b/libs/indicore/sharedblob.c index df0af41b7a..52bd43c29a 100644 --- a/libs/indicore/sharedblob.c +++ b/libs/indicore/sharedblob.c @@ -31,8 +31,11 @@ #include #include #include +#ifdef _WIN32 +#include +#else #include - +#endif #ifdef ENABLE_INDI_SHARED_MEMORY #include "shm_open_anon.h" #endif @@ -44,7 +47,10 @@ static pthread_mutex_t shared_buffer_mutex = PTHREAD_MUTEX_INITIALIZER; typedef struct shared_buffer { - void * mapstart; +#ifdef _WIN32 + HANDLE hMapObject; +#endif + void* mapstart; size_t size; size_t allocated; int fd; @@ -66,116 +72,219 @@ static void sharedBufferAdd(shared_buffer * sb); static shared_buffer * sharedBufferRemove(void * mapstart); static shared_buffer * sharedBufferFind(void * mapstart); - -void * IDSharedBlobAlloc(size_t size) -{ +void* IDSharedBlobAlloc(size_t size) { #ifdef ENABLE_INDI_SHARED_MEMORY - shared_buffer * sb = (shared_buffer*)malloc(sizeof(shared_buffer)); - if (sb == NULL) goto ERROR; + shared_buffer* sb = (shared_buffer*)malloc(sizeof(shared_buffer)); + if (sb == NULL) { + // 错误处理逻辑 + goto ERROR_LABEL; + } sb->size = size; sb->allocated = allocation(size); sb->sealed = 0; - sb->fd = shm_open_anon(); - if (sb->fd == -1) goto ERROR; + sb->fd = -1; + +#ifdef _WIN32 + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + + sb->hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, sb->allocated, NULL); + if (sb->hMapObject == NULL) { + // 错误处理逻辑 + goto ERROR_LABEL; + } + + sb->mapstart = MapViewOfFile(sb->hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, sb->allocated); + if (sb->mapstart == NULL) { + // 错误处理逻辑 + goto ERROR_LABEL; + } +#else + sb->fd = shm_open("/mysharedmem", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if (sb->fd == -1) { + // 错误处理逻辑 + goto ERROR_LABEL; + } int ret = ftruncate(sb->fd, sb->allocated); - if (ret == -1) goto ERROR; + if (ret == -1) { + // 错误处理逻辑 + goto ERROR_LABEL; + } - // FIXME: try to map far more than sb->allocated, to allow efficient mremap - sb->mapstart = mmap(0, sb->allocated, PROT_READ | PROT_WRITE, MAP_SHARED, sb->fd, 0); - if (sb->mapstart == MAP_FAILED) goto ERROR; + sb->mapstart = mmap(NULL, sb->allocated, PROT_READ | PROT_WRITE, MAP_SHARED, sb->fd, 0); + if (sb->mapstart == MAP_FAILED) { + // 错误处理逻辑 + goto ERROR_LABEL; + } +#endif sharedBufferAdd(sb); + // 返回正常的结果 return sb->mapstart; -ERROR: - if (sb) - { + +ERROR_LABEL: + if (sb) { +#ifdef _WIN32 + DWORD e = GetLastError(); + if (sb->mapstart) UnmapViewOfFile(sb->mapstart); + if (sb->hMapObject) CloseHandle(sb->hMapObject); +#else int e = errno; + if (sb->mapstart) munmap(sb->mapstart, sb->allocated); if (sb->fd != -1) close(sb->fd); +#endif free(sb); +#ifdef _WIN32 + SetLastError(e); +#else errno = e; +#endif } + + // 返回错误结果 return NULL; #else return malloc(size); #endif } -void * IDSharedBlobAttach(int fd, size_t size) -{ - shared_buffer * sb = (shared_buffer*)malloc(sizeof(shared_buffer)); - if (sb == NULL) goto ERROR; +#ifdef _WIN32 +void* IDSharedBlobAttach(int fd, size_t size) { + shared_buffer* sb = (shared_buffer*)malloc(sizeof(shared_buffer)); + if (sb == NULL) goto ERROR_LABEL; sb->fd = fd; sb->size = size; sb->allocated = size; sb->sealed = 1; - sb->mapstart = mmap(0, sb->allocated, PROT_READ, MAP_SHARED, sb->fd, 0); - if (sb->mapstart == MAP_FAILED) goto ERROR; + sb->mapstart = MapViewOfFile((HANDLE)_get_osfhandle(fd), FILE_MAP_READ, 0, 0, size); + if (sb->mapstart == NULL) goto ERROR_LABEL; sharedBufferAdd(sb); return sb->mapstart; -ERROR: - if (sb) - { + +ERROR_LABEL: + if (sb) { + DWORD e = GetLastError(); + free(sb); + SetLastError(e); + } + return NULL; +} +#else +void* IDSharedBlobAttach(int fd, size_t size) { + shared_buffer* sb = (shared_buffer*)malloc(sizeof(shared_buffer)); + if (sb == NULL) goto ERROR_LABEL; + sb->fd = fd; + sb->size = size; + sb->allocated = size; + sb->sealed = 1; + + sb->mapstart = mmap(NULL, sb->allocated, PROT_READ, MAP_SHARED, sb->fd, 0); + if (sb->mapstart == MAP_FAILED) goto ERROR_LABEL; + + sharedBufferAdd(sb); + + return sb->mapstart; + +ERROR_LABEL: + if (sb) { int e = errno; free(sb); errno = e; } return NULL; } +#endif +#ifdef _WIN32 +void IDSharedBlobFree(void* ptr) { + shared_buffer* sb = sharedBufferRemove(ptr); + if (sb == NULL) { + // 不是连接到共享内存的内存块 + free(ptr); + return; + } -void IDSharedBlobFree(void * ptr) -{ - shared_buffer * sb = sharedBufferRemove(ptr); - if (sb == NULL) - { - // Not a memory attached to a blob + if (!UnmapViewOfFile(sb->mapstart)) { + perror("shared buffer UnmapViewOfFile"); + _exit(1); + } + if (!CloseHandle(sb->hMapObject)) { + perror("shared buffer CloseHandle"); + } + free(sb); +} +#else +void IDSharedBlobFree(void* ptr) { + shared_buffer* sb = sharedBufferRemove(ptr); + if (sb == NULL) { + // 不是连接到共享内存的内存块 free(ptr); return; } - if (munmap(sb->mapstart, sb->allocated) == -1) - { + if (munmap(sb->mapstart, sb->allocated) == -1) { perror("shared buffer munmap"); _exit(1); } - if (close(sb->fd) == -1) - { + if (close(sb->fd) == -1) { perror("shared buffer close"); } free(sb); } +#endif -void IDSharedBlobDettach(void * ptr) +#ifdef _WIN32 +void IDSharedBlobDettach(void* ptr) { - shared_buffer * sb = sharedBufferRemove(ptr); + shared_buffer* sb = sharedBufferRemove(ptr); + if (sb == NULL) + { + free(ptr); + return; + } + if (UnmapViewOfFile(sb->mapstart) == 0) + { + perror("shared buffer UnmapViewOfFile"); + exit(1); + } + free(sb); +} +#else +void IDSharedBlobDettach(void* ptr) +{ + shared_buffer* sb = sharedBufferRemove(ptr); if (sb == NULL) { - // Not a memory attached to a blob free(ptr); return; } if (munmap(sb->mapstart, sb->allocated) == -1) { perror("shared buffer munmap"); - _exit(1); + exit(1); } free(sb); } +#endif + -void * IDSharedBlobRealloc(void * ptr, size_t size) +#ifdef _WIN32 +void* IDSharedBlobRealloc(void* ptr, size_t size) { if (ptr == NULL) { return IDSharedBlobAlloc(size); } - shared_buffer * sb; + shared_buffer* sb; sb = sharedBufferFind(ptr); if (sb == NULL) @@ -192,7 +301,7 @@ void * IDSharedBlobRealloc(void * ptr, size_t size) if (sb->size >= size) { - // Shrinking is not implemented + // 缩小尺寸未实现 sb->size = size; return ptr; } @@ -204,39 +313,119 @@ void * IDSharedBlobRealloc(void * ptr, size_t size) return ptr; } - int ret = ftruncate(sb->fd, reallocated); - if (ret == -1) return NULL; + // 在Windows平台上使用VirtualAlloc重新分配内存,需要先取消当前内存映射,再重新映射 + if (UnmapViewOfFile(sb->mapstart) == 0) + { + perror("shared buffer UnmapViewOfFile"); + _exit(1); + } + void* remapped = VirtualAlloc(NULL, reallocated, MEM_COMMIT, PAGE_READWRITE); + if (remapped == NULL) + { + perror("shared buffer VirtualAlloc"); + _exit(1); + } + void* ret = MapViewOfFileEx(sb->hMapObject, FILE_MAP_WRITE, 0, 0, 0, remapped); + if (ret == NULL) + { + perror("shared buffer MapViewOfFileEx"); + _exit(1); + } -#ifdef HAVE_MREMAP - void * remaped = mremap(sb->mapstart, sb->allocated, reallocated, MREMAP_MAYMOVE); - if (remaped == MAP_FAILED) return NULL; + sb->size = size; + sb->allocated = reallocated; + sb->mapstart = remapped; + + return remapped; +} + +static void seal(shared_buffer* sb) +{ + void* ret = MapViewOfFileEx(sb->hMapObject, FILE_MAP_READ, 0, 0, 0, sb->mapstart); + if (ret == NULL) + { + perror("remap readonly failed"); + _exit(1); + } + sb->sealed = 1; +} +#else +void* IDSharedBlobRealloc(void* ptr, size_t size) +{ + if (ptr == NULL) + { + return IDSharedBlobAlloc(size); + } + + shared_buffer* sb; + sb = sharedBufferFind(ptr); + + if (sb == NULL) + { + return realloc(ptr, size); + } + + if (sb->sealed) + { + IDSharedBlobFree(ptr); + errno = EROFS; + return NULL; + } + + if (sb->size >= size) + { + // 缩小尺寸未实现 + sb->size = size; + return ptr; + } + size_t reallocated = allocation(size); + if (reallocated == sb->allocated) + { + sb->size = size; + return ptr; + } + +#ifdef HAVE_MREMAP + void* remapped = mremap(sb->mapstart, sb->allocated, reallocated, MREMAP_MAYMOVE); + if (remapped == MAP_FAILED) + { + perror("shared buffer mremap"); + _exit(1); + } #else - // compatibility path for MACOS + // 兼容MACOS平台的路径 if (munmap(sb->mapstart, sb->allocated) == -1) { perror("shared buffer munmap"); _exit(1); } - void * remaped = mmap(0, reallocated, PROT_READ | PROT_WRITE, MAP_SHARED, sb->fd, 0); - if (remaped == MAP_FAILED) return NULL; + void* remapped = mmap(0, reallocated, PROT_READ | PROT_WRITE, MAP_SHARED, sb->fd, 0); + if (remapped == MAP_FAILED) + { + perror("shared buffer mmap"); + _exit(1); + } #endif + sb->size = size; sb->allocated = reallocated; - sb->mapstart = remaped; + sb->mapstart = remapped; - return remaped; + return remapped; } -static void seal(shared_buffer * sb) +static void seal(shared_buffer* sb) { - void * ret = mmap(sb->mapstart, sb->allocated, PROT_READ, MAP_SHARED | MAP_FIXED, sb->fd, 0); + void* ret = mmap(sb->mapstart, sb->allocated, PROT_READ, MAP_SHARED | MAP_FIXED, sb->fd, 0); if (ret == MAP_FAILED) { perror("remap readonly failed"); + _exit(1); } sb->sealed = 1; } +#endif int IDSharedBlobGetFd(void * ptr) { diff --git a/libs/indicore/shm_open_anon.c b/libs/indicore/shm_open_anon.c index a56980af93..4b2821eb37 100644 --- a/libs/indicore/shm_open_anon.c +++ b/libs/indicore/shm_open_anon.c @@ -10,9 +10,9 @@ #endif #include - +#ifndef _WIN32 #include - +#endif #include #include #include diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 09e6c13546..75b75da21d 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,20 +1,20 @@ # ########## getINDI ############## add_executable(indi_getprop getINDIproperty.c) -target_link_libraries(indi_getprop indicore eventloop ${NOVA_LIBRARIES} ${M_LIB} ${ZLIB_LIBRARY}) +target_link_libraries(indi_getprop indicore eventloop ${NOVA_LIBRARIES} ${M_LIB} ${ZLIB_LIBRARY} wsock32 ws2_32) install(TARGETS indi_getprop RUNTIME DESTINATION bin) # ########## setINDI ############## add_executable(indi_setprop setINDIproperty.c) -target_link_libraries(indi_setprop indicore eventloop ${NOVA_LIBRARIES} ${M_LIB} ${ZLIB_LIBRARY}) +target_link_libraries(indi_setprop indicore eventloop ${NOVA_LIBRARIES} ${M_LIB} ${ZLIB_LIBRARY} wsock32 ws2_32) install(TARGETS indi_setprop RUNTIME DESTINATION bin) # ########## evalINDI ############## add_executable(indi_eval compiler.c evalINDI.c) -target_link_libraries(indi_eval indicore eventloop ${NOVA_LIBRARIES} ${M_LIB} ${ZLIB_LIBRARY}) +target_link_libraries(indi_eval indicore eventloop ${NOVA_LIBRARIES} ${M_LIB} ${ZLIB_LIBRARY} wsock32 ws2_32) install(TARGETS indi_eval RUNTIME DESTINATION bin) diff --git a/tools/evalINDI.c b/tools/evalINDI.c index e3bf18d762..83adbc310d 100644 --- a/tools/evalINDI.c +++ b/tools/evalINDI.c @@ -18,16 +18,22 @@ #include #include +#ifdef _WIN32 +#include +#include +#include +#else #include +#include +#include +#endif #include #include #include #include #include #include -#include #include -#include extern int compileExpr(char *expr, char *errmsg); extern int evalExpr(double *vp, char *errmsg); @@ -49,8 +55,11 @@ static int runEval(FILE *fp); static int setOp(XMLEle *root); static XMLEle *nxtEle(FILE *fp); static int readServerChar(FILE *fp); +#ifdef _WIN32 +void CALLBACK onAlarm(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime); +#else static void onAlarm(int dummy); - +#endif static char *me; static char host_def[] = "localhost"; /* default host name */ static char *host = host_def; /* working host name */ @@ -190,8 +199,12 @@ int main(int ac, char *av[]) /* build a parser context for cracking XML responses */ lillp = newLilXML(); +#ifdef _WIN32 + SetTimer(NULL, 0, TIMEOUT * 1000, onAlarm); +#else /* set up to catch an io timeout function */ signal(SIGALRM, onAlarm); +#endif /* send getProperties */ getProps(fp); @@ -575,6 +588,26 @@ static int readServerChar(FILE *fp) return (c); } +#ifdef _WIN32 +void CALLBACK onAlarm(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + char **ops; + int nops; + + /* report any unseen operands if any, else just say timed out */ + if ((nops = getUnsetOperands(&ops)) > 0) + { + fprintf(stderr, "No values seen for"); + while (nops-- > 0) + fprintf(stderr, " %s", ops[nops]); + fprintf(stderr, "\n"); + } + else + fprintf(stderr, "Timed out waiting for new values\n"); + + exit(2); +} +#else /* called after timeout seconds waiting to hear from server. * print reason for trouble and exit(2). */ @@ -598,3 +631,4 @@ static void onAlarm(int dummy) exit(2); } +#endif diff --git a/tools/getINDIproperty.c b/tools/getINDIproperty.c index 3fcdcb84e3..d76e071fb8 100644 --- a/tools/getINDIproperty.c +++ b/tools/getINDIproperty.c @@ -13,16 +13,22 @@ #include #include +#ifdef _WIN32 +#include +#include +#else #include +#include +#include +#endif #include #include #include #include #include #include -#include #include -#include +#include /* table of INDI definition elements, plus setBLOB. * we also look for set* if -m @@ -284,13 +290,32 @@ static void openINDIServer(void) struct hostent *hp; int sockfd; - /* lookup host address */ +#ifdef _WIN32 + struct addrinfo hints, *res; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + int result = getaddrinfo(host, NULL, &hints, &res); + if (result != 0) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(result)); + exit(2); + } + + struct sockaddr_in* sock_addr = (struct sockaddr_in*)res->ai_addr; + hp = gethostbyaddr((char*)&(sock_addr->sin_addr), sizeof(struct in_addr), AF_INET); + + freeaddrinfo(res); +#else hp = gethostbyname(host); if (!hp) { herror("gethostbyname"); exit(2); } +#endif + /* create a socket to the INDI server */ (void)memset((char *)&serv_addr, 0, sizeof(serv_addr)); @@ -344,6 +369,15 @@ static void getprops() fprintf(stderr, "Queried properties from %s\n", onedev ? onedev : "*"); } +#define TIMEOUT_MS 5000 + +static void CALLBACK onTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + printf("Timer expired!\n"); + exit(0); +} + + /* listen for INDI traffic on svrrfp. * print matching srchs[] and return when see all. * timeout and exit if any trouble. @@ -352,9 +386,12 @@ static void listenINDI() { char msg[1024]; - /* arrange to call onAlarm() if not seeing any more defXXX */ +#ifdef _WIN32 + SetTimer(NULL, 0, TIMEOUT_MS, onTimer); +#else signal(SIGALRM, onAlarm); - alarm(timeout); + alarm(TIMEOUT_MS / 1000); +#endif /* read from server, exit if find all requested properties */ while (1) diff --git a/tools/setINDIproperty.c b/tools/setINDIproperty.c index 2b12b82bcd..1c35b8fcd0 100644 --- a/tools/setINDIproperty.c +++ b/tools/setINDIproperty.c @@ -9,16 +9,21 @@ #include #include +#ifdef _WIN32 +#include +#include +#else #include +#include +#include +#endif #include #include #include #include #include #include -#include #include -#include /* table of INDI definition elements we can set * N.B. do not change defs[] order, they are indexed via -x/-n/-s args @@ -353,14 +358,25 @@ static void openINDIServer(FILE **rfpp, FILE **wfpp) *wfpp = fdopen(sockfd, "w"); } +#define TIMEOUT_MS 5000 + +static void CALLBACK onTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + printf("Timer expired!\n"); + exit(0); +} + /* listen for property reports, send new sets if match */ static void listenINDI(FILE *rfp, FILE *wfp) { char msg[1024]; - /* arrange to call onAlarm() if not seeing any more defXXX */ +#ifdef _WIN32 + SetTimer(NULL, 0, TIMEOUT_MS, onTimer); +#else signal(SIGALRM, onAlarm); - alarm(timeout); + alarm(TIMEOUT_MS / 1000); +#endif /* read from server, exit if find all properties */ while (1) @@ -374,14 +390,18 @@ static void listenINDI(FILE *rfp, FILE *wfp) findSet(root, wfp); if (finished() == 0) { - shutdown(fileno(wfp), SHUT_WR); /* insure flush */ - exit(0); /* found all we want */ +#ifdef _WIN32 + shutdown(fileno(wfp), SD_SEND); // Windows 下的关闭写入操作符示例 +#else + shutdown(fileno(wfp), SHUT_WR); // 非 Windows 平台下的关闭写入操作符示例 +#endif + exit(0); // found all we want } - delXMLEle(root); /* not yet, delete and continue */ + delXMLEle(root); // not yet, delete and continue } else if (msg[0]) { - fprintf(stderr, "Bad XML from %s/%d: %s\n", host, port, msg); + fprintf(stderr, "Bad XML: %s\n", msg); exit(2); } } @@ -451,7 +471,7 @@ static void findSet(XMLEle *root, FILE *fp) if (t == NDEFS) return; - alarm(timeout); /* reset timeout */ + onAlarm(timeout); /* reset timeout */ /* check each set for matching device and property name, send if ok */ rdev = (char *)findXMLAttValu(root, "device"); From 1a987199d94f870a4fc10d071727dbae5c367aae Mon Sep 17 00:00:00 2001 From: Max Qian <64824374+AstroAir@users.noreply.github.com> Date: Mon, 14 Aug 2023 11:47:51 +0000 Subject: [PATCH 2/4] Fix error on windows platform --- libs/indicore/indicom.c | 42 +- libs/json.h | 2917 +++++++++++++++++++++++++-------------- 2 files changed, 1882 insertions(+), 1077 deletions(-) diff --git a/libs/indicore/indicom.c b/libs/indicore/indicom.c index b9ff4bd82d..8f9a791fde 100644 --- a/libs/indicore/indicom.c +++ b/libs/indicore/indicom.c @@ -358,22 +358,32 @@ void IDLog(const char *fmt, ...) double time_ns() { struct timespec ts; -#if defined(HAVE_TIMESPEC_GET) - timespec_get(&ts, TIME_UTC); -#elif defined(HAVE_CLOCK_GETTIME) - clock_gettime(CLOCK_REALTIME, &ts); -#elif defined(__APPLE__) // OS X does not have clock_gettime, use clock_get_time - clock_serv_t cclock; - mach_timespec_t mts; - host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - ts.tv_sec = mts.tv_sec; - ts.tv_nsec = mts.tv_nsec; -#else - #error "Unsupported platform" -#endif - return (double)ts.tv_sec+(double)(ts.tv_nsec%1000000000)/1000000000.0; + + #ifdef _WIN32 + FILETIME ft; + ULONGLONG time; + GetSystemTimeAsFileTime(&ft); + time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime; + time -= 116444736000000000ULL; // Convert to Unix timestamp epoch + ts.tv_sec = (long)(time / 10000000ULL); // Convert 100 ns intervals to seconds + ts.tv_nsec = (long)(time % 10000000ULL * 100); // Convert remaining 100 ns intervals to nanoseconds + + #else + #ifdef __MACH__ + clock_serv_t cclock; + mach_timespec_t mts; + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + ts.tv_sec = mts.tv_sec; + ts.tv_nsec = mts.tv_nsec; + #else + timespec_get(&ts, TIME_UTC); + #endif + + #endif + + return (double)ts.tv_sec + (double)(ts.tv_nsec % 1000000000) / 1000000000.0; } /* return current system time in message format */ diff --git a/libs/json.h b/libs/json.h index cffbd7dce9..ddd3131dc6 100644 --- a/libs/json.h +++ b/libs/json.h @@ -1,31 +1,10 @@ -/* - __ _____ _____ _____ - __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 3.10.5 -|_____|_____|_____|_|___| https://github.com/nlohmann/json - -Licensed under the MIT License . -SPDX-License-Identifier: MIT -Copyright (c) 2013-2022 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. -*/ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT /****************************************************************************\ * Note on documentation: The source files contain links to the online * @@ -39,18 +18,6 @@ SOFTWARE. #ifndef INCLUDE_NLOHMANN_JSON_HPP_ #define INCLUDE_NLOHMANN_JSON_HPP_ -#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK - #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) - #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 10 || NLOHMANN_JSON_VERSION_PATCH != 5 - #warning "Already included a different version of the library!" - #endif - #endif -#endif - -#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_MINOR 10 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_PATCH 5 // NOLINT(modernize-macro-to-enum) - #include // all_of, find, for_each #include // nullptr_t, ptrdiff_t, size_t #include // hash, less @@ -60,18 +27,134 @@ SOFTWARE. #endif // JSON_NO_IO #include // random_access_iterator_tag #include // unique_ptr -#include // accumulate #include // string, stoi, to_string #include // declval, forward, move, pair, swap #include // vector // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + -#include #include +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // transform @@ -87,15 +170,34 @@ SOFTWARE. #include // valarray // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // nullptr_t #include // exception +#if JSON_DIAGNOSTICS + #include // accumulate +#endif #include // runtime_error #include // to_string #include // vector // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // array @@ -104,22 +206,129 @@ SOFTWARE. #include // string // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +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 class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + /* 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 < 15) @@ -2153,86 +2362,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ -// #include - - -#include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template struct make_void -{ - using type = void; -}; -template using void_t = typename make_void::type; -} // namespace detail -} // namespace nlohmann +// This file contains all internal macro definitions (except those affecting ABI) +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them -// https://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 class Op, class... Args> -using is_detected = typename detector::value_t; - -template class Op, class... Args> -struct is_detected_lazy : is_detected { }; - -template class Op, class... Args> -using detected_t = typename detector::type; - -template class Op, class... Args> -using detected_or = detector; - -template class Op, class... Args> -using detected_or_t = typename detected_or::type; - -template class Op, class... Args> -using is_detected_exact = std::is_same>; - -template class Op, class... Args> -using is_detected_convertible = - std::is_convertible, To>; -} // namespace detail -} // namespace nlohmann - +// #include -// 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) @@ -2457,12 +2592,13 @@ using is_detected_convertible = class NumberUnsignedType, class NumberFloatType, \ template class AllocatorType, \ template class JSONSerializer, \ - class BinaryType> + class BinaryType, \ + class CustomBaseClass> #define NLOHMANN_BASIC_JSON_TPL \ basic_json + AllocatorType, JSONSerializer, BinaryType, CustomBaseClass> // Macros to simplify conversion from/to types @@ -2612,7 +2748,7 @@ using is_detected_convertible = #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } /*! @brief macro @@ -2625,7 +2761,7 @@ using is_detected_convertible = #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } // inspired from https://stackoverflow.com/a/26745591 @@ -2676,26 +2812,22 @@ using is_detected_convertible = #define JSON_EXPLICIT explicit #endif -#ifndef JSON_DIAGNOSTICS - #define JSON_DIAGNOSTICS 0 -#endif - -#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON - #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 -#endif - #ifndef JSON_DISABLE_ENUM_SERIALIZATION #define JSON_DISABLE_ENUM_SERIALIZATION 0 #endif +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + #if JSON_HAS_THREE_WAY_COMPARISON #include // partial_ordering #endif -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /////////////////////////// // JSON type enumeration // /////////////////////////// @@ -2787,17 +2919,25 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept return std::is_lt(lhs <=> rhs); // *NOPAD* } #endif + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -// #include +// #include -namespace nlohmann -{ + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -2855,18 +2995,29 @@ static void unescape(StringType& s) replace_substring(s, StringType{"~0"}, StringType{"~"}); } -} // namespace detail -} // namespace nlohmann +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // size_t -namespace nlohmann -{ +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /// struct to capture the start position of the current token struct position_t { @@ -2884,14 +3035,24 @@ struct position_t } }; -} // namespace detail -} // namespace nlohmann +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + +#include // array #include // size_t #include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type #include // index_sequence, make_index_sequence, index_sequence_for @@ -2899,8 +3060,7 @@ struct position_t // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -3037,20 +3197,32 @@ template<> struct priority_tag<0> {}; template struct static_const { - static constexpr T value{}; + static JSON_INLINE_VARIABLE constexpr T value{}; }; #ifndef JSON_HAS_CPP_17 - template - constexpr T static_const::value; // NOLINT(readability-redundant-declaration) - + constexpr T static_const::value; #endif +template +inline constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // numeric_limits @@ -3058,23 +3230,30 @@ struct static_const #include // declval #include // tuple -// #include - - // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // random_access_iterator_tag +// #include + // #include // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + template struct iterator_types {}; @@ -3113,104 +3292,136 @@ struct iterator_traits::value>> using pointer = T*; using reference = T&; }; -} // namespace detail -} // namespace nlohmann + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN + NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); -} // namespace nlohmann + +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN + NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); -} // namespace nlohmann + +NLOHMANN_JSON_NAMESPACE_END // #include // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ -#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ -#include // int64_t, uint64_t -#include // map -#include // allocator -#include // string -#include // vector + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ -namespace nlohmann -{ -/*! -@brief default JSONSerializer template argument + // #include -This serializer ignores the template arguments and uses ADL -([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) -for serialization. -*/ -template -struct adl_serializer; - -/// a class to store JSON values -/// @sa https://json.nlohmann.me/api/basic_json/ -template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector> -class basic_json; -/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document -/// @sa https://json.nlohmann.me/api/json_pointer/ -template -class json_pointer; + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN -/*! -@brief default specialization -@sa https://json.nlohmann.me/api/json/ -*/ -using json = basic_json<>; + /*! + @brief default JSONSerializer template argument + + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> + class basic_json; + + /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document + /// @sa https://json.nlohmann.me/api/json_pointer/ + template + class json_pointer; + + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; -/// @brief a minimal map-like container that preserves insertion order -/// @sa https://json.nlohmann.me/api/ordered_map/ -template -struct ordered_map; + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; -/// @brief specialization that maintains the insertion order of object keys -/// @sa https://json.nlohmann.me/api/ordered_json/ -using ordered_json = basic_json; + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; -} // namespace nlohmann + NLOHMANN_JSON_NAMESPACE_END #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN /*! @brief detail namespace with internal helper functions @@ -3221,6 +3432,7 @@ implementations of some @ref basic_json methods, and meta-programming helpers. */ namespace detail { + ///////////// // helpers // ///////////// @@ -3550,8 +3762,10 @@ struct is_constructible_string_type #endif static constexpr auto value = - is_constructible::value; + conjunction < + is_constructible, + is_detected_exact>::value; }; template @@ -3805,7 +4019,7 @@ struct value_in_range_of_impl2 static constexpr bool test(T val) { using CommonType = typename std::common_type::type; - return static_cast(val) <= static_cast(std::numeric_limits::max()); + return static_cast(val) <= static_cast((std::numeric_limits::max)()); } }; @@ -3815,7 +4029,7 @@ struct value_in_range_of_impl2 static constexpr bool test(T val) { using CommonType = typename std::common_type::type; - return static_cast(val) <= static_cast(std::numeric_limits::max()); + return static_cast(val) <= static_cast((std::numeric_limits::max)()); } }; @@ -3825,7 +4039,7 @@ struct value_in_range_of_impl2 static constexpr bool test(T val) { using CommonType = typename std::common_type::type; - return val >= 0 && static_cast(val) <= static_cast(std::numeric_limits::max()); + return val >= 0 && static_cast(val) <= static_cast((std::numeric_limits::max)()); } }; @@ -3836,8 +4050,8 @@ struct value_in_range_of_impl2 static constexpr bool test(T val) { using CommonType = typename std::common_type::type; - return static_cast(val) >= static_cast(std::numeric_limits::min()) - && static_cast(val) <= static_cast(std::numeric_limits::max()); + return static_cast(val) >= static_cast((std::numeric_limits::min)()) + && static_cast(val) <= static_cast((std::numeric_limits::max)()); } }; @@ -3870,10 +4084,70 @@ inline constexpr bool value_in_range_of(T val) return value_in_range_of_impl1::test(val); } +template +using bool_constant = std::integral_constant; + +/////////////////////////////////////////////////////////////////////////////// +// is_c_string +/////////////////////////////////////////////////////////////////////////////// + +namespace impl +{ + +template +inline constexpr bool is_c_string() +{ + using TUnExt = typename std::remove_extent::type; + using TUnCVExt = typename std::remove_cv::type; + using TUnPtr = typename std::remove_pointer::type; + using TUnCVPtr = typename std::remove_cv::type; + return + (std::is_array::value && std::is_same::value) + || (std::is_pointer::value && std::is_same::value); +} + +} // namespace impl + +// checks whether T is a [cv] char */[cv] char[] C string +template +struct is_c_string : bool_constant()> {}; + +template +using is_c_string_uncvref = is_c_string>; + +/////////////////////////////////////////////////////////////////////////////// +// is_transparent +/////////////////////////////////////////////////////////////////////////////// + +namespace impl +{ + +template +inline constexpr bool is_transparent() +{ + return is_detected::value; +} + +} // namespace impl + +// checks whether T has a member named is_transparent +template +struct is_transparent : bool_constant()> {}; + +/////////////////////////////////////////////////////////////////////////////// + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // strlen @@ -3885,8 +4159,7 @@ inline constexpr bool value_in_range_of(T val) // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -3896,28 +4169,28 @@ inline std::size_t concat_length() } template -inline std::size_t concat_length(const char* cstr, Args&& ... rest); +inline std::size_t concat_length(const char* cstr, const Args& ... rest); template -inline std::size_t concat_length(const StringType& str, Args&& ... rest); +inline std::size_t concat_length(const StringType& str, const Args& ... rest); template -inline std::size_t concat_length(const char /*c*/, Args&& ... rest) +inline std::size_t concat_length(const char /*c*/, const Args& ... rest) { - return 1 + concat_length(std::forward(rest)...); + return 1 + concat_length(rest...); } template -inline std::size_t concat_length(const char* cstr, Args&& ... rest) +inline std::size_t concat_length(const char* cstr, const Args& ... rest) { // cppcheck-suppress ignoredReturnValue - return ::strlen(cstr) + concat_length(std::forward(rest)...); + return ::strlen(cstr) + concat_length(rest...); } template -inline std::size_t concat_length(const StringType& str, Args&& ... rest) +inline std::size_t concat_length(const StringType& str, const Args& ... rest) { - return str.size() + concat_length(std::forward(rest)...); + return str.size() + concat_length(rest...); } template @@ -4008,20 +4281,20 @@ template inline OutStringType concat(Args && ... args) { OutStringType str; - str.reserve(concat_length(std::forward(args)...)); + str.reserve(concat_length(args...)); concat_into(str, std::forward(args)...); return str; } -} // namespace detail -} // namespace nlohmann +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + //////////////// // exceptions // //////////////// @@ -4065,9 +4338,9 @@ class exception : public std::exception { case value_t::array: { - for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) + for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i) { - if (¤t->m_parent->m_value.array->operator[](i) == current) + if (¤t->m_parent->m_data.m_value.array->operator[](i) == current) { tokens.emplace_back(std::to_string(i)); break; @@ -4078,7 +4351,7 @@ class exception : public std::exception case value_t::object: { - for (const auto& element : *current->m_parent->m_value.object) + for (const auto& element : *current->m_parent->m_data.m_value.object) { if (&element.second == current) { @@ -4141,17 +4414,17 @@ class parse_error : public exception template::value, int> = 0> static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) { - std::string w = concat(exception::name("parse_error", id_), "parse error", - position_string(pos), ": ", exception::diagnostics(context), what_arg); + const std::string w = concat(exception::name("parse_error", id_), "parse error", + position_string(pos), ": ", exception::diagnostics(context), what_arg); return {id_, pos.chars_read_total, w.c_str()}; } template::value, int> = 0> static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context) { - std::string w = concat(exception::name("parse_error", id_), "parse error", - (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), - ": ", exception::diagnostics(context), what_arg); + const std::string w = concat(exception::name("parse_error", id_), "parse error", + (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), + ": ", exception::diagnostics(context), what_arg); return {id_, byte_, w.c_str()}; } @@ -4185,7 +4458,7 @@ class invalid_iterator : public exception template::value, int> = 0> static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) { - std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); + const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -4203,7 +4476,7 @@ class type_error : public exception template::value, int> = 0> static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) { - std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); + const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -4220,7 +4493,7 @@ class out_of_range : public exception template::value, int> = 0> static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) { - std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); + const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -4237,7 +4510,7 @@ class other_error : public exception template::value, int> = 0> static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) { - std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); + const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -4247,49 +4520,79 @@ class other_error : public exception }; } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -namespace nlohmann -{ + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + // dispatching helper struct template struct identity_tag {}; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END -// #include +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -// #include -// #include + +// #include #if JSON_HAS_EXPERIMENTAL_FILESYSTEM #include -namespace nlohmann::detail +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail { namespace std_fs = std::experimental::filesystem; -} // namespace nlohmann::detail +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END #elif JSON_HAS_FILESYSTEM #include -namespace nlohmann::detail +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail { namespace std_fs = std::filesystem; -} // namespace nlohmann::detail +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END #endif -namespace nlohmann -{ +// #include + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + template inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) { @@ -4361,6 +4664,7 @@ template < typename BasicJsonType, typename StringType, enable_if_t < std::is_assignable::value + && is_detected_exact::value && !std::is_same::value && !is_json_ref::value, int > = 0 > inline void from_json(const BasicJsonType& j, StringType& s) @@ -4734,6 +5038,7 @@ struct from_json_fn return from_json(j, std::forward(val)); } }; + } // namespace detail #ifndef JSON_HAS_CPP_17 @@ -4746,11 +5051,20 @@ namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-n JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers) detail::static_const::value; #ifndef JSON_HAS_CPP_17 -} // namespace +} // namespace #endif -} // namespace nlohmann + +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // copy @@ -4762,9 +5076,15 @@ JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definition #include // valarray #include // vector -// #include - // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // size_t @@ -4777,15 +5097,17 @@ JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definition #include // enable_borrowed_range #endif +// #include + // #include // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + template void int_to_string( string_type& target, std::size_t value ) { @@ -4829,10 +5151,10 @@ template class iteration_proxy_value // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions iteration_proxy_value(iteration_proxy_value&&) noexcept(std::is_nothrow_move_constructible::value - && std::is_nothrow_move_constructible::value) = default; + && std::is_nothrow_move_constructible::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) iteration_proxy_value& operator=(iteration_proxy_value&&) noexcept(std::is_nothrow_move_assignable::value - && std::is_nothrow_move_assignable::value) = default; + && std::is_nothrow_move_assignable::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) ~iteration_proxy_value() = default; /// dereference operator (needed for range-based for) @@ -4962,8 +5284,9 @@ auto get(const nlohmann::detail::iteration_proxy_value& i) -> decl { return i.value(); } + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // The Addition to the STD Namespace is required to add // Structured Bindings Support to the iteration_proxy_value class @@ -4971,17 +5294,18 @@ auto get(const nlohmann::detail::iteration_proxy_value& i) -> decl // And see https://github.com/nlohmann/json/pull/1391 namespace std { + #if defined(__clang__) // Fix: https://github.com/nlohmann/json/issues/1401 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wmismatched-tags" #endif template -class tuple_size<::nlohmann::detail::iteration_proxy_value> +class tuple_size<::nlohmann::detail::iteration_proxy_value> // NOLINT(cert-dcl58-cpp) : public std::integral_constant {}; template -class tuple_element> +class tuple_element> // NOLINT(cert-dcl58-cpp) { public: using type = decltype( @@ -4991,45 +5315,36 @@ class tuple_element> #if defined(__clang__) #pragma clang diagnostic pop #endif -} // namespace std + +} // namespace std #if JSON_HAS_RANGES template inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy> = true; #endif +// #include + // #include +// #include + // #include // #include -#if JSON_HAS_EXPERIMENTAL_FILESYSTEM -#include -namespace nlohmann::detail -{ -namespace std_fs = std::experimental::filesystem; -} // namespace nlohmann::detail -#elif JSON_HAS_FILESYSTEM -#include -namespace nlohmann::detail -{ -namespace std_fs = std::filesystem; -} // namespace nlohmann::detail -#endif - -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + ////////////////// // constructors // ////////////////// /* * Note all external_constructor<>::construct functions need to call - * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an + * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an * allocated value (e.g., a string). See bug issue * https://github.com/nlohmann/json/issues/2865 for more information. */ @@ -5042,9 +5357,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept { - j.m_value.destroy(j.m_type); - j.m_type = value_t::boolean; - j.m_value = b; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::boolean; + j.m_data.m_value = b; j.assert_invariant(); } }; @@ -5055,18 +5370,18 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::string; - j.m_value = s; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::string; + j.m_data.m_value = s; j.assert_invariant(); } template static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::string; - j.m_value = std::move(s); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::string; + j.m_data.m_value = std::move(s); j.assert_invariant(); } @@ -5075,9 +5390,9 @@ struct external_constructor int > = 0 > static void construct(BasicJsonType& j, const CompatibleStringType& str) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::string; - j.m_value.string = j.template create(str); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::string; + j.m_data.m_value.string = j.template create(str); j.assert_invariant(); } }; @@ -5088,18 +5403,18 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::binary; - j.m_value = typename BasicJsonType::binary_t(b); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::binary; + j.m_data.m_value = typename BasicJsonType::binary_t(b); j.assert_invariant(); } template static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::binary; - j.m_value = typename BasicJsonType::binary_t(std::move(b)); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::binary; + j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b)); j.assert_invariant(); } }; @@ -5110,9 +5425,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept { - j.m_value.destroy(j.m_type); - j.m_type = value_t::number_float; - j.m_value = val; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::number_float; + j.m_data.m_value = val; j.assert_invariant(); } }; @@ -5123,9 +5438,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept { - j.m_value.destroy(j.m_type); - j.m_type = value_t::number_unsigned; - j.m_value = val; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::number_unsigned; + j.m_data.m_value = val; j.assert_invariant(); } }; @@ -5136,9 +5451,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept { - j.m_value.destroy(j.m_type); - j.m_type = value_t::number_integer; - j.m_value = val; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::number_integer; + j.m_data.m_value = val; j.assert_invariant(); } }; @@ -5149,9 +5464,9 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value = arr; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value = arr; j.set_parents(); j.assert_invariant(); } @@ -5159,9 +5474,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value = std::move(arr); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value = std::move(arr); j.set_parents(); j.assert_invariant(); } @@ -5174,9 +5489,9 @@ struct external_constructor using std::begin; using std::end; - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value.array = j.template create(begin(arr), end(arr)); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value.array = j.template create(begin(arr), end(arr)); j.set_parents(); j.assert_invariant(); } @@ -5184,14 +5499,14 @@ struct external_constructor template static void construct(BasicJsonType& j, const std::vector& arr) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->reserve(arr.size()); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value = value_t::array; + j.m_data.m_value.array->reserve(arr.size()); for (const bool x : arr) { - j.m_value.array->push_back(x); - j.set_parent(j.m_value.array->back()); + j.m_data.m_value.array->push_back(x); + j.set_parent(j.m_data.m_value.array->back()); } j.assert_invariant(); } @@ -5200,13 +5515,13 @@ struct external_constructor enable_if_t::value, int> = 0> static void construct(BasicJsonType& j, const std::valarray& arr) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->resize(arr.size()); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value = value_t::array; + j.m_data.m_value.array->resize(arr.size()); if (arr.size() > 0) { - std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); } j.set_parents(); j.assert_invariant(); @@ -5219,9 +5534,9 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::object; - j.m_value = obj; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::object; + j.m_data.m_value = obj; j.set_parents(); j.assert_invariant(); } @@ -5229,9 +5544,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::object; - j.m_value = std::move(obj); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::object; + j.m_data.m_value = std::move(obj); j.set_parents(); j.assert_invariant(); } @@ -5243,9 +5558,9 @@ struct external_constructor using std::begin; using std::end; - j.m_value.destroy(j.m_type); - j.m_type = value_t::object; - j.m_value.object = j.template create(begin(obj), end(obj)); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::object; + j.m_data.m_value.object = j.template create(begin(obj), end(obj)); j.set_parents(); j.assert_invariant(); } @@ -5262,9 +5577,15 @@ inline void to_json(BasicJsonType& j, T b) noexcept external_constructor::construct(j, b); } -template::reference&, typename BasicJsonType::boolean_t>::value, int> = 0> -inline void to_json(BasicJsonType& j, const std::vector::reference& b) noexcept +template < typename BasicJsonType, typename BoolRef, + enable_if_t < + ((std::is_same::reference, BoolRef>::value + && !std::is_same ::reference, typename BasicJsonType::boolean_t&>::value) + || (std::is_same::const_reference, BoolRef>::value + && !std::is_same ::const_reference>, + typename BasicJsonType::boolean_t >::value)) + && std::is_convertible::value, int > = 0 > +inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept { external_constructor::construct(j, static_cast(b)); } @@ -5429,17 +5750,15 @@ namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-n JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers) detail::static_const::value; #ifndef JSON_HAS_CPP_17 -} // namespace +} // namespace #endif -} // namespace nlohmann -// #include +NLOHMANN_JSON_NAMESPACE_END -// #include +// #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN /// @sa https://json.nlohmann.me/api/adl_serializer/ template @@ -5475,17 +5794,28 @@ struct adl_serializer ::nlohmann::to_json(j, std::forward(val)); } }; -} // namespace nlohmann + +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // uint8_t, uint64_t #include // tie #include // move -namespace nlohmann -{ +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN /// @brief an internal type for a backed binary type /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/ @@ -5571,7 +5901,7 @@ class byte_container_with_subtype : public BinaryType bool m_has_subtype = false; }; -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include @@ -5580,19 +5910,26 @@ class byte_container_with_subtype : public BinaryType // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // uint8_t #include // size_t #include // hash -// #include +// #include // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -5703,9 +6040,17 @@ std::size_t hash(const BasicJsonType& j) } } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // generate_n @@ -5720,11 +6065,18 @@ std::size_t hash(const BasicJsonType& j) #include // char_traits, string #include // make_pair, move #include // vector -#include // map // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // array @@ -5747,10 +6099,10 @@ std::size_t hash(const BasicJsonType& j) // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /// the supported input formats enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata }; @@ -5771,7 +6123,9 @@ class file_input_adapter JSON_HEDLEY_NON_NULL(2) explicit file_input_adapter(std::FILE* f) noexcept : m_file(f) - {} + { + JSON_ASSERT(m_file != nullptr); + } // make class move-only file_input_adapter(const file_input_adapter&) = delete; @@ -6129,7 +6483,7 @@ struct container_input_adapter_factory< ContainerType, } }; -} // namespace container_input_adapter_factory_impl +} // namespace container_input_adapter_factory_impl template typename container_input_adapter_factory_impl::container_input_adapter_factory::adapter_type input_adapter(const ContainerType& container) @@ -6208,10 +6562,19 @@ class span_input_adapter private: contiguous_bytes_input_adapter ia; }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include @@ -6226,8 +6589,7 @@ class span_input_adapter // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN /*! @brief SAX interface @@ -6454,7 +6816,7 @@ class json_sax_dom_parser JSON_ASSERT(ref_stack.back()->is_object()); // add null at given key and store the reference for later - object_element = &(ref_stack.back()->m_value.object->operator[](val)); + object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val)); return true; } @@ -6529,8 +6891,8 @@ class json_sax_dom_parser if (ref_stack.back()->is_array()) { - ref_stack.back()->m_value.array->emplace_back(std::forward(v)); - return &(ref_stack.back()->m_value.array->back()); + ref_stack.back()->m_data.m_value.array->emplace_back(std::forward(v)); + return &(ref_stack.back()->m_data.m_value.array->back()); } JSON_ASSERT(ref_stack.back()->is_object()); @@ -6649,7 +7011,7 @@ class json_sax_dom_callback_parser // add discarded value at given key and store the reference for later if (keep && ref_stack.back()) { - object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); + object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded); } return true; @@ -6734,7 +7096,7 @@ class json_sax_dom_callback_parser // remove discarded value if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) { - ref_stack.back()->m_value.array->pop_back(); + ref_stack.back()->m_data.m_value.array->pop_back(); } return true; @@ -6817,8 +7179,8 @@ class json_sax_dom_callback_parser // array if (ref_stack.back()->is_array()) { - ref_stack.back()->m_value.array->emplace_back(std::move(value)); - return {true, &(ref_stack.back()->m_value.array->back())}; + ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value)); + return {true, &(ref_stack.back()->m_data.m_value.array->back())}; } // object @@ -6933,11 +7295,19 @@ class json_sax_acceptor return false; } }; -} // namespace detail -} // namespace nlohmann +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // array @@ -6957,10 +7327,10 @@ class json_sax_acceptor // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /////////// // lexer // /////////// @@ -8562,27 +8932,38 @@ class lexer : public lexer_base /// the decimal point const char_int_type decimal_point_char = '.'; }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // size_t #include // declval #include // string +// #include + // #include // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + template using null_function_t = decltype(std::declval().null()); @@ -8717,8 +9098,9 @@ struct is_sax_static_asserts "Missing/invalid function: bool parse_error(std::size_t, const " "std::string&, const exception&)"); }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include @@ -8727,8 +9109,7 @@ struct is_sax_static_asserts // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -9027,7 +9408,7 @@ class binary_reader { std::array cr{{}}; static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - std::string cr_str{cr.data()}; + const std::string cr_str{cr.data()}; return sax->parse_error(element_type_parse_position, cr_str, parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr)); } @@ -10649,7 +11030,7 @@ class binary_reader return false; } - if (size_and_type.first != string_t::npos) + if (size_and_type.first != npos) { if (size_and_type.second != 0) { @@ -10850,7 +11231,7 @@ class binary_reader } if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array { - return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimentional vector is not allowed", "size"), nullptr)); + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr)); } std::vector dim; if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) @@ -10882,7 +11263,7 @@ class binary_reader for (auto i : dim) { result *= i; - if (result == 0 || result == string_t::npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be string_t::npos as it is used to initialize size in get_ubjson_size_type() + if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type() { return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); } @@ -10928,7 +11309,7 @@ class binary_reader */ bool get_ubjson_size_type(std::pair& result, bool inside_ndarray = false) { - result.first = string_t::npos; // size + result.first = npos; // size result.second = 0; // type bool is_ndarray = false; @@ -10936,10 +11317,9 @@ class binary_reader if (current == '$') { - std::vector bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type - result.second = get(); // must not ignore 'N', because 'N' maybe the type - if (JSON_HEDLEY_UNLIKELY( input_format == input_format_t::bjdata && std::find(bjdx.begin(), bjdx.end(), result.second) != bjdx.end() )) + if (input_format == input_format_t::bjdata + && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second))) { auto last_token = get_token_string(); return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, @@ -10963,7 +11343,7 @@ class binary_reader exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); } - bool is_error = get_ubjson_size_value(result.first, is_ndarray); + const bool is_error = get_ubjson_size_value(result.first, is_ndarray); if (input_format == input_format_t::bjdata && is_ndarray) { if (inside_ndarray) @@ -10978,7 +11358,7 @@ class binary_reader if (current == '#') { - bool is_error = get_ubjson_size_value(result.first, is_ndarray); + const bool is_error = get_ubjson_size_value(result.first, is_ndarray); if (input_format == input_format_t::bjdata && is_ndarray) { return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, @@ -11188,23 +11568,23 @@ class binary_reader // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata): // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} - if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0) + if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) { - std::map bjdtype = {{'U', "uint8"}, {'i', "int8"}, {'u', "uint16"}, {'I', "int16"}, - {'m', "uint32"}, {'l', "int32"}, {'M', "uint64"}, {'L', "int64"}, {'d', "single"}, {'D', "double"}, {'C', "char"} - }; - size_and_type.second &= ~(static_cast(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker - + auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t) + { + return p.first < t; + }); string_t key = "_ArrayType_"; - if (JSON_HEDLEY_UNLIKELY(bjdtype.count(size_and_type.second) == 0)) + if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second)) { auto last_token = get_token_string(); return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr)); } - if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(bjdtype[size_and_type.second]) )) + string_t type = it->second; // sax->string() takes a reference + if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type))) { return false; } @@ -11231,7 +11611,7 @@ class binary_reader return (sax->end_array() && sax->end_object()); } - if (size_and_type.first != string_t::npos) + if (size_and_type.first != npos) { if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) { @@ -11294,7 +11674,7 @@ class binary_reader } // do not accept ND-array size in objects in BJData - if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0) + if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) { auto last_token = get_token_string(); return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, @@ -11302,7 +11682,7 @@ class binary_reader } string_t key; - if (size_and_type.first != string_t::npos) + if (size_and_type.first != npos) { if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) { @@ -11646,6 +12026,8 @@ class binary_reader } private: + static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast(-1); + /// input adapter InputAdapterType ia; @@ -11663,15 +12045,61 @@ class binary_reader /// the SAX parser json_sax_t* sax = nullptr; + + // excluded markers in bjdata optimized type +#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \ + make_array('F', 'H', 'N', 'S', 'T', 'Z', '[', '{') + +#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \ + make_array( \ + bjd_type{'C', "char"}, \ + bjd_type{'D', "double"}, \ + bjd_type{'I', "int16"}, \ + bjd_type{'L', "int64"}, \ + bjd_type{'M', "uint64"}, \ + bjd_type{'U', "uint8"}, \ + bjd_type{'d', "single"}, \ + bjd_type{'i', "int8"}, \ + bjd_type{'l', "int32"}, \ + bjd_type{'m', "uint32"}, \ + bjd_type{'u', "uint16"}) + + JSON_PRIVATE_UNLESS_TESTED: + // lookup tables + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers = + JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_; + + using bjd_type = std::pair; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map = + JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_; + +#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ +#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ }; + +#ifndef JSON_HAS_CPP_17 + template + constexpr std::size_t binary_reader::npos; +#endif + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // isfinite @@ -11698,8 +12126,7 @@ class binary_reader // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { //////////// @@ -12179,12 +12606,30 @@ class parser }; } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +// #include + // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // ptrdiff_t @@ -12193,10 +12638,10 @@ class parser // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /* @brief an iterator for primitive JSON types @@ -12307,14 +12752,15 @@ class primitive_iterator_t return *this; } }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /*! @brief an iterator value @@ -12330,10 +12776,19 @@ template struct internal_iterator /// generic iterator for all other types primitive_iterator_t primitive_iterator {}; }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next @@ -12354,10 +12809,10 @@ template struct internal_iterator // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + // forward declare, to be able to friend it later on template class iteration_proxy; template class iteration_proxy_value; @@ -12436,7 +12891,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { @@ -12533,17 +12988,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { - m_it.object_iterator = m_object->m_value.object->begin(); + m_it.object_iterator = m_object->m_data.m_value.object->begin(); break; } case value_t::array: { - m_it.array_iterator = m_object->m_value.array->begin(); + m_it.array_iterator = m_object->m_data.m_value.array->begin(); break; } @@ -12577,17 +13032,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { - m_it.object_iterator = m_object->m_value.object->end(); + m_it.object_iterator = m_object->m_data.m_value.object->end(); break; } case value_t::array: { - m_it.array_iterator = m_object->m_value.array->end(); + m_it.array_iterator = m_object->m_data.m_value.array->end(); break; } @@ -12616,17 +13071,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { - JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); + JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); return m_it.object_iterator->second; } case value_t::array: { - JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); + JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); return *m_it.array_iterator; } @@ -12660,17 +13115,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { - JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); + JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); return &(m_it.object_iterator->second); } case value_t::array: { - JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); + JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); return &*m_it.array_iterator; } @@ -12713,7 +13168,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { @@ -12764,7 +13219,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { @@ -12811,7 +13266,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: return (m_it.object_iterator == other.m_it.object_iterator); @@ -12856,7 +13311,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object)); @@ -12912,7 +13367,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); @@ -12991,7 +13446,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); @@ -13020,7 +13475,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object)); @@ -13081,22 +13536,34 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /// the actual iterator of the associated instance internal_iterator::type> m_it {}; }; -} // namespace detail -} // namespace nlohmann + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // ptrdiff_t #include // reverse_iterator #include // declval -namespace nlohmann -{ +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + ////////////////////// // reverse_iterator // ////////////////////// @@ -13204,18 +13671,64 @@ class json_reverse_iterator : public std::reverse_iterator return it.operator * (); } }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include +// #include + + +#include // conditional, is_same + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief Default base class of the @ref basic_json class. + +So that the correct implementations of the copy / move ctors / assign operators +of @ref basic_json do not require complex case distinctions +(no base class / custom base class used as customization point), +@ref basic_json always has a base class. +By default, this class is used because it is empty and thus has no effect +on the behavior of @ref basic_json. +*/ +struct json_default_base {}; + +template +using json_base_class = typename std::conditional < + std::is_same::value, + json_default_base, + T + >::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // all_of #include // isdigit #include // errno, ERANGE #include // strtoull +#ifndef JSON_NO_IO + #include // ostream +#endif // JSON_NO_IO #include // max #include // accumulate #include // string @@ -13233,8 +13746,7 @@ class json_reverse_iterator : public std::reverse_iterator // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document /// @sa https://json.nlohmann.me/api/json_pointer/ @@ -13284,11 +13796,22 @@ class json_pointer /// @brief return a string representation of the JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/ + JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string()) operator string_t() const { return to_string(); } +#ifndef JSON_NO_IO + /// @brief write string representation of the JSON pointer to stream + /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ + friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr) + { + o << ptr.to_string(); + return o; + } +#endif + /// @brief append another JSON pointer at the end of this JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ json_pointer& operator/=(const json_pointer& ptr) @@ -13426,7 +13949,7 @@ class json_pointer const char* p = s.c_str(); char* p_end = nullptr; errno = 0; // strtoull doesn't reset errno - unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) + const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) if (p == p_end // invalid input or empty string || errno == ERANGE // out of range || JSON_HEDLEY_UNLIKELY(static_cast(p_end - p) != s.size())) // incomplete read @@ -13582,7 +14105,7 @@ class json_pointer if (reference_token == "-") { // explicitly treat "-" as index beyond the end - ptr = &ptr->operator[](ptr->m_value.array->size()); + ptr = &ptr->operator[](ptr->m_data.m_value.array->size()); } else { @@ -13634,7 +14157,7 @@ class json_pointer { // "-" always fails the range check JSON_THROW(detail::out_of_range::create(402, detail::concat( - "array index '-' (", std::to_string(ptr->m_value.array->size()), + "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); } @@ -13691,7 +14214,7 @@ class json_pointer if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { // "-" cannot be used for const access - JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr)); + JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); } // use unchecked array access @@ -13741,7 +14264,7 @@ class json_pointer { // "-" always fails the range check JSON_THROW(detail::out_of_range::create(402, detail::concat( - "array index '-' (", std::to_string(ptr->m_value.array->size()), + "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); } @@ -13936,7 +14459,7 @@ class json_pointer { case detail::value_t::array: { - if (value.m_value.array->empty()) + if (value.m_data.m_value.array->empty()) { // flatten empty array as null result[reference_string] = nullptr; @@ -13944,10 +14467,10 @@ class json_pointer else { // iterate array and use index as reference string - for (std::size_t i = 0; i < value.m_value.array->size(); ++i) + for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) { flatten(detail::concat(reference_string, '/', std::to_string(i)), - value.m_value.array->operator[](i), result); + value.m_data.m_value.array->operator[](i), result); } } break; @@ -13955,7 +14478,7 @@ class json_pointer case detail::value_t::object: { - if (value.m_value.object->empty()) + if (value.m_data.m_value.object->empty()) { // flatten empty object as null result[reference_string] = nullptr; @@ -13963,7 +14486,7 @@ class json_pointer else { // iterate object and use keys as reference string - for (const auto& element : *value.m_value.object) + for (const auto& element : *value.m_data.m_value.object) { flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); } @@ -14010,7 +14533,7 @@ class json_pointer BasicJsonType result; // iterate the JSON object values - for (const auto& element : *value.m_value.object) + for (const auto& element : *value.m_data.m_value.object) { if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) { @@ -14042,71 +14565,170 @@ class json_pointer return result; } - /*! - @brief compares two JSON pointers for equality - - @param[in] lhs JSON pointer to compare - @param[in] rhs JSON pointer to compare - @return whether @a lhs is equal to @a rhs + public: +#if JSON_HAS_THREE_WAY_COMPARISON + /// @brief compares two JSON pointers for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + bool operator==(const json_pointer& rhs) const noexcept + { + return reference_tokens == rhs.reference_tokens; + } - @complexity Linear in the length of the JSON pointer + /// @brief compares JSON pointer and string for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer)) + bool operator==(const string_t& rhs) const + { + return *this == json_pointer(rhs); + } - @exceptionsafety No-throw guarantee: this function never throws exceptions. - */ + /// @brief 3-way compares two JSON pointers + template + std::strong_ordering operator<=>(const json_pointer& rhs) const noexcept // *NOPAD* + { + return reference_tokens <=> rhs.reference_tokens; // *NOPAD* + } +#else + /// @brief compares two JSON pointers for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept; + friend bool operator==(const json_pointer& lhs, + const json_pointer& rhs) noexcept; - /*! - @brief compares two JSON pointers for inequality + /// @brief compares JSON pointer and string for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator==(const json_pointer& lhs, + const StringType& rhs); - @param[in] lhs JSON pointer to compare - @param[in] rhs JSON pointer to compare - @return whether @a lhs is not equal @a rhs + /// @brief compares string and JSON pointer for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator==(const StringType& lhs, + const json_pointer& rhs); - @complexity Linear in the length of the JSON pointer + /// @brief compares two JSON pointers for inequality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator!=(const json_pointer& lhs, + const json_pointer& rhs) noexcept; - @exceptionsafety No-throw guarantee: this function never throws exceptions. - */ + /// @brief compares JSON pointer and string for inequality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator!=(const json_pointer& lhs, + const StringType& rhs); + + /// @brief compares string and JSON pointer for inequality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator!=(const StringType& lhs, + const json_pointer& rhs); + + /// @brief compares two JSON pointer for less-than template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept; + friend bool operator<(const json_pointer& lhs, + const json_pointer& rhs) noexcept; +#endif + private: /// the reference tokens std::vector reference_tokens; }; +#if !JSON_HAS_THREE_WAY_COMPARISON // functions cannot be defined inside class due to ODR violations template -inline bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept +inline bool operator==(const json_pointer& lhs, + const json_pointer& rhs) noexcept { return lhs.reference_tokens == rhs.reference_tokens; } +template::string_t> +JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) +inline bool operator==(const json_pointer& lhs, + const StringType& rhs) +{ + return lhs == json_pointer(rhs); +} + +template::string_t> +JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) +inline bool operator==(const StringType& lhs, + const json_pointer& rhs) +{ + return json_pointer(lhs) == rhs; +} + template -inline bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept +inline bool operator!=(const json_pointer& lhs, + const json_pointer& rhs) noexcept { return !(lhs == rhs); } -} // namespace nlohmann + +template::string_t> +JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) +inline bool operator!=(const json_pointer& lhs, + const StringType& rhs) +{ + return !(lhs == rhs); +} + +template::string_t> +JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) +inline bool operator!=(const StringType& lhs, + const json_pointer& rhs) +{ + return !(lhs == rhs); +} + +template +inline bool operator<(const json_pointer& lhs, + const json_pointer& rhs) noexcept +{ + return lhs.reference_tokens < rhs.reference_tokens; +} +#endif + +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include #include +// #include + // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + template class json_ref { @@ -14162,8 +14784,9 @@ class json_ref mutable value_type owned_value = nullptr; value_type const* value_ref = nullptr; }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include @@ -14176,6 +14799,14 @@ class json_ref // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // reverse @@ -14194,6 +14825,14 @@ class json_ref // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // copy @@ -14211,10 +14850,10 @@ class json_ref // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /// abstract output adapter interface template struct output_adapter_protocol { @@ -14331,16 +14970,17 @@ class output_adapter private: output_adapter_t oa = nullptr; }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /////////////////// // binary writer // /////////////////// @@ -14376,7 +15016,7 @@ class binary_writer { case value_t::object: { - write_bson_object(*j.m_value.object); + write_bson_object(*j.m_data.m_value.object); break; } @@ -14411,7 +15051,7 @@ class binary_writer case value_t::boolean: { - oa->write_character(j.m_value.boolean + oa->write_character(j.m_data.m_value.boolean ? to_char_type(0xF5) : to_char_type(0xF4)); break; @@ -14419,42 +15059,42 @@ class binary_writer case value_t::number_integer: { - if (j.m_value.number_integer >= 0) + if (j.m_data.m_value.number_integer >= 0) { // CBOR does not differentiate between positive signed // integers and unsigned integers. Therefore, we used the // code from the value_t::number_unsigned case here. - if (j.m_value.number_integer <= 0x17) + if (j.m_data.m_value.number_integer <= 0x17) { - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } else { oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } } else { // The conversions below encode the sign in the first // byte, and the value is converted to a positive number. - const auto positive_number = -1 - j.m_value.number_integer; - if (j.m_value.number_integer >= -24) + const auto positive_number = -1 - j.m_data.m_value.number_integer; + if (j.m_data.m_value.number_integer >= -24) { write_number(static_cast(0x20 + positive_number)); } @@ -14484,52 +15124,52 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_value.number_unsigned <= 0x17) + if (j.m_data.m_value.number_unsigned <= 0x17) { - write_number(static_cast(j.m_value.number_unsigned)); + write_number(static_cast(j.m_data.m_value.number_unsigned)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_value.number_unsigned)); + write_number(static_cast(j.m_data.m_value.number_unsigned)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_value.number_unsigned)); + write_number(static_cast(j.m_data.m_value.number_unsigned)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_value.number_unsigned)); + write_number(static_cast(j.m_data.m_value.number_unsigned)); } else { oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_value.number_unsigned)); + write_number(static_cast(j.m_data.m_value.number_unsigned)); } break; } case value_t::number_float: { - if (std::isnan(j.m_value.number_float)) + if (std::isnan(j.m_data.m_value.number_float)) { // NaN is 0xf97e00 in CBOR oa->write_character(to_char_type(0xF9)); oa->write_character(to_char_type(0x7E)); oa->write_character(to_char_type(0x00)); } - else if (std::isinf(j.m_value.number_float)) + else if (std::isinf(j.m_data.m_value.number_float)) { // Infinity is 0xf97c00, -Infinity is 0xf9fc00 oa->write_character(to_char_type(0xf9)); - oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); + oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); oa->write_character(to_char_type(0x00)); } else { - write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); + write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor); } break; } @@ -14537,7 +15177,7 @@ class binary_writer case value_t::string: { // step 1: write control byte and the string length - const auto N = j.m_value.string->size(); + const auto N = j.m_data.m_value.string->size(); if (N <= 0x17) { write_number(static_cast(0x60 + N)); @@ -14567,15 +15207,15 @@ class binary_writer // step 2: write the string oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); + reinterpret_cast(j.m_data.m_value.string->c_str()), + j.m_data.m_value.string->size()); break; } case value_t::array: { // step 1: write control byte and the array size - const auto N = j.m_value.array->size(); + const auto N = j.m_data.m_value.array->size(); if (N <= 0x17) { write_number(static_cast(0x80 + N)); @@ -14604,7 +15244,7 @@ class binary_writer // LCOV_EXCL_STOP // step 2: write each element - for (const auto& el : *j.m_value.array) + for (const auto& el : *j.m_data.m_value.array) { write_cbor(el); } @@ -14613,32 +15253,32 @@ class binary_writer case value_t::binary: { - if (j.m_value.binary->has_subtype()) + if (j.m_data.m_value.binary->has_subtype()) { - if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xd8)); - write_number(static_cast(j.m_value.binary->subtype())); + write_number(static_cast(j.m_data.m_value.binary->subtype())); } - else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xd9)); - write_number(static_cast(j.m_value.binary->subtype())); + write_number(static_cast(j.m_data.m_value.binary->subtype())); } - else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xda)); - write_number(static_cast(j.m_value.binary->subtype())); + write_number(static_cast(j.m_data.m_value.binary->subtype())); } - else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xdb)); - write_number(static_cast(j.m_value.binary->subtype())); + write_number(static_cast(j.m_data.m_value.binary->subtype())); } } // step 1: write control byte and the binary array size - const auto N = j.m_value.binary->size(); + const auto N = j.m_data.m_value.binary->size(); if (N <= 0x17) { write_number(static_cast(0x40 + N)); @@ -14668,7 +15308,7 @@ class binary_writer // step 2: write each element oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), + reinterpret_cast(j.m_data.m_value.binary->data()), N); break; @@ -14677,7 +15317,7 @@ class binary_writer case value_t::object: { // step 1: write control byte and the object size - const auto N = j.m_value.object->size(); + const auto N = j.m_data.m_value.object->size(); if (N <= 0x17) { write_number(static_cast(0xA0 + N)); @@ -14706,7 +15346,7 @@ class binary_writer // LCOV_EXCL_STOP // step 2: write each element - for (const auto& el : *j.m_value.object) + for (const auto& el : *j.m_data.m_value.object) { write_cbor(el.first); write_cbor(el.second); @@ -14735,7 +15375,7 @@ class binary_writer case value_t::boolean: // true and false { - oa->write_character(j.m_value.boolean + oa->write_character(j.m_data.m_value.boolean ? to_char_type(0xC3) : to_char_type(0xC2)); break; @@ -14743,75 +15383,75 @@ class binary_writer case value_t::number_integer: { - if (j.m_value.number_integer >= 0) + if (j.m_data.m_value.number_integer >= 0) { // MessagePack does not differentiate between positive // signed integers and unsigned integers. Therefore, we used // the code from the value_t::number_unsigned case here. - if (j.m_value.number_unsigned < 128) + if (j.m_data.m_value.number_unsigned < 128) { // positive fixnum - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } } else { - if (j.m_value.number_integer >= -32) + if (j.m_data.m_value.number_integer >= -32) { // negative fixnum - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { // int 8 oa->write_character(to_char_type(0xD0)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { // int 16 oa->write_character(to_char_type(0xD1)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { // int 32 oa->write_character(to_char_type(0xD2)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { // int 64 oa->write_character(to_char_type(0xD3)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } } break; @@ -14819,48 +15459,48 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_value.number_unsigned < 128) + if (j.m_data.m_value.number_unsigned < 128) { // positive fixnum - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } break; } case value_t::number_float: { - write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack); + write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack); break; } case value_t::string: { // step 1: write control byte and the string length - const auto N = j.m_value.string->size(); + const auto N = j.m_data.m_value.string->size(); if (N <= 31) { // fixstr @@ -14887,15 +15527,15 @@ class binary_writer // step 2: write the string oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); + reinterpret_cast(j.m_data.m_value.string->c_str()), + j.m_data.m_value.string->size()); break; } case value_t::array: { // step 1: write control byte and the array size - const auto N = j.m_value.array->size(); + const auto N = j.m_data.m_value.array->size(); if (N <= 15) { // fixarray @@ -14915,7 +15555,7 @@ class binary_writer } // step 2: write each element - for (const auto& el : *j.m_value.array) + for (const auto& el : *j.m_data.m_value.array) { write_msgpack(el); } @@ -14926,10 +15566,10 @@ class binary_writer { // step 0: determine if the binary type has a set subtype to // determine whether or not to use the ext or fixext types - const bool use_ext = j.m_value.binary->has_subtype(); + const bool use_ext = j.m_data.m_value.binary->has_subtype(); // step 1: write control byte and the byte string length - const auto N = j.m_value.binary->size(); + const auto N = j.m_data.m_value.binary->size(); if (N <= (std::numeric_limits::max)()) { std::uint8_t output_type{}; @@ -14974,18 +15614,18 @@ class binary_writer } else if (N <= (std::numeric_limits::max)()) { - std::uint8_t output_type = use_ext - ? 0xC8 // ext 16 - : 0xC5; // bin 16 + const std::uint8_t output_type = use_ext + ? 0xC8 // ext 16 + : 0xC5; // bin 16 oa->write_character(to_char_type(output_type)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - std::uint8_t output_type = use_ext - ? 0xC9 // ext 32 - : 0xC6; // bin 32 + const std::uint8_t output_type = use_ext + ? 0xC9 // ext 32 + : 0xC6; // bin 32 oa->write_character(to_char_type(output_type)); write_number(static_cast(N)); @@ -14994,12 +15634,12 @@ class binary_writer // step 1.5: if this is an ext type, write the subtype if (use_ext) { - write_number(static_cast(j.m_value.binary->subtype())); + write_number(static_cast(j.m_data.m_value.binary->subtype())); } // step 2: write the byte string oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), + reinterpret_cast(j.m_data.m_value.binary->data()), N); break; @@ -15008,7 +15648,7 @@ class binary_writer case value_t::object: { // step 1: write control byte and the object size - const auto N = j.m_value.object->size(); + const auto N = j.m_data.m_value.object->size(); if (N <= 15) { // fixmap @@ -15028,7 +15668,7 @@ class binary_writer } // step 2: write each element - for (const auto& el : *j.m_value.object) + for (const auto& el : *j.m_data.m_value.object) { write_msgpack(el.first); write_msgpack(el.second); @@ -15068,7 +15708,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(j.m_value.boolean + oa->write_character(j.m_data.m_value.boolean ? to_char_type('T') : to_char_type('F')); } @@ -15077,19 +15717,19 @@ class binary_writer case value_t::number_integer: { - write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata); break; } case value_t::number_unsigned: { - write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata); break; } case value_t::number_float: { - write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata); break; } @@ -15099,10 +15739,10 @@ class binary_writer { oa->write_character(to_char_type('S')); } - write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata); oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); + reinterpret_cast(j.m_data.m_value.string->c_str()), + j.m_data.m_value.string->size()); break; } @@ -15114,7 +15754,7 @@ class binary_writer } bool prefix_required = true; - if (use_type && !j.m_value.array->empty()) + if (use_type && !j.m_data.m_value.array->empty()) { JSON_ASSERT(use_count); const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); @@ -15137,10 +15777,10 @@ class binary_writer if (use_count) { oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata); } - for (const auto& el : *j.m_value.array) + for (const auto& el : *j.m_data.m_value.array) { write_ubjson(el, use_count, use_type, prefix_required, use_bjdata); } @@ -15160,7 +15800,7 @@ class binary_writer oa->write_character(to_char_type('[')); } - if (use_type && !j.m_value.binary->empty()) + if (use_type && !j.m_data.m_value.binary->empty()) { JSON_ASSERT(use_count); oa->write_character(to_char_type('$')); @@ -15170,21 +15810,21 @@ class binary_writer if (use_count) { oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata); } if (use_type) { oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - j.m_value.binary->size()); + reinterpret_cast(j.m_data.m_value.binary->data()), + j.m_data.m_value.binary->size()); } else { - for (size_t i = 0; i < j.m_value.binary->size(); ++i) + for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i) { oa->write_character(to_char_type('U')); - oa->write_character(j.m_value.binary->data()[i]); + oa->write_character(j.m_data.m_value.binary->data()[i]); } } @@ -15198,9 +15838,9 @@ class binary_writer case value_t::object: { - if (use_bjdata && j.m_value.object->size() == 3 && j.m_value.object->find("_ArrayType_") != j.m_value.object->end() && j.m_value.object->find("_ArraySize_") != j.m_value.object->end() && j.m_value.object->find("_ArrayData_") != j.m_value.object->end()) + if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end()) { - if (!write_bjdata_ndarray(*j.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) + if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) { break; } @@ -15212,7 +15852,7 @@ class binary_writer } bool prefix_required = true; - if (use_type && !j.m_value.object->empty()) + if (use_type && !j.m_data.m_value.object->empty()) { JSON_ASSERT(use_count); const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); @@ -15235,10 +15875,10 @@ class binary_writer if (use_count) { oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata); } - for (const auto& el : *j.m_value.object) + for (const auto& el : *j.m_data.m_value.object) { write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata); oa->write_characters( @@ -15388,19 +16028,19 @@ class binary_writer void write_bson_unsigned(const string_t& name, const BasicJsonType& j) { - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { write_bson_entry_header(name, 0x10 /* int32 */); - write_number(static_cast(j.m_value.number_unsigned), true); + write_number(static_cast(j.m_data.m_value.number_unsigned), true); } - else if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + else if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { write_bson_entry_header(name, 0x12 /* int64 */); - write_number(static_cast(j.m_value.number_unsigned), true); + write_number(static_cast(j.m_data.m_value.number_unsigned), true); } else { - JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); + JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); } } @@ -15481,13 +16121,13 @@ class binary_writer switch (j.type()) { case value_t::object: - return header_size + calc_bson_object_size(*j.m_value.object); + return header_size + calc_bson_object_size(*j.m_data.m_value.object); case value_t::array: - return header_size + calc_bson_array_size(*j.m_value.array); + return header_size + calc_bson_array_size(*j.m_data.m_value.array); case value_t::binary: - return header_size + calc_bson_binary_size(*j.m_value.binary); + return header_size + calc_bson_binary_size(*j.m_data.m_value.binary); case value_t::boolean: return header_size + 1ul; @@ -15496,13 +16136,13 @@ class binary_writer return header_size + 8ul; case value_t::number_integer: - return header_size + calc_bson_integer_size(j.m_value.number_integer); + return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer); case value_t::number_unsigned: - return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); + return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned); case value_t::string: - return header_size + calc_bson_string_size(*j.m_value.string); + return header_size + calc_bson_string_size(*j.m_data.m_value.string); case value_t::null: return header_size + 0ul; @@ -15528,28 +16168,28 @@ class binary_writer switch (j.type()) { case value_t::object: - return write_bson_object_entry(name, *j.m_value.object); + return write_bson_object_entry(name, *j.m_data.m_value.object); case value_t::array: - return write_bson_array(name, *j.m_value.array); + return write_bson_array(name, *j.m_data.m_value.array); case value_t::binary: - return write_bson_binary(name, *j.m_value.binary); + return write_bson_binary(name, *j.m_data.m_value.binary); case value_t::boolean: - return write_bson_boolean(name, j.m_value.boolean); + return write_bson_boolean(name, j.m_data.m_value.boolean); case value_t::number_float: - return write_bson_double(name, j.m_value.number_float); + return write_bson_double(name, j.m_data.m_value.number_float); case value_t::number_integer: - return write_bson_integer(name, j.m_value.number_integer); + return write_bson_integer(name, j.m_data.m_value.number_integer); case value_t::number_unsigned: return write_bson_unsigned(name, j); case value_t::string: - return write_bson_string(name, *j.m_value.string); + return write_bson_string(name, *j.m_data.m_value.string); case value_t::null: return write_bson_null(name); @@ -15571,8 +16211,8 @@ class binary_writer */ static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) { - std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast(0), - [](size_t result, const typename BasicJsonType::object_t::value_type & el) + const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast(0), + [](size_t result, const typename BasicJsonType::object_t::value_type & el) { return result += calc_bson_element_size(el.first, el.second); }); @@ -15822,35 +16462,35 @@ class binary_writer return 'Z'; case value_t::boolean: - return j.m_value.boolean ? 'T' : 'F'; + return j.m_data.m_value.boolean ? 'T' : 'F'; case value_t::number_integer: { - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { return 'i'; } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { return 'U'; } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { return 'I'; } - if (use_bjdata && ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)())) + if (use_bjdata && ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)())) { return 'u'; } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { return 'l'; } - if (use_bjdata && ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)())) + if (use_bjdata && ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)())) { return 'm'; } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { return 'L'; } @@ -15860,35 +16500,35 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'i'; } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'U'; } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'I'; } - if (use_bjdata && j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'u'; } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'l'; } - if (use_bjdata && j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'm'; } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'L'; } - if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits::max)()) + if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { return 'M'; } @@ -15897,7 +16537,7 @@ class binary_writer } case value_t::number_float: - return get_ubjson_float_prefix(j.m_value.number_float); + return get_ubjson_float_prefix(j.m_data.m_value.number_float); case value_t::string: return 'S'; @@ -15946,7 +16586,7 @@ class binary_writer std::size_t len = (value.at(key).empty() ? 0 : 1); for (const auto& el : value.at(key)) { - len *= static_cast(el.m_value.number_unsigned); + len *= static_cast(el.m_data.m_value.number_unsigned); } key = "_ArrayData_"; @@ -15968,70 +16608,70 @@ class binary_writer { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_unsigned), true); + write_number(static_cast(el.m_data.m_value.number_unsigned), true); } } else if (dtype == 'i') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_integer), true); + write_number(static_cast(el.m_data.m_value.number_integer), true); } } else if (dtype == 'u') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_unsigned), true); + write_number(static_cast(el.m_data.m_value.number_unsigned), true); } } else if (dtype == 'I') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_integer), true); + write_number(static_cast(el.m_data.m_value.number_integer), true); } } else if (dtype == 'm') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_unsigned), true); + write_number(static_cast(el.m_data.m_value.number_unsigned), true); } } else if (dtype == 'l') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_integer), true); + write_number(static_cast(el.m_data.m_value.number_integer), true); } } else if (dtype == 'M') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_unsigned), true); + write_number(static_cast(el.m_data.m_value.number_unsigned), true); } } else if (dtype == 'L') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_integer), true); + write_number(static_cast(el.m_data.m_value.number_integer), true); } } else if (dtype == 'd') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_float), true); + write_number(static_cast(el.m_data.m_value.number_float), true); } } else if (dtype == 'D') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_float), true); + write_number(static_cast(el.m_data.m_value.number_float), true); } } return false; @@ -16146,12 +16786,22 @@ class binary_writer /// the output output_adapter_t oa = nullptr; }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // reverse, remove, fill, find, none_of @@ -16168,6 +16818,15 @@ class binary_writer #include // move // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2009 Florian Loitsch +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // array @@ -16180,8 +16839,7 @@ class binary_writer // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -17072,7 +17730,7 @@ void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) // NB: If the neighbors are computed for single-precision numbers, there is a single float // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision // value is off by 1 ulp. -#if 0 +#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if) const boundaries w = compute_boundaries(static_cast(value)); #else const boundaries w = compute_boundaries(value); @@ -17210,7 +17868,7 @@ inline char* format_buffer(char* buf, int len, int decimal_exponent, return append_exponent(buf, n - 1); } -} // namespace dtoa_impl +} // namespace dtoa_impl /*! @brief generates a decimal representation of the floating-point number value in [first, last). @@ -17277,8 +17935,8 @@ char* to_chars(char* first, const char* last, FloatType value) return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); } -} // namespace detail -} // namespace nlohmann +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END // #include @@ -17295,10 +17953,10 @@ char* to_chars(char* first, const char* last, FloatType value) // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /////////////////// // serialization // /////////////////// @@ -17374,11 +18032,11 @@ class serializer const unsigned int indent_step, const unsigned int current_indent = 0) { - switch (val.m_type) + switch (val.m_data.m_type) { case value_t::object: { - if (val.m_value.object->empty()) + if (val.m_data.m_value.object->empty()) { o->write_characters("{}", 2); return; @@ -17396,8 +18054,8 @@ class serializer } // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + auto i = val.m_data.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) { o->write_characters(indent_string.c_str(), new_indent); o->write_character('\"'); @@ -17408,8 +18066,8 @@ class serializer } // last element - JSON_ASSERT(i != val.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_value.object->cend()); + JSON_ASSERT(i != val.m_data.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); o->write_characters(indent_string.c_str(), new_indent); o->write_character('\"'); dump_escaped(i->first, ensure_ascii); @@ -17425,8 +18083,8 @@ class serializer o->write_character('{'); // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + auto i = val.m_data.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) { o->write_character('\"'); dump_escaped(i->first, ensure_ascii); @@ -17436,8 +18094,8 @@ class serializer } // last element - JSON_ASSERT(i != val.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_value.object->cend()); + JSON_ASSERT(i != val.m_data.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); o->write_character('\"'); dump_escaped(i->first, ensure_ascii); o->write_characters("\":", 2); @@ -17451,7 +18109,7 @@ class serializer case value_t::array: { - if (val.m_value.array->empty()) + if (val.m_data.m_value.array->empty()) { o->write_characters("[]", 2); return; @@ -17469,8 +18127,8 @@ class serializer } // first n-1 elements - for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; ++i) + for (auto i = val.m_data.m_value.array->cbegin(); + i != val.m_data.m_value.array->cend() - 1; ++i) { o->write_characters(indent_string.c_str(), new_indent); dump(*i, true, ensure_ascii, indent_step, new_indent); @@ -17478,9 +18136,9 @@ class serializer } // last element - JSON_ASSERT(!val.m_value.array->empty()); + JSON_ASSERT(!val.m_data.m_value.array->empty()); o->write_characters(indent_string.c_str(), new_indent); - dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); + dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); o->write_character('\n'); o->write_characters(indent_string.c_str(), current_indent); @@ -17491,16 +18149,16 @@ class serializer o->write_character('['); // first n-1 elements - for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; ++i) + for (auto i = val.m_data.m_value.array->cbegin(); + i != val.m_data.m_value.array->cend() - 1; ++i) { dump(*i, false, ensure_ascii, indent_step, current_indent); o->write_character(','); } // last element - JSON_ASSERT(!val.m_value.array->empty()); - dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); + JSON_ASSERT(!val.m_data.m_value.array->empty()); + dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); o->write_character(']'); } @@ -17511,7 +18169,7 @@ class serializer case value_t::string: { o->write_character('\"'); - dump_escaped(*val.m_value.string, ensure_ascii); + dump_escaped(*val.m_data.m_value.string, ensure_ascii); o->write_character('\"'); return; } @@ -17533,24 +18191,24 @@ class serializer o->write_characters("\"bytes\": [", 10); - if (!val.m_value.binary->empty()) + if (!val.m_data.m_value.binary->empty()) { - for (auto i = val.m_value.binary->cbegin(); - i != val.m_value.binary->cend() - 1; ++i) + for (auto i = val.m_data.m_value.binary->cbegin(); + i != val.m_data.m_value.binary->cend() - 1; ++i) { dump_integer(*i); o->write_characters(", ", 2); } - dump_integer(val.m_value.binary->back()); + dump_integer(val.m_data.m_value.binary->back()); } o->write_characters("],\n", 3); o->write_characters(indent_string.c_str(), new_indent); o->write_characters("\"subtype\": ", 11); - if (val.m_value.binary->has_subtype()) + if (val.m_data.m_value.binary->has_subtype()) { - dump_integer(val.m_value.binary->subtype()); + dump_integer(val.m_data.m_value.binary->subtype()); } else { @@ -17564,21 +18222,21 @@ class serializer { o->write_characters("{\"bytes\":[", 10); - if (!val.m_value.binary->empty()) + if (!val.m_data.m_value.binary->empty()) { - for (auto i = val.m_value.binary->cbegin(); - i != val.m_value.binary->cend() - 1; ++i) + for (auto i = val.m_data.m_value.binary->cbegin(); + i != val.m_data.m_value.binary->cend() - 1; ++i) { dump_integer(*i); o->write_character(','); } - dump_integer(val.m_value.binary->back()); + dump_integer(val.m_data.m_value.binary->back()); } o->write_characters("],\"subtype\":", 12); - if (val.m_value.binary->has_subtype()) + if (val.m_data.m_value.binary->has_subtype()) { - dump_integer(val.m_value.binary->subtype()); + dump_integer(val.m_data.m_value.binary->subtype()); o->write_character('}'); } else @@ -17591,7 +18249,7 @@ class serializer case value_t::boolean: { - if (val.m_value.boolean) + if (val.m_data.m_value.boolean) { o->write_characters("true", 4); } @@ -17604,19 +18262,19 @@ class serializer case value_t::number_integer: { - dump_integer(val.m_value.number_integer); + dump_integer(val.m_data.m_value.number_integer); return; } case value_t::number_unsigned: { - dump_integer(val.m_value.number_unsigned); + dump_integer(val.m_data.m_value.number_unsigned); return; } case value_t::number_float: { - dump_float(val.m_value.number_float); + dump_float(val.m_data.m_value.number_float); return; } @@ -18190,8 +18848,8 @@ class serializer ? (byte & 0x3fu) | (codep << 6u) : (0xFFu >> type) & (byte); - std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); - JSON_ASSERT(index < 400); + const std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); + JSON_ASSERT(index < utf8d.size()); state = utf8d[index]; return state; } @@ -18247,14 +18905,23 @@ class serializer /// error_handler how to react on decoding errors const error_handler_t error_handler; }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // equal_to, less @@ -18271,8 +18938,7 @@ class serializer // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN /// ordered_map: a minimal map-like container that preserves insertion order /// for use within nlohmann::basic_json @@ -18370,7 +19036,7 @@ template , template::value, int> = 0> - T & at(KeyType && key) + T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -18398,7 +19064,7 @@ template , template::value, int> = 0> - const T & at(KeyType && key) const + const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -18432,7 +19098,7 @@ template , template::value, int> = 0> - size_type erase(KeyType && key) + size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -18523,7 +19189,7 @@ template , template::value, int> = 0> - size_type count(KeyType && key) const + size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -18549,7 +19215,7 @@ template , template::value, int> = 0> - iterator find(KeyType && key) + iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -18608,7 +19274,7 @@ template , JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare(); }; -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END #if defined(JSON_HAS_CPP_17) @@ -18621,8 +19287,7 @@ template , @see https://github.com/nlohmann @since version 1.0.0 */ -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN /*! @brief a class to store JSON values @@ -18644,6 +19309,7 @@ The invariants are checked by member function assert_invariant(). */ NLOHMANN_BASIC_JSON_TPL_DECLARATION class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + : public ::nlohmann::detail::json_base_class { private: template friend struct detail::external_constructor; @@ -18670,6 +19336,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// workaround type for MSVC using basic_json_t = NLOHMANN_BASIC_JSON_TPL; + using json_base_class_t = ::nlohmann::detail::json_base_class; JSON_PRIVATE_UNLESS_TESTED: // convenience aliases for types residing in namespace detail; @@ -19065,7 +19732,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec object = nullptr; // silence warning, see #821 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", nullptr)); // LCOV_EXCL_LINE + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.2", nullptr)); // LCOV_EXCL_LINE } break; } @@ -19104,6 +19771,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec void destroy(value_t t) { + if ( + (t == value_t::object && object == nullptr) || + (t == value_t::array && array == nullptr) || + (t == value_t::string && string == nullptr) || + (t == value_t::binary && binary == nullptr) + ) + { + //not initialized (e.g. due to exception in the ctor) + return; + } if (t == value_t::array || t == value_t::object) { // flatten the current json_value to a heap-allocated stack @@ -19134,18 +19811,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // its children to the stack to be processed later if (current_item.is_array()) { - std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); + std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack)); - current_item.m_value.array->clear(); + current_item.m_data.m_value.array->clear(); } else if (current_item.is_object()) { - for (auto&& it : *current_item.m_value.object) + for (auto&& it : *current_item.m_data.m_value.object) { stack.push_back(std::move(it.second)); } - current_item.m_value.object->clear(); + current_item.m_data.m_value.object->clear(); } // it's now safe that current_item get destructed @@ -19222,10 +19899,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec */ void assert_invariant(bool check_parents = true) const noexcept { - JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr); - JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr); - JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr); - JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr); + JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr); + JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr); + JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr); + JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr); #if JSON_DIAGNOSTICS JSON_TRY @@ -19244,11 +19921,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec void set_parents() { #if JSON_DIAGNOSTICS - switch (m_type) + switch (m_data.m_type) { case value_t::array: { - for (auto& element : *m_value.array) + for (auto& element : *m_data.m_value.array) { element.m_parent = this; } @@ -19257,7 +19934,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::object: { - for (auto& element : *m_value.object) + for (auto& element : *m_data.m_value.object) { element.second.m_parent = this; } @@ -19298,7 +19975,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { // see https://github.com/nlohmann/json/issues/2838 JSON_ASSERT(type() == value_t::array); - if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) { // capacity has changed: update all parents set_parents(); @@ -19354,7 +20031,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief create an empty value with a given type /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(const value_t v) - : m_type(v), m_value(v) + : m_data(v) { assert_invariant(); } @@ -19428,12 +20105,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec *this = nullptr; break; case value_t::discarded: - m_type = value_t::discarded; + m_data.m_type = value_t::discarded; break; default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } - JSON_ASSERT(m_type == val.type()); + JSON_ASSERT(m_data.m_type == val.type()); set_parents(); assert_invariant(); } @@ -19471,22 +20148,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_an_object) { // the initializer list is a list of pairs -> create object - m_type = value_t::object; - m_value = value_t::object; + m_data.m_type = value_t::object; + m_data.m_value = value_t::object; for (auto& element_ref : init) { auto element = element_ref.moved_or_copied(); - m_value.object->emplace( - std::move(*((*element.m_value.array)[0].m_value.string)), - std::move((*element.m_value.array)[1])); + m_data.m_value.object->emplace( + std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)), + std::move((*element.m_data.m_value.array)[1])); } } else { // the initializer list describes an array -> create array - m_type = value_t::array; - m_value.array = create(init.begin(), init.end()); + m_data.m_type = value_t::array; + m_data.m_value.array = create(init.begin(), init.end()); } set_parents(); @@ -19499,8 +20176,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(const typename binary_t::container_type& init) { auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = init; + res.m_data.m_type = value_t::binary; + res.m_data.m_value = init; return res; } @@ -19510,8 +20187,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) { auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = binary_t(init, subtype); + res.m_data.m_type = value_t::binary; + res.m_data.m_value = binary_t(init, subtype); return res; } @@ -19521,8 +20198,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(typename binary_t::container_type&& init) { auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = std::move(init); + res.m_data.m_type = value_t::binary; + res.m_data.m_value = std::move(init); return res; } @@ -19532,8 +20209,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) { auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = binary_t(std::move(init), subtype); + res.m_data.m_type = value_t::binary; + res.m_data.m_value = binary_t(std::move(init), subtype); return res; } @@ -19555,10 +20232,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief construct an array with count copies of given value /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ - basic_json(size_type cnt, const basic_json& val) - : m_type(value_t::array) + basic_json(size_type cnt, const basic_json& val): + m_data{cnt, val} { - m_value.array = create(cnt, val); set_parents(); assert_invariant(); } @@ -19580,10 +20256,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // copy type from first iterator - m_type = first.m_object->m_type; + m_data.m_type = first.m_object->m_data.m_type; // check if iterator range is complete for primitive values - switch (m_type) + switch (m_data.m_type) { case value_t::boolean: case value_t::number_float: @@ -19608,55 +20284,55 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } - switch (m_type) + switch (m_data.m_type) { case value_t::number_integer: { - m_value.number_integer = first.m_object->m_value.number_integer; + m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer; break; } case value_t::number_unsigned: { - m_value.number_unsigned = first.m_object->m_value.number_unsigned; + m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned; break; } case value_t::number_float: { - m_value.number_float = first.m_object->m_value.number_float; + m_data.m_value.number_float = first.m_object->m_data.m_value.number_float; break; } case value_t::boolean: { - m_value.boolean = first.m_object->m_value.boolean; + m_data.m_value.boolean = first.m_object->m_data.m_value.boolean; break; } case value_t::string: { - m_value = *first.m_object->m_value.string; + m_data.m_value = *first.m_object->m_data.m_value.string; break; } case value_t::object: { - m_value.object = create(first.m_it.object_iterator, - last.m_it.object_iterator); + m_data.m_value.object = create(first.m_it.object_iterator, + last.m_it.object_iterator); break; } case value_t::array: { - m_value.array = create(first.m_it.array_iterator, - last.m_it.array_iterator); + m_data.m_value.array = create(first.m_it.array_iterator, + last.m_it.array_iterator); break; } case value_t::binary: { - m_value = *first.m_object->m_value.binary; + m_data.m_value = *first.m_object->m_data.m_value.binary; break; } @@ -19683,58 +20359,59 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief copy constructor /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(const basic_json& other) - : m_type(other.m_type) + : json_base_class_t(other) { + m_data.m_type = other.m_data.m_type; // check of passed value is valid other.assert_invariant(); - switch (m_type) + switch (m_data.m_type) { case value_t::object: { - m_value = *other.m_value.object; + m_data.m_value = *other.m_data.m_value.object; break; } case value_t::array: { - m_value = *other.m_value.array; + m_data.m_value = *other.m_data.m_value.array; break; } case value_t::string: { - m_value = *other.m_value.string; + m_data.m_value = *other.m_data.m_value.string; break; } case value_t::boolean: { - m_value = other.m_value.boolean; + m_data.m_value = other.m_data.m_value.boolean; break; } case value_t::number_integer: { - m_value = other.m_value.number_integer; + m_data.m_value = other.m_data.m_value.number_integer; break; } case value_t::number_unsigned: { - m_value = other.m_value.number_unsigned; + m_data.m_value = other.m_data.m_value.number_unsigned; break; } case value_t::number_float: { - m_value = other.m_value.number_float; + m_data.m_value = other.m_data.m_value.number_float; break; } case value_t::binary: { - m_value = *other.m_value.binary; + m_data.m_value = *other.m_data.m_value.binary; break; } @@ -19751,15 +20428,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief move constructor /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(basic_json&& other) noexcept - : m_type(std::move(other.m_type)), - m_value(std::move(other.m_value)) + : json_base_class_t(std::forward(other)), + m_data(std::move(other.m_data)) { // check that passed value is valid other.assert_invariant(false); // invalidate payload - other.m_type = value_t::null; - other.m_value = {}; + other.m_data.m_type = value_t::null; + other.m_data.m_value = {}; set_parents(); assert_invariant(); @@ -19771,15 +20448,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value&& std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value + std::is_nothrow_move_assignable::value&& + std::is_nothrow_move_assignable::value ) { // check that passed value is valid other.assert_invariant(); using std::swap; - swap(m_type, other.m_type); - swap(m_value, other.m_value); + swap(m_data.m_type, other.m_data.m_type); + swap(m_data.m_value, other.m_data.m_value); + json_base_class_t::operator=(std::move(other)); set_parents(); assert_invariant(); @@ -19791,7 +20470,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec ~basic_json() noexcept { assert_invariant(false); - m_value.destroy(m_type); } /// @} @@ -19831,7 +20509,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/type/ constexpr value_t type() const noexcept { - return m_type; + return m_data.m_type; } /// @brief return whether type is primitive @@ -19852,14 +20530,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/is_null/ constexpr bool is_null() const noexcept { - return m_type == value_t::null; + return m_data.m_type == value_t::null; } /// @brief return whether value is a boolean /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/ constexpr bool is_boolean() const noexcept { - return m_type == value_t::boolean; + return m_data.m_type == value_t::boolean; } /// @brief return whether value is a number @@ -19873,63 +20551,63 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/ constexpr bool is_number_integer() const noexcept { - return m_type == value_t::number_integer || m_type == value_t::number_unsigned; + return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned; } /// @brief return whether value is an unsigned integer number /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/ constexpr bool is_number_unsigned() const noexcept { - return m_type == value_t::number_unsigned; + return m_data.m_type == value_t::number_unsigned; } /// @brief return whether value is a floating-point number /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/ constexpr bool is_number_float() const noexcept { - return m_type == value_t::number_float; + return m_data.m_type == value_t::number_float; } /// @brief return whether value is an object /// @sa https://json.nlohmann.me/api/basic_json/is_object/ constexpr bool is_object() const noexcept { - return m_type == value_t::object; + return m_data.m_type == value_t::object; } /// @brief return whether value is an array /// @sa https://json.nlohmann.me/api/basic_json/is_array/ constexpr bool is_array() const noexcept { - return m_type == value_t::array; + return m_data.m_type == value_t::array; } /// @brief return whether value is a string /// @sa https://json.nlohmann.me/api/basic_json/is_string/ constexpr bool is_string() const noexcept { - return m_type == value_t::string; + return m_data.m_type == value_t::string; } /// @brief return whether value is a binary array /// @sa https://json.nlohmann.me/api/basic_json/is_binary/ constexpr bool is_binary() const noexcept { - return m_type == value_t::binary; + return m_data.m_type == value_t::binary; } /// @brief return whether value is discarded /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/ constexpr bool is_discarded() const noexcept { - return m_type == value_t::discarded; + return m_data.m_type == value_t::discarded; } /// @brief return the type of the JSON value (implicit) /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/ constexpr operator value_t() const noexcept { - return m_type; + return m_data.m_type; } /// @} @@ -19944,7 +20622,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { if (JSON_HEDLEY_LIKELY(is_boolean())) { - return m_value.boolean; + return m_data.m_value.boolean; } JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this)); @@ -19953,97 +20631,97 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// get a pointer to the value (object) object_t* get_impl_ptr(object_t* /*unused*/) noexcept { - return is_object() ? m_value.object : nullptr; + return is_object() ? m_data.m_value.object : nullptr; } /// get a pointer to the value (object) constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept { - return is_object() ? m_value.object : nullptr; + return is_object() ? m_data.m_value.object : nullptr; } /// get a pointer to the value (array) array_t* get_impl_ptr(array_t* /*unused*/) noexcept { - return is_array() ? m_value.array : nullptr; + return is_array() ? m_data.m_value.array : nullptr; } /// get a pointer to the value (array) constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept { - return is_array() ? m_value.array : nullptr; + return is_array() ? m_data.m_value.array : nullptr; } /// get a pointer to the value (string) string_t* get_impl_ptr(string_t* /*unused*/) noexcept { - return is_string() ? m_value.string : nullptr; + return is_string() ? m_data.m_value.string : nullptr; } /// get a pointer to the value (string) constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept { - return is_string() ? m_value.string : nullptr; + return is_string() ? m_data.m_value.string : nullptr; } /// get a pointer to the value (boolean) boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept { - return is_boolean() ? &m_value.boolean : nullptr; + return is_boolean() ? &m_data.m_value.boolean : nullptr; } /// get a pointer to the value (boolean) constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept { - return is_boolean() ? &m_value.boolean : nullptr; + return is_boolean() ? &m_data.m_value.boolean : nullptr; } /// get a pointer to the value (integer number) number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept { - return is_number_integer() ? &m_value.number_integer : nullptr; + return is_number_integer() ? &m_data.m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept { - return is_number_integer() ? &m_value.number_integer : nullptr; + return is_number_integer() ? &m_data.m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; } /// get a pointer to the value (unsigned number) constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; } /// get a pointer to the value (floating-point number) number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept { - return is_number_float() ? &m_value.number_float : nullptr; + return is_number_float() ? &m_data.m_value.number_float : nullptr; } /// get a pointer to the value (floating-point number) constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept { - return is_number_float() ? &m_value.number_float : nullptr; + return is_number_float() ? &m_data.m_value.number_float : nullptr; } /// get a pointer to the value (binary) binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept { - return is_binary() ? m_value.binary : nullptr; + return is_binary() ? m_data.m_value.binary : nullptr; } /// get a pointer to the value (binary) constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept { - return is_binary() ? m_value.binary : nullptr; + return is_binary() ? m_data.m_value.binary : nullptr; } /*! @@ -20481,7 +21159,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { JSON_TRY { - return set_parent(m_value.array->at(idx)); + return set_parent(m_data.m_value.array->at(idx)); } JSON_CATCH (std::out_of_range&) { @@ -20504,7 +21182,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { JSON_TRY { - return m_value.array->at(idx); + return m_data.m_value.array->at(idx); } JSON_CATCH (std::out_of_range&) { @@ -20528,8 +21206,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_value.object->find(key); - if (it == m_value.object->end()) + auto it = m_data.m_value.object->find(key); + if (it == m_data.m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); } @@ -20548,8 +21226,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_value.object->find(std::forward(key)); - if (it == m_value.object->end()) + auto it = m_data.m_value.object->find(std::forward(key)); + if (it == m_data.m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward(key)), "' not found"), this)); } @@ -20566,8 +21244,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_value.object->find(key); - if (it == m_value.object->end()) + auto it = m_data.m_value.object->find(key); + if (it == m_data.m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); } @@ -20586,8 +21264,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_value.object->find(std::forward(key)); - if (it == m_value.object->end()) + auto it = m_data.m_value.object->find(std::forward(key)); + if (it == m_data.m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward(key)), "' not found"), this)); } @@ -20601,8 +21279,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty array if (is_null()) { - m_type = value_t::array; - m_value.array = create(); + m_data.m_type = value_t::array; + m_data.m_value.array = create(); assert_invariant(); } @@ -20610,17 +21288,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (JSON_HEDLEY_LIKELY(is_array())) { // fill up array with null values if given idx is outside range - if (idx >= m_value.array->size()) + if (idx >= m_data.m_value.array->size()) { #if JSON_DIAGNOSTICS // remember array size & capacity before resizing - const auto old_size = m_value.array->size(); - const auto old_capacity = m_value.array->capacity(); + const auto old_size = m_data.m_value.array->size(); + const auto old_capacity = m_data.m_value.array->capacity(); #endif - m_value.array->resize(idx + 1); + m_data.m_value.array->resize(idx + 1); #if JSON_DIAGNOSTICS - if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) { // capacity has changed: update all parents set_parents(); @@ -20634,7 +21312,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec assert_invariant(); } - return m_value.array->operator[](idx); + return m_data.m_value.array->operator[](idx); } JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); @@ -20647,7 +21325,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // const operator[] only works for arrays if (JSON_HEDLEY_LIKELY(is_array())) { - return m_value.array->operator[](idx); + return m_data.m_value.array->operator[](idx); } JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); @@ -20660,15 +21338,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty object if (is_null()) { - m_type = value_t::object; - m_value.object = create(); + m_data.m_type = value_t::object; + m_data.m_value.object = create(); assert_invariant(); } // operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto result = m_value.object->emplace(std::move(key), nullptr); + auto result = m_data.m_value.object->emplace(std::move(key), nullptr); return set_parent(result.first->second); } @@ -20682,8 +21360,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // const operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto it = m_value.object->find(key); - JSON_ASSERT(it != m_value.object->end()); + auto it = m_data.m_value.object->find(key); + JSON_ASSERT(it != m_data.m_value.object->end()); return it->second; } @@ -20713,15 +21391,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty object if (is_null()) { - m_type = value_t::object; - m_value.object = create(); + m_data.m_type = value_t::object; + m_data.m_value.object = create(); assert_invariant(); } // operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto result = m_value.object->emplace(std::forward(key), nullptr); + auto result = m_data.m_value.object->emplace(std::forward(key), nullptr); return set_parent(result.first->second); } @@ -20737,22 +21415,32 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // const operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto it = m_value.object->find(std::forward(key)); - JSON_ASSERT(it != m_value.object->end()); + auto it = m_data.m_value.object->find(std::forward(key)); + JSON_ASSERT(it != m_data.m_value.object->end()); return it->second; } JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); } + private: + template + using is_comparable_with_object_key = detail::is_comparable < + object_comparator_t, const typename object_t::key_type&, KeyType >; + + template + using value_return_type = std::conditional < + detail::is_c_string_uncvref::value, + string_t, typename std::decay::type >; + + public: /// @brief access specified object element with default value /// @sa https://json.nlohmann.me/api/basic_json/value/ - // this is the value(const typename object_t::key_type&) overload - template < class KeyType, class ValueType, detail::enable_if_t < - std::is_same::value + template < class ValueType, detail::enable_if_t < + !detail::is_transparent::value && detail::is_getable::value - && !std::is_same::value, int > = 0 > - typename std::decay::type value(const KeyType& key, ValueType && default_value) const + && !std::is_same>::value, int > = 0 > + ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const { // value only works for objects if (JSON_HEDLEY_LIKELY(is_object())) @@ -20761,10 +21449,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const auto it = find(key); if (it != end()) { - return it->template get::type>(); + return it->template get(); } - return std::forward(default_value); + return default_value; } JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); @@ -20772,36 +21460,38 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief access specified object element with default value /// @sa https://json.nlohmann.me/api/basic_json/value/ - /// overload for a default value of type const char* - string_t value(const typename object_t::key_type& key, const char* default_value) const + template < class ValueType, class ReturnType = typename value_return_type::type, + detail::enable_if_t < + !detail::is_transparent::value + && detail::is_getable::value + && !std::is_same>::value, int > = 0 > + ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const { - return value(key, string_t(default_value)); - } + // value only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + // if key is found, return value and given default value otherwise + const auto it = find(key); + if (it != end()) + { + return it->template get(); + } - // these two functions, in conjunction with value(const KeyType &, ValueType &&), - // resolve an ambiguity that would otherwise occur between the json_pointer and - // typename object_t::key_type & overloads - template < class ValueType, detail::enable_if_t < - detail::is_getable::value - && !std::is_same::value, int > = 0 > - typename std::decay::type value(const char* key, ValueType && default_value) const - { - return value(typename object_t::key_type(key), std::forward(default_value)); - } + return std::forward(default_value); + } - string_t value(const char* key, const char* default_value) const - { - return value(typename object_t::key_type(key), string_t(default_value)); + JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); } /// @brief access specified object element with default value /// @sa https://json.nlohmann.me/api/basic_json/value/ - /// using std::is_convertible in a std::enable_if will fail when using explicit conversions - template < class KeyType, class ValueType, detail::enable_if_t < - detail::is_getable::value - && !std::is_same::value - && detail::is_usable_as_basic_json_key_type::value, int > = 0 > - typename std::decay::type value(KeyType && key, ValueType && default_value) const + template < class ValueType, class KeyType, detail::enable_if_t < + detail::is_transparent::value + && !detail::is_json_pointer::value + && is_comparable_with_object_key::value + && detail::is_getable::value + && !std::is_same>::value, int > = 0 > + ValueType value(KeyType && key, const ValueType& default_value) const { // value only works for objects if (JSON_HEDLEY_LIKELY(is_object())) @@ -20810,29 +21500,47 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const auto it = find(std::forward(key)); if (it != end()) { - return it->template get::type>(); + return it->template get(); } - return std::forward(default_value); + return default_value; } JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); } - /// @brief access specified object element with default value + /// @brief access specified object element via JSON Pointer with default value /// @sa https://json.nlohmann.me/api/basic_json/value/ - /// overload for a default value of type const char* - template < class KeyType, detail::enable_if_t < - !detail::is_json_pointer::value, int > = 0 > - string_t value(KeyType && key, const char* default_value) const + template < class ValueType, class KeyType, class ReturnType = typename value_return_type::type, + detail::enable_if_t < + detail::is_transparent::value + && !detail::is_json_pointer::value + && is_comparable_with_object_key::value + && detail::is_getable::value + && !std::is_same>::value, int > = 0 > + ReturnType value(KeyType && key, ValueType && default_value) const { - return value(std::forward(key), string_t(default_value)); + // value only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + // if key is found, return value and given default value otherwise + const auto it = find(std::forward(key)); + if (it != end()) + { + return it->template get(); + } + + return std::forward(default_value); + } + + JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); } /// @brief access specified object element via JSON Pointer with default value /// @sa https://json.nlohmann.me/api/basic_json/value/ template < class ValueType, detail::enable_if_t < - detail::is_getable::value, int> = 0 > + detail::is_getable::value + && !std::is_same>::value, int > = 0 > ValueType value(const json_pointer& ptr, const ValueType& default_value) const { // value only works for objects @@ -20852,29 +21560,50 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); } + /// @brief access specified object element via JSON Pointer with default value + /// @sa https://json.nlohmann.me/api/basic_json/value/ + template < class ValueType, class ReturnType = typename value_return_type::type, + detail::enable_if_t < + detail::is_getable::value + && !std::is_same>::value, int > = 0 > + ReturnType value(const json_pointer& ptr, ValueType && default_value) const + { + // value only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + // if pointer resolves a value, return it or use default value + JSON_TRY + { + return ptr.get_checked(this).template get(); + } + JSON_INTERNAL_CATCH (out_of_range&) + { + return std::forward(default_value); + } + } + + JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); + } + template < class ValueType, class BasicJsonType, detail::enable_if_t < - detail::is_getable::value, int> = 0 > + detail::is_basic_json::value + && detail::is_getable::value + && !std::is_same>::value, int > = 0 > JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) ValueType value(const ::nlohmann::json_pointer& ptr, const ValueType& default_value) const { return value(ptr.convert(), default_value); } - /// @brief access specified object element via JSON Pointer with default value - /// @sa https://json.nlohmann.me/api/basic_json/value/ - /// overload for a default value of type const char* - JSON_HEDLEY_NON_NULL(3) - string_t value(const json_pointer& ptr, const char* default_value) const - { - return value(ptr, string_t(default_value)); - } - - template + template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type::type, + detail::enable_if_t < + detail::is_basic_json::value + && detail::is_getable::value + && !std::is_same>::value, int > = 0 > JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) - JSON_HEDLEY_NON_NULL(3) - string_t value(const typename ::nlohmann::json_pointer& ptr, const char* default_value) const + ReturnType value(const ::nlohmann::json_pointer& ptr, ValueType && default_value) const { - return value(ptr.convert(), default_value); + return value(ptr.convert(), std::forward(default_value)); } /// @brief access the first element @@ -20924,7 +21653,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec IteratorType result = end(); - switch (m_type) + switch (m_data.m_type) { case value_t::boolean: case value_t::number_float: @@ -20941,32 +21670,32 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_string()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.string); - std::allocator_traits::deallocate(alloc, m_value.string, 1); - m_value.string = nullptr; + std::allocator_traits::destroy(alloc, m_data.m_value.string); + std::allocator_traits::deallocate(alloc, m_data.m_value.string, 1); + m_data.m_value.string = nullptr; } else if (is_binary()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.binary); - std::allocator_traits::deallocate(alloc, m_value.binary, 1); - m_value.binary = nullptr; + std::allocator_traits::destroy(alloc, m_data.m_value.binary); + std::allocator_traits::deallocate(alloc, m_data.m_value.binary, 1); + m_data.m_value.binary = nullptr; } - m_type = value_t::null; + m_data.m_type = value_t::null; assert_invariant(); break; } case value_t::object: { - result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); + result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator); break; } case value_t::array: { - result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); + result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator); break; } @@ -20994,7 +21723,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec IteratorType result = end(); - switch (m_type) + switch (m_data.m_type) { case value_t::boolean: case value_t::number_float: @@ -21012,33 +21741,33 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_string()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.string); - std::allocator_traits::deallocate(alloc, m_value.string, 1); - m_value.string = nullptr; + std::allocator_traits::destroy(alloc, m_data.m_value.string); + std::allocator_traits::deallocate(alloc, m_data.m_value.string, 1); + m_data.m_value.string = nullptr; } else if (is_binary()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.binary); - std::allocator_traits::deallocate(alloc, m_value.binary, 1); - m_value.binary = nullptr; + std::allocator_traits::destroy(alloc, m_data.m_value.binary); + std::allocator_traits::deallocate(alloc, m_data.m_value.binary, 1); + m_data.m_value.binary = nullptr; } - m_type = value_t::null; + m_data.m_type = value_t::null; assert_invariant(); break; } case value_t::object: { - result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, + result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator); break; } case value_t::array: { - result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, + result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator); break; } @@ -21063,7 +21792,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); } - return m_value.object->erase(std::forward(key)); + return m_data.m_value.object->erase(std::forward(key)); } template < typename KeyType, detail::enable_if_t < @@ -21076,10 +21805,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); } - const auto it = m_value.object->find(std::forward(key)); - if (it != m_value.object->end()) + const auto it = m_data.m_value.object->find(std::forward(key)); + if (it != m_data.m_value.object->end()) { - m_value.object->erase(it); + m_data.m_value.object->erase(it); return 1; } return 0; @@ -21117,7 +21846,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); } - m_value.array->erase(m_value.array->begin() + static_cast(idx)); + m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast(idx)); } else { @@ -21143,7 +21872,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_value.object->find(key); + result.m_it.object_iterator = m_data.m_value.object->find(key); } return result; @@ -21157,7 +21886,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_value.object->find(key); + result.m_it.object_iterator = m_data.m_value.object->find(key); } return result; @@ -21173,7 +21902,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_value.object->find(std::forward(key)); + result.m_it.object_iterator = m_data.m_value.object->find(std::forward(key)); } return result; @@ -21189,7 +21918,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_value.object->find(std::forward(key)); + result.m_it.object_iterator = m_data.m_value.object->find(std::forward(key)); } return result; @@ -21200,7 +21929,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec size_type count(const typename object_t::key_type& key) const { // return 0 for all nonobject types - return is_object() ? m_value.object->count(key) : 0; + return is_object() ? m_data.m_value.object->count(key) : 0; } /// @brief returns the number of occurrences of a key in a JSON object @@ -21210,14 +21939,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec size_type count(KeyType && key) const { // return 0 for all nonobject types - return is_object() ? m_value.object->count(std::forward(key)) : 0; + return is_object() ? m_data.m_value.object->count(std::forward(key)) : 0; } /// @brief check the existence of an element in a JSON object /// @sa https://json.nlohmann.me/api/basic_json/contains/ bool contains(const typename object_t::key_type& key) const { - return is_object() && m_value.object->find(key) != m_value.object->end(); + return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end(); } /// @brief check the existence of an element in a JSON object @@ -21226,7 +21955,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::is_usable_as_basic_json_key_type::value, int> = 0> bool contains(KeyType && key) const { - return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); + return is_object() && m_data.m_value.object->find(std::forward(key)) != m_data.m_value.object->end(); } /// @brief check the existence of an element in a JSON object given a JSON pointer @@ -21236,9 +21965,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return ptr.contains(this); } - template + template::value, int> = 0> JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) - bool contains(const typename ::nlohmann::json_pointer ptr) const + bool contains(const typename ::nlohmann::json_pointer& ptr) const { return ptr.contains(this); } @@ -21396,7 +22125,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/empty/ bool empty() const noexcept { - switch (m_type) + switch (m_data.m_type) { case value_t::null: { @@ -21407,13 +22136,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::array: { // delegate call to array_t::empty() - return m_value.array->empty(); + return m_data.m_value.array->empty(); } case value_t::object: { // delegate call to object_t::empty() - return m_value.object->empty(); + return m_data.m_value.object->empty(); } case value_t::string: @@ -21435,7 +22164,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/size/ size_type size() const noexcept { - switch (m_type) + switch (m_data.m_type) { case value_t::null: { @@ -21446,13 +22175,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::array: { // delegate call to array_t::size() - return m_value.array->size(); + return m_data.m_value.array->size(); } case value_t::object: { // delegate call to object_t::size() - return m_value.object->size(); + return m_data.m_value.object->size(); } case value_t::string: @@ -21474,18 +22203,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/max_size/ size_type max_size() const noexcept { - switch (m_type) + switch (m_data.m_type) { case value_t::array: { // delegate call to array_t::max_size() - return m_value.array->max_size(); + return m_data.m_value.array->max_size(); } case value_t::object: { // delegate call to object_t::max_size() - return m_value.object->max_size(); + return m_data.m_value.object->max_size(); } case value_t::null: @@ -21518,53 +22247,53 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/clear/ void clear() noexcept { - switch (m_type) + switch (m_data.m_type) { case value_t::number_integer: { - m_value.number_integer = 0; + m_data.m_value.number_integer = 0; break; } case value_t::number_unsigned: { - m_value.number_unsigned = 0; + m_data.m_value.number_unsigned = 0; break; } case value_t::number_float: { - m_value.number_float = 0.0; + m_data.m_value.number_float = 0.0; break; } case value_t::boolean: { - m_value.boolean = false; + m_data.m_value.boolean = false; break; } case value_t::string: { - m_value.string->clear(); + m_data.m_value.string->clear(); break; } case value_t::binary: { - m_value.binary->clear(); + m_data.m_value.binary->clear(); break; } case value_t::array: { - m_value.array->clear(); + m_data.m_value.array->clear(); break; } case value_t::object: { - m_value.object->clear(); + m_data.m_value.object->clear(); break; } @@ -21588,15 +22317,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an array if (is_null()) { - m_type = value_t::array; - m_value = value_t::array; + m_data.m_type = value_t::array; + m_data.m_value = value_t::array; assert_invariant(); } // add element to array (move semantics) - const auto old_capacity = m_value.array->capacity(); - m_value.array->push_back(std::move(val)); - set_parent(m_value.array->back(), old_capacity); + const auto old_capacity = m_data.m_value.array->capacity(); + m_data.m_value.array->push_back(std::move(val)); + set_parent(m_data.m_value.array->back(), old_capacity); // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor } @@ -21621,15 +22350,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an array if (is_null()) { - m_type = value_t::array; - m_value = value_t::array; + m_data.m_type = value_t::array; + m_data.m_value = value_t::array; assert_invariant(); } // add element to array - const auto old_capacity = m_value.array->capacity(); - m_value.array->push_back(val); - set_parent(m_value.array->back(), old_capacity); + const auto old_capacity = m_data.m_value.array->capacity(); + m_data.m_value.array->push_back(val); + set_parent(m_data.m_value.array->back(), old_capacity); } /// @brief add an object to an array @@ -21653,13 +22382,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an object if (is_null()) { - m_type = value_t::object; - m_value = value_t::object; + m_data.m_type = value_t::object; + m_data.m_value = value_t::object; assert_invariant(); } // add element to object - auto res = m_value.object->insert(val); + auto res = m_data.m_value.object->insert(val); set_parent(res.first->second); } @@ -21709,15 +22438,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an array if (is_null()) { - m_type = value_t::array; - m_value = value_t::array; + m_data.m_type = value_t::array; + m_data.m_value = value_t::array; assert_invariant(); } // add element to array (perfect forwarding) - const auto old_capacity = m_value.array->capacity(); - m_value.array->emplace_back(std::forward(args)...); - return set_parent(m_value.array->back(), old_capacity); + const auto old_capacity = m_data.m_value.array->capacity(); + m_data.m_value.array->emplace_back(std::forward(args)...); + return set_parent(m_data.m_value.array->back(), old_capacity); } /// @brief add an object to an object if key does not exist @@ -21734,13 +22463,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an object if (is_null()) { - m_type = value_t::object; - m_value = value_t::object; + m_data.m_type = value_t::object; + m_data.m_value = value_t::object; assert_invariant(); } // add element to array (perfect forwarding) - auto res = m_value.object->emplace(std::forward(args)...); + auto res = m_data.m_value.object->emplace(std::forward(args)...); set_parent(res.first->second); // create result iterator and set iterator to the result of emplace @@ -21758,14 +22487,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec iterator insert_iterator(const_iterator pos, Args&& ... args) { iterator result(this); - JSON_ASSERT(m_value.array != nullptr); + JSON_ASSERT(m_data.m_value.array != nullptr); - auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); - m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); - result.m_it.array_iterator = m_value.array->begin() + insert_pos; + auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator); + m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); + result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos; // This could have been written as: - // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); + // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val); // but the return value of insert is missing in GCC 4.8, so it is written this way instead. set_parents(); @@ -21892,7 +22621,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this)); } - m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); } /// @brief updates a JSON object from another object, overwriting existing keys @@ -21909,8 +22638,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty object if (is_null()) { - m_type = value_t::object; - m_value.object = create(); + m_data.m_type = value_t::object; + m_data.m_value.object = create(); assert_invariant(); } @@ -21935,16 +22664,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { if (merge_objects && it.value().is_object()) { - auto it2 = m_value.object->find(it.key()); - if (it2 != m_value.object->end()) + auto it2 = m_data.m_value.object->find(it.key()); + if (it2 != m_data.m_value.object->end()) { it2->second.update(it.value(), true); continue; } } - m_value.object->operator[](it.key()) = it.value(); + m_data.m_value.object->operator[](it.key()) = it.value(); #if JSON_DIAGNOSTICS - m_value.object->operator[](it.key()).m_parent = this; + m_data.m_value.object->operator[](it.key()).m_parent = this; #endif } } @@ -21958,8 +22687,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec std::is_nothrow_move_assignable::value ) { - std::swap(m_type, other.m_type); - std::swap(m_value, other.m_value); + std::swap(m_data.m_type, other.m_data.m_type); + std::swap(m_data.m_value, other.m_data.m_value); set_parents(); other.set_parents(); @@ -21985,11 +22714,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // swap only works for arrays if (JSON_HEDLEY_LIKELY(is_array())) { - std::swap(*(m_value.array), other); + using std::swap; + swap(*(m_data.m_value.array), other); } else { - JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this)); + JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this)); } } @@ -22000,11 +22730,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // swap only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - std::swap(*(m_value.object), other); + using std::swap; + swap(*(m_data.m_value.object), other); } else { - JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this)); + JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this)); } } @@ -22015,11 +22746,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // swap only works for strings if (JSON_HEDLEY_LIKELY(is_string())) { - std::swap(*(m_value.string), other); + using std::swap; + swap(*(m_data.m_value.string), other); } else { - JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this)); + JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this)); } } @@ -22030,11 +22762,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // swap only works for strings if (JSON_HEDLEY_LIKELY(is_binary())) { - std::swap(*(m_value.binary), other); + using std::swap; + swap(*(m_data.m_value.binary), other); } else { - JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this)); + JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this)); } } @@ -22045,11 +22778,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // swap only works for strings if (JSON_HEDLEY_LIKELY(is_binary())) { - std::swap(*(m_value.binary), other); + using std::swap; + swap(*(m_data.m_value.binary), other); } else { - JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this)); + JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this)); } } @@ -22073,31 +22807,31 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec switch (lhs_type) \ { \ case value_t::array: \ - return (*lhs.m_value.array) op (*rhs.m_value.array); \ + return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \ \ case value_t::object: \ - return (*lhs.m_value.object) op (*rhs.m_value.object); \ + return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \ \ case value_t::null: \ return (null_result); \ \ case value_t::string: \ - return (*lhs.m_value.string) op (*rhs.m_value.string); \ + return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \ \ case value_t::boolean: \ - return (lhs.m_value.boolean) op (rhs.m_value.boolean); \ + return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \ \ case value_t::number_integer: \ - return (lhs.m_value.number_integer) op (rhs.m_value.number_integer); \ + return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \ \ case value_t::number_unsigned: \ - return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned); \ + return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \ \ case value_t::number_float: \ - return (lhs.m_value.number_float) op (rhs.m_value.number_float); \ + return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \ \ case value_t::binary: \ - return (*lhs.m_value.binary) op (*rhs.m_value.binary); \ + return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \ \ case value_t::discarded: \ default: \ @@ -22106,27 +22840,27 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } \ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \ { \ - return static_cast(lhs.m_value.number_integer) op rhs.m_value.number_float; \ + return static_cast(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \ } \ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \ { \ - return lhs.m_value.number_float op static_cast(rhs.m_value.number_integer); \ + return lhs.m_data.m_value.number_float op static_cast(rhs.m_data.m_value.number_integer); \ } \ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \ { \ - return static_cast(lhs.m_value.number_unsigned) op rhs.m_value.number_float; \ + return static_cast(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \ } \ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \ { \ - return lhs.m_value.number_float op static_cast(rhs.m_value.number_unsigned); \ + return lhs.m_data.m_value.number_float op static_cast(rhs.m_data.m_value.number_unsigned); \ } \ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \ { \ - return static_cast(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \ + return static_cast(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \ } \ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \ { \ - return lhs.m_value.number_integer op static_cast(rhs.m_value.number_unsigned); \ + return lhs.m_data.m_value.number_integer op static_cast(rhs.m_data.m_value.number_unsigned); \ } \ else if(compares_unordered(lhs, rhs))\ {\ @@ -22143,8 +22877,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // an operation is computed as an odd number of inverses of others static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept { - if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number()) - || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number())) + if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number()) + || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number())) { return true; } @@ -22645,7 +23379,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_HEDLEY_RETURNS_NON_NULL const char* type_name() const noexcept { - switch (m_type) + switch (m_data.m_type) { case value_t::null: return "null"; @@ -22675,11 +23409,38 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // member variables // ////////////////////// - /// the type of the current element - value_t m_type = value_t::null; + struct data + { + /// the type of the current element + value_t m_type = value_t::null; + + /// the value of the current element + json_value m_value = {}; - /// the value of the current element - json_value m_value = {}; + data(const value_t v) + : m_type(v), m_value(v) + { + } + + data(size_type cnt, const basic_json& val) + : m_type(value_t::array) + { + m_value.array = create(cnt, val); + } + + data() noexcept = default; + data(data&&) noexcept = default; + data(const data&) noexcept = delete; + data& operator=(data&&) noexcept = delete; + data& operator=(const data&) noexcept = delete; + + ~data() noexcept + { + m_value.destroy(m_type); + } + }; + + data m_data = {}; #if JSON_DIAGNOSTICS /// a pointer to a parent value (for debugging purposes) @@ -23112,7 +23873,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return ptr.get_checked(this); } - template + template::value, int> = 0> JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) reference at(const ::nlohmann::json_pointer& ptr) { @@ -23126,7 +23887,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return ptr.get_checked(this); } - template + template::value, int> = 0> JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) const_reference at(const ::nlohmann::json_pointer& ptr) const { @@ -23158,13 +23919,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @name JSON Patch functions /// @{ - /// @brief applies a JSON patch + /// @brief applies a JSON patch in-place without copying the object /// @sa https://json.nlohmann.me/api/basic_json/patch/ - basic_json patch(const basic_json& json_patch) const + void patch_inplace(const basic_json& json_patch) { - // make a working copy to apply the patch to - basic_json result = *this; - + basic_json& result = *this; // the valid JSON Patch operations enum class patch_operations {add, remove, replace, move, copy, test, invalid}; @@ -23209,7 +23968,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // make sure the top element of the pointer exists - json_pointer top_pointer = ptr.top(); + json_pointer const top_pointer = ptr.top(); if (top_pointer != ptr) { result.at(top_pointer); @@ -23218,9 +23977,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // get reference to parent of JSON pointer ptr const auto last_path = ptr.back(); ptr.pop_back(); - basic_json& parent = result[ptr]; + // parent must exist when performing patch add per RFC6902 specs + basic_json& parent = result.at(ptr); - switch (parent.m_type) + switch (parent.m_data.m_type) { case value_t::null: case value_t::object: @@ -23309,13 +24069,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec bool string_type) -> basic_json & { // find value - auto it = val.m_value.object->find(member); + auto it = val.m_data.m_value.object->find(member); // context-sensitive error message const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // check if desired value is present - if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) + if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) { // NOLINTNEXTLINE(performance-inefficient-string-concatenation) JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val)); @@ -23370,7 +24130,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec json_pointer from_ptr(from_path); // the "from" location must exist - use at() - basic_json v = result.at(from_ptr); + basic_json const v = result.at(from_ptr); // The move operation is functionally identical to a // "remove" operation on the "from" location, followed @@ -23387,7 +24147,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const json_pointer from_ptr(from_path); // the "from" location must exist - use at() - basic_json v = result.at(from_ptr); + basic_json const v = result.at(from_ptr); // The copy is functionally identical to an "add" // operation at the target location using the value @@ -23428,7 +24188,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } } } + } + /// @brief applies a JSON patch to a copy of the current object + /// @sa https://json.nlohmann.me/api/basic_json/patch/ + basic_json patch(const basic_json& json_patch) const + { + basic_json result = *this; + result.patch_inplace(json_patch); return result; } @@ -23566,7 +24333,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return result; } - /// @} //////////////////////////////// @@ -23615,7 +24381,30 @@ std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) return j.dump(); } -} // namespace nlohmann +inline namespace literals +{ +inline namespace json_literals +{ + +/// @brief user-defined string literal for JSON values +/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ +JSON_HEDLEY_NON_NULL(1) +inline nlohmann::json operator "" _json(const char* s, std::size_t n) +{ + return nlohmann::json::parse(s, s + n); +} + +/// @brief user-defined string literal for JSON pointer +/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ +JSON_HEDLEY_NON_NULL(1) +inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) +{ + return nlohmann::json::json_pointer(std::string(s, n)); +} + +} // namespace json_literals +} // namespace literals +NLOHMANN_JSON_NAMESPACE_END /////////////////////// // nonmember support // @@ -23627,7 +24416,7 @@ namespace std // NOLINT(cert-dcl58-cpp) /// @brief hash value for JSON objects /// @sa https://json.nlohmann.me/api/basic_json/std_hash/ NLOHMANN_BASIC_JSON_TPL_DECLARATION -struct hash +struct hash // NOLINT(cert-dcl58-cpp) { std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const { @@ -23660,7 +24449,7 @@ struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', /// @brief exchanges the values of two JSON objects /// @sa https://json.nlohmann.me/api/basic_json/std_swap/ NLOHMANN_BASIC_JSON_TPL_DECLARATION -inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name) +inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible::value&& // NOLINT(misc-redundant-expression) is_nothrow_move_assignable::value) { @@ -23669,25 +24458,22 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC #endif -} // namespace std - -/// @brief user-defined string literal for JSON values -/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ -JSON_HEDLEY_NON_NULL(1) -inline nlohmann::json operator "" _json(const char* s, std::size_t n) -{ - return nlohmann::json::parse(s, s + n); -} +} // namespace std -/// @brief user-defined string literal for JSON pointer -/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ -JSON_HEDLEY_NON_NULL(1) -inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) -{ - return nlohmann::json::json_pointer(std::string(s, n)); -} +#if JSON_USE_GLOBAL_UDLS + using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) + using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) +#endif // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + // restore clang diagnostic settings @@ -23707,6 +24493,7 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #undef JSON_INLINE_VARIABLE #undef JSON_NO_UNIQUE_ADDRESS #undef JSON_DISABLE_ENUM_SERIALIZATION +#undef JSON_USE_GLOBAL_UDLS #ifndef JSON_TEST_KEEP_MACROS #undef JSON_CATCH @@ -23723,6 +24510,14 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #endif // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #undef JSON_HEDLEY_ALWAYS_INLINE From 7f1c6e13b525aec7775dc1d994cdc4ebe2c95b62 Mon Sep 17 00:00:00 2001 From: Max Qian <64824374+AstroAir@users.noreply.github.com> Date: Mon, 14 Aug 2023 11:51:41 +0000 Subject: [PATCH 3/4] Fix error in Linux --- libs/indicore/sharedblob.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/libs/indicore/sharedblob.c b/libs/indicore/sharedblob.c index 52bd43c29a..91d999e088 100644 --- a/libs/indicore/sharedblob.c +++ b/libs/indicore/sharedblob.c @@ -93,33 +93,20 @@ void* IDSharedBlobAlloc(size_t size) { sb->hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, sb->allocated, NULL); if (sb->hMapObject == NULL) { - // 错误处理逻辑 goto ERROR_LABEL; } sb->mapstart = MapViewOfFile(sb->hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, sb->allocated); if (sb->mapstart == NULL) { - // 错误处理逻辑 goto ERROR_LABEL; } #else - sb->fd = shm_open("/mysharedmem", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); - if (sb->fd == -1) { - // 错误处理逻辑 - goto ERROR_LABEL; - } - int ret = ftruncate(sb->fd, sb->allocated); - if (ret == -1) { - // 错误处理逻辑 - goto ERROR_LABEL; - } + if (ret == -1) goto ERROR_LABEL; - sb->mapstart = mmap(NULL, sb->allocated, PROT_READ | PROT_WRITE, MAP_SHARED, sb->fd, 0); - if (sb->mapstart == MAP_FAILED) { - // 错误处理逻辑 - goto ERROR_LABEL; - } + // FIXME: try to map far more than sb->allocated, to allow efficient mremap + sb->mapstart = mmap(0, sb->allocated, PROT_READ | PROT_WRITE, MAP_SHARED, sb->fd, 0); + if (sb->mapstart == MAP_FAILED) goto ERROR_LABEL; #endif sharedBufferAdd(sb); From 65ea27a2b650190956a556ec56f106a4786432c7 Mon Sep 17 00:00:00 2001 From: Max Qian <64824374+AstroAir@users.noreply.github.com> Date: Mon, 14 Aug 2023 11:57:13 +0000 Subject: [PATCH 4/4] Sorry for my mistake --- README.md | 29 +++++++++++++++++++++++++++++ tools/getINDIproperty.c | 3 ++- tools/setINDIproperty.c | 2 ++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index da92e6b52e..6548e77f64 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,35 @@ sudo apt-get install -y \ libtheora-dev ``` +On Windows + +Download https://github.com/msys2/msys2-installer/releases/download/2023-07-18/msys2-x86_64-20230718.exe + +``` +pacman -Syu # Update all of the packages +pacman -S mingw-w64-x86_64-toolchain # Install g++ toolchain +pacman -S mingw-w64-x86_64-cmake # Install Cmake +pacman -S mingw-w64-x86_64-zlib +pacman -S mingw-w64-x86_64-cfitsio +pacman -S mingw-w64-x86_64-libnova +pacman -S mingw-w64-x86_64-libusb +pacman -S mingw-w64-x86_64-fftw +pacman -S mingw-w64-x86_64-libxisf +pacman -S mingw-w64-x86_64-rtl-sdr + +# Install Libev +# Download sources from http://dist.schmorp.de/libev/Attic/ +pacman -S autoconf +pacman -S automake +pacman -S libtool +pacman -S make +sh autogen.sh +./configure +make +make -j4 +make install +``` + ## XISF Support To enable [XISF format](https://pixinsight.com/xisf/) support in INDI, you need to build or install [libxisf](https://gitea.nouspiro.space/nou/libXISF) package. diff --git a/tools/getINDIproperty.c b/tools/getINDIproperty.c index d76e071fb8..c3550a2f54 100644 --- a/tools/getINDIproperty.c +++ b/tools/getINDIproperty.c @@ -369,6 +369,7 @@ static void getprops() fprintf(stderr, "Queried properties from %s\n", onedev ? onedev : "*"); } +#ifdef _WIN32 #define TIMEOUT_MS 5000 static void CALLBACK onTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) @@ -376,7 +377,7 @@ static void CALLBACK onTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTim printf("Timer expired!\n"); exit(0); } - +#endif /* listen for INDI traffic on svrrfp. * print matching srchs[] and return when see all. diff --git a/tools/setINDIproperty.c b/tools/setINDIproperty.c index 1c35b8fcd0..775b364be4 100644 --- a/tools/setINDIproperty.c +++ b/tools/setINDIproperty.c @@ -358,6 +358,7 @@ static void openINDIServer(FILE **rfpp, FILE **wfpp) *wfpp = fdopen(sockfd, "w"); } +#ifdef _WIN32 #define TIMEOUT_MS 5000 static void CALLBACK onTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) @@ -365,6 +366,7 @@ static void CALLBACK onTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTim printf("Timer expired!\n"); exit(0); } +#endif /* listen for property reports, send new sets if match */ static void listenINDI(FILE *rfp, FILE *wfp)